Execution containers for workers

For a step running on a worker or on the Octopus Server, you can select a Docker image to execute the step inside of.

When an execution container is configured for a step, Octopus will still connect to the worker machine via a Tentacle or SSH. The difference is that the specified image will be run as a container and the step will be executed inside the container.

See the blog post announcing this feature for some added context.

Requirements

You need Docker installed and running on the worker/Octopus Server (built-in worker), in order to use execution containers for workers

Octopus cloud dynamic worker pools

Octopus Cloud dynamic workers have Docker pre-installed and support execution containers.

How to use execution containers for workers

  • Configure a feed in Octopus Deploy for a Docker registry.
  • Add a project and define a deployment process (or add a runbook).
  • Set the Execution Location for your step to Run on a worker.
  • In Container Image select Run inside a container on a worker and then Pull container from a registry.
  • Choose the previously added container registry.
  • Enter the name of the image (execution container) you want your step to run in. (e.g. octopusdeploy/worker-tools:ubuntu.22.04).
  • Click Save.
  • Click Create release & deploy.

First deployment on a docker container

Pre-pulling your chosen image will save you time during deployments.

When you choose to run one or more of your deployment steps in a container, your deployment process will docker pull the image you provide at the start of each deployment during package acquisition.

For your first deployment this may take a while since your docker image won’t be cached. You can pre-pull the desired docker image on your worker before your first deployment to avoid any delays.

Which Docker images can I use?

The easiest way to get started is to use the worker-tools images built by Octopus Deploy.

When a step is configured to use an execution container, you can choose from:

If you run into issues with the provided worker-tools images or they don’t meet your needs, you will have to create a custom image. Take a look at the custom docker image section or the blog post on extending execution containers to learn how to create a custom image.

The octopusdeploy/worker-tools Docker images

For convenience, we provide some images on Docker Hub octopusdeploy/worker-tools which include common tools used in deployments.

We recommend using our worker-tools image as a starting point for your own custom image to run on a worker.

The canonical source for what is contained in the octopusdeploy/worker-tools images is the Dockerfile’s in the GitHub repo. For example:

Some of the tools included are:

  • Octopus Deploy CLI and .NET client library
  • .NET Core
  • Java (JDK)
  • NodeJS
  • Azure CLI
  • AWS CLI
  • Google Cloud CLI
  • kubectl
  • Helm
  • Terraform
  • Python

Custom docker images

It can be beneficial to build your own custom Docker image when using execution containers, particularly when you wish the image size to be as small as possible.

Supported Windows base images

For Windows images, we recommend using a base image no older than the ltsc2022 image. Octopus does not support images that are older than ltsc2022, and while containers based on these images can still run steps, you may run into unexpected issues.

If your containers are based on an earlier image of Windows, we strongly recommend upgrading your workers to Windows 2022 and rebasing your Docker containers to use a 2022 base image.

Supported Linux distributions

It’s important to understand there are some limits to which Linux Docker images can be used as a container image. The Docker image must be based on a Linux distribution using the GNU C library, or glibc. This includes operating systems like Ubuntu, Debian, and Fedora.

Linux distributions built on musl, most notably Alpine, do not support Calamari, and cannot be used as a container image. This is due to Calamari currently only being compiled against glibc and not musl.

You can usually find the base operating system of a Linux Docker image by running the following command:

docker run --entrypoint='' [image name] /bin/cat /etc/os-release.

For example for the octopusdeploy/worker-tools:5.0.0-ubuntu.22.04 image, you’d run:

docker run --entrypoint='' octopusdeploy/worker-tools:5.0.0-ubuntu.22.04 /bin/cat /etc/os-release.

Required OS dependencies

The operating system must also include a number of dependencies required to support .NET Core applications. When a step is configured to use an execution container, Calamari (the Octopus deployment utility) is executed inside the specified container. Since Calamari is a .NET Core self-contained executable, any custom Docker image needs to include the dependencies required to execute a .NET self-contained executable.

The Microsoft .NET Core documentation lists the dependencies required for a .NET Core application with popular Linux distributions.

If a third party container is missing a library, it is usually the libicu library. The error Couldn’t find a valid ICU package installed on the system indicates the ICU library is missing.

