Getting Started
Architecture
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Docker Container Host

Hosting endpoints in Docker containers provides self-contained artifacts that are deployable 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 in the ParticularTemplates package. The project that is created will have the required endpoint setup infrastructure in addition to the Dockerfile needed to create 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 must 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);
    }
}

There is also a Stop() method that can hold any operations required to gracefully shutdown 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);
    }
}

There are also methods that handle endpoint failures and exceptions, which can be modified to fit the needs 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 have a license.xml file included in it. A placeholder for this file is created when the template is used to create a new endpoint. This file must be replaced with a valid license.xml file prior to building the Docker container.

An endpoint running in Docker will look for the license.xml file in the same locations as it would in any other hosting situation. By default, a project created using the dotnet new templates will put the license.xml file in the correct location in a 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/dotnet:2.1-runtime image. Once built, the container image contains the compiled artifacts of the endpoint project, and it will launch that endpoint when the container is run.

To compile the endpoint and create the Docker image, run the following command:

docker build -f Dockerfile -t MyEndpoint ./..

Building the container will compile and publish the endpoint in Release mode.

RUN dotnet publish -c Release -o /app

The compiled endpoint is added to the docker image, the endpoint is configured to start when the container is run, and the container is built.

COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyEndpoint.dll"]

Program.cs

The Program.cs file contains the infrastructure required to successfully start an endpoint and gracefully shut it down when the docker stop command has been issued.

Samples

Related Articles