﻿# Deploying ServiceControl Error instances using Containers


ServiceControl Error instances are deployed using the [`particular/servicecontrol` image](https://hub.docker.com/r/particular/servicecontrol), as shown in this minimal example using `docker run`, assuming a RabbitMQ container named `rabbitmq`:

```shell
docker run -d --name servicecontrol -p 33333:33333 \
    -e TRANSPORTTYPE=RabbitMQ.QuorumConventionalRouting \
    -e CONNECTIONSTRING="host=rabbitmq" \
    -e RAVENDB_CONNECTIONSTRING="http://servicecontrol-db:8080" \
    -e REMOTEINSTANCES='[{"api_uri":"http://audit:44444/api"}]' \
    -e ENABLEINTEGRATEDSERVICEPULSE="true" \
    particular/servicecontrol:latest
```

> [!TIP]
> For examples of ServiceControl containers used together, including Docker Compose and Kubernetes using a Helm chart, see the [Platform Container Examples repository](https://github.com/Particular/PlatformContainerExamples).

## Initial setup

Before running the container image normally, it must run in setup mode to create the required message queues and perform upgrade tasks.

The container image will run in setup mode by adding the `--setup` argument. For example:

```shell
# Using docker run
docker run --rm {OPTIONS} particular/servicecontrol --setup
```

Setup mode may require different settings, such as a different transport connection string with permissions to create queues.

After setup is complete, the container will exit, and the `--rm` (or equivalent) option can be used to automatically remove it.

The setup process should be repeated any time the container is [updated to a new version](#upgrading).

### Simplified setup

Instead of running `--setup` as a separate container, the setup and run operations can be combined using the `--setup-and-run` argument:

```shell
# Using docker run
docker run {OPTIONS} particular/servicecontrol --setup-and-run
```

The `--setup-and-run` argument runs the setup process when the container starts, after which the application runs normally. This simplifies deployment by removing the need for a separate init container in environments where the setup process does not need different settings.

Using `--setup-and-run` removes the need to repeat a setup process when the container is updated to a new version.

## Required settings

The following environment settings are required to run a ServiceControl error instance.

### Transport type

_Environment variable:_ `TRANSPORTTYPE`

 Determines the message transport used to communicate with message endpoints. See [ServiceControl transport configuration](/servicecontrol/transports.md) for valid TransportType values.

 ### Transport connection string

_Environment variable:_ `CONNECTIONSTRING`

Provides the connection information to connect to the chosen transport. The form of this connection string is different for every message transport. See [ServiceControl transport support](/servicecontrol/transports.md) for more details on options available to each message transport.


### RavenDB connection string

_Environment variable:_ `RAVENDB_CONNECTIONSTRING`

Provides the URL to connect to the database container that stores the instance's data. The database container should be exclusive to the instance, and not shared by any other ServiceControl instances.

If the [storage requirements for the RavenDB container](/servicecontrol/ravendb/containers.md#required-settings) cannot be met by the container hosting infrastructure, especially in cloud-hosted environments, an externally-hosted and separately-licensed RavenDB instance can also be used starting with ServiceControl version 6.0.

In this case, the RavenDB Major.Minor version must match the version expected by ServiceControl as shown in this table:

<!-- This include file may be auto-generated in the future -->

| ServiceControl Versions | RavenDB Version |
|:-:|:-:|
| `6.*` | `6.2` |

#### RavenDB client certificate

_Added in ServiceControl version 6.3.0_

When connecting to an external RavenDB instance, the RavenDB client certificate can be specified using a combination of settings, which are attempted in this order:

1. An environment variable `RAVENDB_CLIENTCERTIFICATEBASE64` can be used to supply the client certificate as a Base64-encoded string.
2. An environment variable `RAVENDB_CLIENTCERTIFICATEPATH` can be used to identify the local path to a certificate that has added to the container via a mounted volume.
3. The app will attempt to load the certificate from `/app/raven-client-certificate.pfx`.
4. The app will attempt to access the database without a client certificate.

In any of the above cases, the certificate can be password-protected, in which case the password can be supplied using the `RAVENDB_CLIENTCERTIFICATEPASSWORD` environment variable.

### Remote instances

_Environment variable:_ `REMOTEINSTANCES`

A JSON structure that provides URLs for the Error instance to access any [remote audit instances](/servicecontrol/servicecontrol-instances/remotes.md). When requesting audit data via the ServiceControl API, the Error instance will communicate with each remote audit instance in a scatter-gather pattern, then return the combined results. The URLs must be accessible directly by the Error instance, not constructed to be accessible from an external browser.

### Enable integrated ServicePulse

_Environment variable:_ `ENABLEINTEGRATEDSERVICEPULSE`

A boolean value specifying whether to enable the [integrated ServicePulse](/servicecontrol/servicecontrol-instances/integrated-servicepulse.md) for this Error instance.

### License

_Environment variable:_ `PARTICULARSOFTWARE_LICENSE`

The Particular Software license, which is most easily provided to a container [as an environment variable](/nservicebus/licensing/index.md#license-management-environment-variable). The environment variable should contain the full multi-line contents of the license file.

A license file can also be volume-mounted to the container in the [machine-wide license location for Linux](/nservicebus/licensing/index.md#license-management-machine-wide-license-location):

```shell
-v license.xml:/usr/share/ParticularSoftware/license.xml
```

## Ports

`33333` is the canonical port exposed by the error instance API within the container, though this port can be mapped to any desired external port.

## Volumes

The Error instance is stateless and does not require any mounted volumes.

## Additional settings

Additional optional settings are documented in [Error Instance Configuration Settings](/servicecontrol/servicecontrol-instances/configuration.md), which describes all available settings, allowed values, and the environment variable keys used to configure the container.

When using tools such as Docker Compose that share environment information across many containers, the `SERVICECONTROL_` prefix can be dropped from an environment variable name, and the value will still be understood by the container. This facilitates sharing values such as `TRANSPORTTYPE` when all instances will be configured with the same values.

In the event of a naming collision, a fully qualified key such as `SERVICECONTROL_TRANSPORTTYPE` will be preferred over the shared `TRANSPORTTYPE` variant.

Not all settings are relevant to error instances running in a container. For example, HTTP hostname and port use standard values inside the container, and are mapped to real hosts and ports by infrastructure external to the container. Be sure to carefully review the documentation for each configuration setting to ensure it is relevant in a container context.

## Upgrading

A ServiceControl error instance is upgraded by removing the container for the old version and replacing it with a container built using the new version. However, the container should be run in [setup mode](#initial-setup) each time it is upgraded. For example:

```shell
docker stop error
docker rm error
docker pull particular/servicecontrol:latest
docker run -rm {OPTIONS} particular/servicecontrol:latest --setup
docker run -d {OPTIONS} particular/servicecontrol:latest
```

Note that Docker can cache the `latest` tag as well as the major/minor tags (such as `5` or `5.3`) unless the tag is pulled again. To be certain, use the full version tag.