If your chosen Docker image does not have these prerequisites, the easiest solution is to create a custom Docker image based on the image you wish to use, install the required libraries, push the image to a repository like DockerHub, and select your custom image as the container image.

Microsoft also provides base images that include these dependencies.

Custom docker image example

The following example is a basic Docker file that (when built) can run Calamari and PowerShell scripts:

FROM ubuntu:20.04

ARG POWERSHELL_VERSION=7.1.3\*

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        curl \
        unzip \
        apt-transport-https \
        software-properties-common && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Powershell core
# https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7.1#ubuntu-2004
RUN curl -LO -k "https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb" && \
    dpkg -i packages-microsoft-prod.deb && \
    apt-get update && \
    add-apt-repository universe && \
    apt-get install -y --no-install-recommends \
        powershell=${POWERSHELL_VERSION} && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -f packages-microsoft-prod.deb

To learn more about creating a custom docker image, we have a detailed blog post that describes how to get started and the minimum set of dependencies you would need.

Inline execution containers

Support for inline execution containers requires Octopus version 2024.1

To improve the experience of using custom docker images on steps in Octopus we’re expanding our execution containers feature to include options to provide the Dockerfile from a Git URL or an Inline Dockerfile that will be built and used as the container that the step is executed on.

This will make it easier and quicker to iterate on building a Docker image best suited to different scenarios.

For your first deployment this may take a while since we’re building the Docker container image for the first time, subsequent runs will be quicker as the image is cached (as long as it runs on the same worker).

Docker image from a Git URL

The Docker image from a Git URL option allows you to use a Dockerfile stored in a Git repository to build the image that the step in Octopus will run on.

See the Docker documentation for information about what context configuration is accepted in the Git URL.

Docker image from an inline Dockerfile

The Docker image from an inline Dockerfile option allows you to write the container specification used to build the image that the step in Octopus will run on directly on the step in your deployment process.

This option allows you to iterate quickly on building a container specification that will work for the step.

Tool paths

Because Calamari is executed directly inside the specified container, execution containers on workers are run in non-interactive mode. Since the execution container is not running interactively, it does not process your .bashrc file. If the tool you have installed relies on .bashrc to modify the path (e.g. nvm) to include a non-standard folder, you will need to manually define the additional directories in the $PATH variable in your Dockerfile using the ENV PATH directive.

For example, if you install node.js via nvm, you will need to remediate the $PATH variable in your image with the location node.js gets installed to with the following directive in your Dockerfile:

ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:$PATH"

CMD and ENTRYPOINT directives

Docker images used with the execution containers feature require that no CMD or ENTRYPOINT directives be defined in your Dockerfile.

Including one of these directives will result in the step failing.

Collecting artifacts with execution containers

You can collect Octopus artifacts from steps used with the execution containers feature.

The source file for the artifact must be saved and collected from the fully qualified path of one of the directories (or sub-directories) mapped into the execution container as a volume.

The recommended volume to use is the temporary directory created within the <Tentacle Home>/Work workspace, for example, /etc/octopus/Tentacle/Work/20221128114036-119427-56.

Once the artifact has been collected, the directory and its contents will be removed once the step has been executed. Its value can be found in the PWD environment variable.

The following script would collect an artifact called foo.txt from the temporary working directory using the $PWD environment variable:

Bash
echo "Hello" > $PWD/foo.txt
new_octopusartifact $PWD/foo.txt
PowerShell
"Hello" > "$($PWD)/foo.txt"
New-OctopusArtifact "$($PWD)/foo.txt"

Supplying arguments to the container runtime

Specifying a variable named Octopus.Action.Container.Options allows configuring the options supplied to the container runtime (i.e. Docker).

For example:

NameValue
Octopus.Action.Container.Options--security-opt label:level:TopSecret

For the list of available options see the Docker run options.

The Octopus.Action.Container.Options variable can be scoped.

Support for Octopus.Action.Container.Options was introduced in Octopus version 2023.2.13224

Help us continuously improve

Please let us know if you have any feedback about this page.

Send feedback

Page updated on Sunday, January 1, 2023