﻿# Octopus Server Linux Container

Running Octopus Server inside a container lets you avoid installing Octopus directly on top of your infrastructure and makes getting up and running with Octopus as simple as a one line command. Upgrading to the latest version of Octopus is just a matter of running a new container with the new image version.

We are confident in the Octopus Server Linux Container's reliability and performance. [Octopus Cloud](/docs/octopus-cloud) runs the Octopus Server Linux Container in AKS clusters in Azure.  But to use the Octopus Server Linux Container in Octopus Cloud, we had to make some design decisions and level up our knowledge about Docker concepts.  

We recommend the use of the Octopus Server Linux Container if you are okay with **all** of these conditions:

- You are familiar with Docker concepts, specifically around debugging containers, volume mounting, and networking.
- You are comfortable with one of the underlying hosting technologies for Docker containers; Kubernetes, ACS, ECS, AKS, EKS, or Docker itself.
- You understand Octopus Deploy is a stateful, not a stateless application, requiring additional monitoring.

We publish `linux/amd64` Docker images for each Octopus Server release and they are available on [DockerHub](https://hub.docker.com/r/octopusdeploy/).

:::figure
![Introducing the Octopus Server Linux Docker image](/docs/img/installation/octopus-server-linux-container/octopus-linux-docker-image.png)
:::

This page describes how to run Octopus Server in the Linux Container.

**Note:** When using Linux containers on a Windows machine, please ensure you have [switched to Linux Containers](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers).

## Getting started

Although there are a few different configuration options, the following is a simple example of starting the  Octopus Server Linux container:

```bash
docker run --interactive --detach --name OctopusDeploy --publish 1322:8080 --env ACCEPT_EULA="Y" --env DB_CONNECTION_STRING="..." octopusdeploy/octopusdeploy
```

- We run in detached mode with `--detach` to allow the container to run in the background.
- The `--interactive` argument ensures that `STDIN` is kept open, which is required since this is what the running `Octopus.Server.exe` process is waiting on to close.
- Setting `--name OctopusServer` gives us an easy-to-remember name for this container. This is optional, but we recommend you provide a name that is meaningful to you, as that will make it easier to perform actions on the container later if necessary.
- Using `--publish 1322:8080` maps the *container port* `8080` to `1322` on the host so that the Octopus instance is accessible outside this server.
- To set the connection string we provide an *environment variable* `DB_CONNECTION_STRING` (this can be a local or external database).

In this example, we run the image `octopusdeploy/octopusdeploy` without an explicit tag, running the `latest` version of Octopus Server that's been published to DockerHub.

## Running Octopus Server in a Container

This section walks through some of the different ways you can run the Octopus Server Linux Container, from `docker compose` to using a full orchestration service such as Kubernetes:

- [Octopus Server Container with Docker Compose](/docs/installation/octopus-server-linux-container/docker-compose-linux)
- [Octopus Server Container with systemd](/docs/installation/octopus-server-linux-container/systemd-service-definition)
- [Octopus Server Container in Kubernetes](/docs/installation/octopus-server-linux-container/octopus-in-kubernetes)

## Migration

You may already have Octopus Server running on Windows Server or in a Windows container you wish to run in a Linux Container. This section walks through the different options and considerations for migrating to an Octopus Server Linux Container.

- [Migrate to Octopus Server Linux Container from Windows Server](/docs/installation/octopus-server-linux-container/migration/migrate-to-server-container-linux-from-windows-server)
- [Migrate to Octopus Server Linux Container from Windows Container](/docs/installation/octopus-server-linux-container/migration/migrate-to-server-container-linux-from-windows-container)

## Configuration

:::div{.hint}
Support for authentication providers differs depending on how you host Octopus Server. Please see our [authentication provider compatibility section](/docs/security/authentication/auth-provider-compatibility) to ensure any existing authentication provider is supported when running Octopus in a Linux Container.
:::

When running an Octopus Server Image, you can supply the following values to configure the running Octopus Server instance.

### Master Key

If you do not specify a master key when Octopus is first run, Octopus will generate one for you, which you must pass as the `MASTER_KEY` environment variable with each subsequent run. However, it is also possible to create your own master key for Octopus to use when configuring the database.

Master keys must be a 128 bit string encoded in base 64. You can generate a random string to use as the master key with the command:

```bash
openssl rand 16 | base64
```

### Environment variables

Read the Docker [docs](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) about setting environment variables.

|Name|Description|
|--|--|
|**DB_CONNECTION_STRING**|Connection string to the database to use|
|**MASTER_KEY**|The Master Key to connect to an existing database. If not supplied, and the database does not exist, it will generate a new one. The Master Key is mandatory if the database exists.|
|**OCTOPUS_SERVER_BASE64_LICENSE**|Your license key for Octopus Deploy. If left empty, it will try to create a free license key for use|
|**ADMIN_USERNAME**|The admin user to create for the Octopus Server|
|**ADMIN_PASSWORD**|The password for the admin user for the Octopus Server|
|**ADMIN_EMAIL**|The email associated with the admin user account|
|**TASK_CAP**|Sets the task cap for this node. If not specified, the default is 5.|
|**DISABLE_DIND**|The Linux image will by default attempt to run Docker-in-Docker to support [execution containers for workers](/docs/projects/steps/execution-containers-for-workers). This requires the image to be launched with [privileged permissions](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities). Setting `DISABLE_DIND` to `Y` prevents Docker-in-Docker from being run when the container is booted.|
|**CLUSTER_SHARED_CONFIG**|Sets how Octopus stores the files that every node in a cluster needs to share. Valid values are `CLUSTER_SHARED`, `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED`, and `SEPARATE_VOLUMES`, and they are not case-sensitive. Any other value stops the container with an error. If not set, a new installation uses the `/repository`, `/artifacts`, `/taskLogs`, and `/eventExports` volumes, and an existing installation keeps its current paths. See [cluster shared configuration](#cluster-shared-configuration).|
|**USE_EXECUTIONS_CLUSTER_SHARED**|Set to `True` to store transient execution data (the `SharedPackageCache`, `DataBus`, and `DataStreams` folders) in the `/executionsClusterShared` volume instead of in `/clusterShared`. The value is not case-sensitive. Only valid when `CLUSTER_SHARED_CONFIG` is `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED` or `CLUSTER_SHARED`. With any other `CLUSTER_SHARED_CONFIG` value, including not set, the container stops with an error. See [cluster shared configuration](#cluster-shared-configuration) for why you might use this.|
|**OCTOPUS_MULTI_NODE_POLLING_TENTACLES_REDIS_CONNECTION_STRING**|The Redis connection string that turns on [multi-node support for Polling Tentacles](/docs/administration/high-availability/polling-tentacles-with-ha/multi-node-polling-tentacles). Requires `CLUSTER_SHARED_CONFIG` to be `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED` or `CLUSTER_SHARED`.|

### Exposed container ports

Read Docker [docs](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose) about exposing ports.

|Port|Description|
|--|--|
|**8080**|Port for API and HTTP portal|
|**443**|SSL Port for API and HTTP portal|
|**10943**|Port for Polling Tentacles to contact the server|
|**8443**|Port for gRPC clients to contact the server|

### Volume mounts

Read the Docker [docs](https://docs.docker.com/engine/reference/commandline/run/#mount-volume--v---read-only) about mounting volumes.

| Name     | Description | Mount source |
| ------------- | ------- | ------- |
| **/import** | Imports from this folder if [Octopus Migrator](/docs/administration/octopus.migrator.exe-command-line) metadata.json exists, then migrator `Import` takes place on startup | Host filesystem or container |
| **/repository** | Package path for the built-in package repository | Shared storage |
| **/artifacts** | Path where artifacts are stored | Shared storage |
| **/taskLogs** | Path where task logs are stored | Shared storage |
| **/eventExports** | Path where event audit logs are exported | Shared storage |
| **/cache** | Path where cached files e.g., signature and delta files (used for package acquisition), are stored | Host filesystem or container |
| **/clusterShared** | Cluster shared directory. Used when `CLUSTER_SHARED_CONFIG` is `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED` or `CLUSTER_SHARED` | Shared storage |
| **/executionsClusterShared** | Transient execution data, in the `SharedPackageCache`, `DataBus`, and `DataStreams` folders. Used when `USE_EXECUTIONS_CLUSTER_SHARED` is `True` | Shared storage |

:::div{.hint}
**Note:** We recommend using shared storage when mounting the volumes for files that must be shared between multiple octopus container nodes, e.g., artifacts, packages, task logs, and event exports.
:::

### Cluster shared configuration \{#cluster-shared-configuration}

The `CLUSTER_SHARED_CONFIG` environment variable sets which volumes Octopus uses for the files that every node needs to share. When it is set, the container applies it each time it starts, not only on first start, so you can change it on an existing installation.

The values are not case-sensitive.

| Value | When to use it | Volumes used |
| --- | --- | --- |
| `CLUSTER_SHARED` | Recommended for new installations. | A single `/clusterShared` volume: packages in `/clusterShared/Packages`, artifacts in `/clusterShared/Artifacts`, task logs in `/clusterShared/TaskLogs`, event exports in `/clusterShared/EventExports`, imports in `/clusterShared/Imports`, telemetry in `/clusterShared/Telemetry`, and transient execution data in `/clusterShared/SharedPackageCache`, `/clusterShared/DataBus`, and `/clusterShared/DataStreams`. The `/repository`, `/artifacts`, `/taskLogs`, and `/eventExports` volumes are not used. |
| `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED` | Recommended if you are moving an existing installation to multiple nodes and want to keep your existing volumes, rather than moving their contents into a single volume. | `/repository`, `/artifacts`, `/taskLogs`, and `/eventExports`, plus `/clusterShared`. Octopus stores transient execution data in `/clusterShared` instead of in `/cache` and the Octopus home directory: the package cache in `/clusterShared/SharedPackageCache`, DataBus in `/clusterShared/DataBus`, and DataStreams in `/clusterShared/DataStreams`. Imports and telemetry are also stored in `/clusterShared/Imports` and `/clusterShared/Telemetry`. |
| `SEPARATE_VOLUMES` | To go back to the layout without a cluster shared directory, for example if you tried one of the other values and want to undo it. | `/repository`, `/artifacts`, `/taskLogs`, and `/eventExports`, with no cluster shared directory. Any cluster shared or executions cluster shared directory configured previously is removed. Multi-node support for Polling Tentacles cannot be used with this value. |
| Not set | To keep the current configuration. | On a new installation, `/repository`, `/artifacts`, `/taskLogs`, and `/eventExports`. On an existing installation, the container does not change any paths, so whatever was configured previously, including any cluster shared directory, is kept. For example, if you used `CLUSTER_SHARED` and then remove the variable, Octopus keeps using `/clusterShared`. |

In every mode, `/cache` is still used as the node's own cache directory.

Switching an existing installation to `CLUSTER_SHARED` does not move existing packages, artifacts, or logs into `/clusterShared`, so Octopus stops finding them unless you move them yourself. To add a cluster shared directory to an existing installation, use `SEPARATE_VOLUMES_WITH_CLUSTER_SHARED`.

To keep transient execution data on different storage, such as faster storage that does not need to be backed up, set `USE_EXECUTIONS_CLUSTER_SHARED` to `True` and mount `/executionsClusterShared` on storage every node can read and write. Octopus then uses the same `SharedPackageCache`, `DataBus`, and `DataStreams` folders in `/executionsClusterShared`.

[Multi-node support for Polling Tentacles](/docs/administration/high-availability/polling-tentacles-with-ha/multi-node-polling-tentacles) needs a cluster shared directory. If `OCTOPUS_MULTI_NODE_POLLING_TENTACLES_REDIS_CONNECTION_STRING` is set and `CLUSTER_SHARED_CONFIG` is `SEPARATE_VOLUMES`, the container stops with an error. The container only checks the environment variable, not a connection string set with the `configure` command.

## Upgrading

When the volumes are externally mounted to the host filesystem, upgrades between Octopus versions are much easier. We can picture the upgrade process with a container as being similar to [moving a standard Octopus Server](/docs/administration/managing-infrastructure/moving-your-octopus/move-the-database-and-server) since containers, being immutable, don't themselves get updated.

Similar to moving an instance, to perform the container upgrade, you will need the Master Key you used to set up the original database. You can find the Master Key for an Octopus Server in a container with the container exec command:

```text
> docker container exec <container name/ID> /Octopus/Octopus.Server show-master-key --console --instance OctopusServer

5qJcW9E6B99teMmrOzaYNA==
```

When you have the Master Key, you can stop the running Octopus Server container instance (delete it if you plan on using the same name) and run *almost* the same command as before, but this time, pass in the Master Key as an environment variable and reference the new Octopus Server version. When this new container starts up, it will use the same credentials and detect that the database has already been set up and use the Master Key to access its sensitive values:

```bash
docker run --interactive --detach --name OctopusServer --publish 1322:8080 --env DB_CONNECTION_STRING="..." --env MASTER_KEY "5qJcW9E6B99teMmrOzaYNA==" octopusdeploy/octopusdeploy
```

The standard backup and restore procedures for the [data stored on the filesystem](/docs/administration/data/backup-and-restore/#octopus-file-storage) and the connected [SQL Server](/docs/administration/data) still apply as per regular Octopus installations.

## Troubleshooting

If you're having trouble with the Octopus Server Linux Container, please use our [troubleshooting guide](/docs/installation/octopus-server-linux-container/troubleshooting-octopus-server-in-a-container).

## Learn more

 - [Docker blog posts](https://octopus.com/blog/tag/docker/1)
 - [Linux blog posts](https://octopus.com/blog/tag/linux/1)
 - [Introducing the Octopus Server Linux Docker image](https://octopus.com/blog/introducing-linux-docker-image)
 - [Octopus Deploy on Docker Hub](https://hub.docker.com/r/octopusdeploy/octopusdeploy)
 - [Octopus Tentacle on Docker Hub](https://hub.docker.com/r/octopusdeploy/tentacle/)
