Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Running ServiceControl in containers

Docker images for ServiceControl exist on Docker Hub under the Particular organization. These can be used to run ServiceControl in Docker containers. These Docker images are only available for Windows due to ServiceControl's current dependency on Windows ESENT storage.

ServiceControl cannot perform a graceful shutdown which can result in manual intervention to repair the underlying datastore. The base Windows operating system images do not support notifying the application that it is being shut down when running docker stop.

Containers overview

ServiceControl is split into multiple docker images for each instance type. These are:

  • The error instance
  • The audit instance
  • The monitoring instance

The images for each of these containers are further split into an init container and a runtime container per transport.

Containerization support

The following table mentions which containerization technology is currently supported for running a production system.

EnvironmentSupportedNote
Docker for WindowsYes
Docker (for Linux)NoServiceControl cannot run in Linux.
Azure Container Services (ACS)NoWorks, but does not support persistent volumes for durable storage
Azure Kubernetes Services (AKS)NoSupports minimum of Windows Server 2019-based images
Amazon Elastic Container Services (ECS)NoUntested, guidance mentions AMIs available for Windows 2016
Amazon Elastic Kubernetes Service (EKS)NoEKS only supports Windows 2019
There is work in progress to enable ServiceControl to run in Linux containers. The details of the work are available on the GitHub issue.

Init containers

The init containers are used to create or upgrade the infrastructure required for ServiceControl. They are based on the Kubernetes init containers. Once the init container has been run, it will shut down and the runtime container can be run. The runtime container uses the infrastructure that has been created by the init container and will fail if the init container is not run.

The init containers are similar to installing all ServiceControl service types (regular, error, and monitoring) via the ServiceControl Management Utility or the Powershell Cmdlets. This includes creating the database and the queues that ServiceControl uses. The runtime containers are similar to starting the corresponding Windows Services.

Init containers are identical to the corresponding runtime image but with added entry point arguments (--setup). It is also possible to use the runtime image, override the entry point and add this argument to achieve the same goal.

Transports

Each supported transport and topology for ServiceControl has further been broken down into its own set of images. The following transport and topologies are available on Docker Hub:

Parameters

All parameters that the ServiceControl instance supports can be provided by passing the parameter as an environment variable. E.g.

-e "ServiceControl/Port=12345"

The most common parameters used are likely to be:

  • ServiceControl/ConnectionString
  • ServiceControl/LicenseText
  • ServiceControl.Audit/ConnectionString
  • ServiceControl.Audit/LicenseText
  • ServiceControl.Audit/ServiceControlQueueAddress
  • ServiceControl/RemoteInstances
  • Monitoring/ConnectionString
  • Monitoring/LicenseText
For hosting in Azure Container Instances parameter names are supported that use only underscores, e.g. ServiceControl_Audit_LicenseText

These parameters can also be added by using a standard Docker environment file. Each parameter has its line and does not need to be enclosed by quotes. It can then be used by Docker as follows:

docker run --env-file servicecontrol.env [dockerimage]

An example of the servicecontrol.env file:

# License text
ServiceControl/LicenseText=<?xml version="1.0" encoding="utf-8"?><license id="..."></license>

# Connection string
ServiceControl/ConnectionString=data source=[server],1433; user id=username; password=[password]; Initial Catalog=servicecontrol

# Remote audit instances
ServiceControl/RemoteInstances=[{'api_uri':'http://[hostname]:44444/api'}]

Running ServiceControl using Docker

This section uses the SqlServer transport as an example of how to run ServiceControl using Docker. The same steps apply to other transports.

Each instance type of ServiceControl has a distinct init and runtime container.

  • The error instance of ServiceControl can be run as stand-alone
  • The audit instance needs an error instance to be running too
  • The monitoring instance can be run as a stand-alone

Error instances

The first step is to create the required infrastructure using the init container:

docker run -e "ServiceControl/ConnectionString=[connectionstring]" -e 'ServiceControl/LicenseText=[licensecontents]' -v d:/servicecontrol/:c:/data/ -d [imagename]

The license contents parameter is the contents of the license file with any " characters encoded as \".

The init container will run and shut down once the required queues and database have been created.

The runtime instance of ServiceControl can now be run:

docker run -e "ServiceControl/ConnectionString=[connectionstring]" -e 'ServiceControl/LicenseText=[licensecontents]' -v d:/servicecontrol/:c:/data/ -p 33333:33333 -d [imagename]

