Hosting endpoints in Docker containers provides self-contained artifacts that can be deployed to multiple environments or managed by orchestration technologies such as Kubernetes. To create and host an endpoint in a Docker container, use the dotnet new
template from the ParticularTemplates package. The generated project includes all required endpoint setup infrastructure, along with a Dockerfile
needed to build and deploy a container hosting one endpoint.
Template overview
The nsbdockercontainer
template creates a project that contains all of the files necessary to build an endpoint that can be deployed to Docker.
Host.cs
The endpoint’s configuration should be added to the Start()
method:
public async Task Start()
{
try
{
// TODO: consider moving common endpoint configuration into a shared project
// for use by all endpoints in the system
var endpointConfiguration = new EndpointConfiguration(EndpointName);
// TODO: ensure the most appropriate serializer is chosen
// https://docs.particular.net/nservicebus/serialization/
endpointConfiguration.UseSerialization<NewtonsoftJsonSerializer>();
endpointConfiguration.DefineCriticalErrorAction(OnCriticalError);
// TODO: remove this condition after choosing a transport, persistence and deployment method suitable for production
if (Environment.UserInteractive && Debugger.IsAttached)
{
// TODO: choose a durable transport for production
// https://docs.particular.net/transports/
var transportExtensions = endpointConfiguration.UseTransport<LearningTransport>();
// TODO: choose a durable persistence for production
// https://docs.particular.net/persistence/
endpointConfiguration.UsePersistence<LearningPersistence>();
// TODO: create a script for deployment to production
endpointConfiguration.EnableInstallers();
}
// TODO: replace the license.xml file with a valid license file
// TODO: perform any further start up operations before or after starting the endpoint
endpoint = await Endpoint.Start(endpointConfiguration);
}
catch (Exception ex)
{
FailFast("Failed to start.", ex);
}
}
A corresponding Stop()
method is available for implementing any operations required to gracefully shut down the endpoint:
public async Task Stop()
{
try
{
// TODO: perform any further shutdown operations before or after stopping the endpoint
await endpoint?.Stop();
}
catch (Exception ex)
{
FailFast("Failed to stop correctly.", ex);
}
}
Additional methods are provided to handle endpoint failures and exceptions. These can be customized as needed to fit the specific requirements of the endpoint:
async Task OnCriticalError(ICriticalErrorContext context)
{
// TODO: decide if stopping the endpoint and exiting the process is the best response to a critical error
// https://docs.particular.net/nservicebus/hosting/critical-errors
// and consider setting up service recovery
// https://docs.particular.net/nservicebus/hosting/windows-service#installation-restart-recovery
try
{
await context.Stop();
}
finally
{
FailFast($"Critical error, shutting down: {context.Error}", context.Exception);
}
}
void FailFast(string message, Exception exception)
{
try
{
log.Fatal(message, exception);
// TODO: when using an external logging framework it is important to flush any pending entries prior to calling FailFast
// https://docs.particular.net/nservicebus/hosting/critical-errors#when-to-override-the-default-critical-error-action
}
finally
{
Environment.FailFast(message, exception);
}
}
license.xml
Each Docker container must include a license.
file. A placeholder for this file is created when the template is used to generate a new endpoint project. Before building the Docker container, this placeholder must be replaced with a valid license.
.
An endpoint running in Docker will look for the license.
file in the same locations as it would in any other hosting scenario. By default, the dotnet new
template places the license.
in the correct location within the Docker image.
Dockerfile
This file contains the instructions for compiling the endpoint and creating the Docker image.
The endpoint will be hosted in a container that is based on the microsoft/
image. After the image is built, it contains the compiled artifacts of the endpoint project and is configured to launch the endpoint when the container runs.
To compile the endpoint and build the Docker image, run the following command:
docker build -f Dockerfile -t MyEndpoint ./..
This step compiles and publishes the endpoint in Release
mode:
RUN dotnet publish -c Release -o /app
The compiled endpoint is then added to the Docker image, and the container is configured to start the endpoint when it runs:
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyEndpoint.dll"]
Program.cs
The Program.
file contains the infrastructure required to successfully start an endpoint and gracefully shut it down when the docker stop
command has been issued.