ServiceControl can now be accessed over port 33333.

All supported parameters for ServiceControl Error can be specified via environment variables.

Audit instances

A ServiceControl audit instance can be configured once a ServiceControl error instance is running.

The first step is to create the required infrastructure by executing the audit.init container:

docker run -e "ServiceControl.Audit/ConnectionString=[connectionstring]" -e 'ServiceControl.Audit/LicenseText=[licensecontents]' -v d:/servicecontrol.audit/:c:/data/ -d [imagename]

The license contents parameter is the contents of the license file with any " characters encoded as \".

The init container will run and shut down once the required queues and database have been created.

The runtime instance of ServiceControl Audit can now be run:

docker run -e "ServiceControl.Audit/ConnectionString=[connectionstring]" -e 'ServiceControl.Audit/LicenseText=[licensecontents]' -e 'ServiceControl.Audit/ServiceControlQueueAddress=Particular.ServiceControl' -v d:/servicecontrol.audit/:c:/data/ -p 44444:44444 -d [imagename]

The ServiceControl.Audit/ServiceControlQueueAddress environment variable must point to the queue of the error instance of ServiceControl.

To complete the setup, the error instance of ServiceControl must be stopped and run with an additional environment variable - specifically -e "ServiceControl/RemoteInstances=[{'api_uri':'http://172.28.XXX.XXX:44444/api'}]" which tells the error instance how to communicate with the audit instance.

ServiceControl can now be accessed over port 44444.

All supported parameters for ServiceControl Audit can be specified via environment variables.

Monitoring Instances

Monitoring instances can be run standalone and therefore only need the init container to be run and then the runtime container.

docker run -e "Monitoring/ConnectionString=[connectionstring]" -e 'Monitoring/LicenseText=[licensecontents]' -v d:/servicecontrol.monitoring/:c:/data/ -d [imagename]

The init container will run and shut down once the required queues and database have been created.

The runtime instance of ServiceControl Monitoring can now be run:

docker run -e "Monitoring/ConnectionString=[connectionstring]" -e 'Monitoring/LicenseText=[licensecontents]' -v d:/servicecontrol.monitoring/:c:/data/ -p 33633:33633 -d [imagename]

All supported parameters for ServiceControl Monitoring can be specified via environment variables.

Volume mappings

A general practice with containers is that no data is persisted inside a container, but rather outside the container on either the host machine, database or something similar. This makes it easier to backup data, share data among containers and more importantly, not lose the data when the container is updated to a later version. Storing files outside of the container can be achieved with volume mappings, or with folder mappings for Windows containers.

Volume mappings can be used with ServiceControl for configuration files, storing log files and possibly reading a license file. More information on data storage can be found on the Docker website.

Configuration and Logging

Every image has a folder in c:\data\ that can be mapped to a folder outside of the container.

docker run -v d:\servicecontrol\:c:\data\ [imagename]

As a result, that container will write both logfiles and its database into that folder in respectively the Logs and DB folders. Another option is to map each folder specifically, for more control over their locations and divide them over separate drives, for example:

docker run -v d:\servicecontroldatabase\:c:\data\DB\ -v e:\logs\servicecontrol\:c:\data\logs\ [imagename]

License file

The license file can be provided via an environment variable on the command line or via an environment file. Another option is to map the folder where ServiceControl will look for the license file.

docker run -v d:\servicecontrol\license\:c:\ProgramData\ParticularSoftware\ [imagename]

As the above command shows, ServiceControl will look for the license file in OS-specific folders as can be found in the license documentation.

RavenDB Maintenance Mode

If maintenance is required on the embedded RavenDb database of ServiceControl, this can be enabled on Docker by

  1. Stopping the ServiceControl container
  2. Starting a new container by adding the --maintenance --portable parameters and adding an additional port mapping for port 33334.
docker run --interactive --tty --detach -v d:\servicecontrol\:c:\data\ [imagename] --maintenance --portable

Interactive shell

To run tools like ESENTUTL to perform low-level maintenance tasks like compacting the RavenDB database the container can be started in interactive mode with an overridden entry point.

Docker for Windows:

docker run --interactive --tty -v d:\servicecontrol\:c:\data --entrypoint cmd [imagename]