The docker-compose Update Module is included in Mender Client 6.0 or newer. The Update Module is not installed by default. It can be installed to your target devices as a Debian package or with a Yocto recipe. You can find the source code in the mender-container-modules repository.
This document explains how to create a docker-compose Artifact using the gen_docker-compose Artifact generator.
The generated Artifact contains a docker-compose manifest and the container images required to deploy an update using the docker-compose Update
Module from mender-container-modules. This ensures robust network transfers of container images using the Mender Client in managed mode, while also enabling Standalone mode to install container images without network access.
This tutorial assumes:
skopeo on your workstation for downloading container images from registriesDownload the Artifact generator from the repository:
curl -O https://raw.githubusercontent.com/mendersoftware/mender-container-modules/1.1.0/src/gen_docker-compose
chmod +x gen_docker-compose
Verify the installation:
./gen_docker-compose --help
The simplest way to create a docker-compose Artifact is to let gen_docker-compose automatically download the required container images from their registries.
Docker Compose doesn't restart stopped services by default. Without a restart policy, Docker Compositions won't be automatically restarted if a device is rebooted. See the example manifest below and the Docker documentation for information on restart policies.
First, create a directory for your manifests and add a docker-compose.yml file, e.g.:
mkdir manifests
cat > manifests/docker-compose.yml << 'EOF'
services:
webserver:
image: nginx:alpine
restart: unless-stopped
ports:
- "8080:80"
EOF
By default, gen_docker-compose downloads container images for your workstation's architecture. If your workstation differs from your device architecture, you should specify the target architecture using the --architecture flag.
To list available architectures for the images in your manifests:
./gen_docker-compose \
--list-architectures \
--manifests-dir manifests/
Create the Artifact by for your target device by specifying the artifact name, compatible types, architecture, manifests directory, and project name:
./gen_docker-compose \
--artifact-name docker-compose-artifact-v1 \
--device-type raspberrypi5 \
--architecture arm64 \
--manifests-dir manifests/ \
--project-name my-webserver \
--output-path docker-compose-artifact-v1.mender \
-- \
--software-filesystem data-docker
The tool will:
skopeoNote that the last option is separated from the rest with -- which means that
this option is not interpreted by the artifact generator itself, but is passed
through to the underlying mender-artifact tool. The
--software-filesystem
option adds metadata information to the Artifact that describes where container
images are stored by Docker. The default (if omitted) is rootfs-image
suggesting the container images are stored on the root filesystem (and thus
manipulated as part of root filesystem updates). However, the preferred
configuration, described in the docker-compose Update Module integration
documentation for
Debian
and
Yocto,
is with Docker storing the images on a different partition, e.g. under
/data/docker (hence the data-docker value describing this). Other options,
for example --depends rootfs-image.checksum:custom-value to specify that the
given Docker composition requires a specific rootfs image or, can be passed to
mender-artifact in a similar way.
The output from the above command shows the Artifact structure:
Mender Artifact:
Name: docker-compose-artifact-v1
Format: mender
Version: 3
Signature: no signature
Compatible types: [raspberrypi5]
Provides group:
Depends on one of artifact(s): []
Depends on one of group(s): []
State scripts: []
Updates:
- Type: docker-compose
Provides:
data-docker.mender-docker-compose.my-webserver.version: docker-compose-artifact-v1
Depends: {}
Clears Provides: [*mender-docker-compose_*]
Metadata:
{
"project_name": "my-webserver",
"version": "1"
}
Files:
- checksum: 57a12b190c2ba23e4fd77222b1df9e1fd14f90bbe13acf64b162c5bc7c7cb98f
modified: 2025-11-27 14:13:30 +0100 CET
name: images.tar.gz
size: 22092805
- checksum: 364567786aab968bd9f54c23ba90235bfdbce8b704e2e6fbfb929513c16eecbf
modified: 2025-11-27 14:13:28 +0100 CET
name: manifests.tar
size: 10240
The Artifact contains two files:
Instead of letting gen_docker-compose download images automatically, you can prepare the container images manually.
First, pull the required images and save them as tar files:
mkdir images
docker pull nginx:alpine
docker save -o images/nginx_alpine.tar nginx:alpine
The filename doesn't need to follow a specific format, but it's helpful to use a descriptive name.
Now generate the Artifact using the --images-dir option:
./gen_docker-compose \
--artifact-name docker-compose-artifact-v1 \
--device-type raspberrypi5 \
--manifests-dir manifests/ \
--images-dir images/ \
--project-name my-webserver \
--output-path docker-compose-artifact-v1.mender
-- \
--software-filesystem data-docker
When --images-dir is specified, gen_docker-compose will use the provided images instead of downloading them from registries.
To use images from a private or custom registry, specify the full image path in your docker-compose manifest:
services:
my-service:
image: registry.example.com/my-org/my-service:v1.2.3
When using automatic image download with authenticated registries, you can configure credentials using either Docker or skopeo:
# Using Docker login (skopeo will use these credentials)
docker login registry.example.com
# Or authenticate directly with skopeo
skopeo login registry.example.com
After authenticating, gen_docker-compose will be able to download images from the private registry.
When updating devices with a docker-compose Artifact installed, a delta between the old (installed) and the new (update) docker-compose Artifacts can be generated and packed as an Artifact of type delta-docker-compose. Such an Artifact can then be deployed as an update instead of the new docker-compose artifact in order to save bandwidth.
The delta-docker-compose Update Module and generator are not publicly available and are not part of Mender Client.
See the mender-delta-docker-compose download
instructions
for how to get the gen_delta-docker-compose generator script and its
dependencies. Once available locally, it can be used to generate a delta
Artifact in the following way:
./gen_delta-docker-compose old_artifact.mender new_artifact.mender
This generates a new_artifact.delta.mender Artifact that can be used instead
of the original new_artifact.mender to deploy an update to devices with the
old_artifact.mender installed (which is checked as part of the
deployment).
The gen_delta-docker-compose generator requires docker-compose Artifacts
created with gen_docker-compose version 1.1.0 or newer.
There are three command-line options that can be passed to the generator script:
--artifact-name, to specify Artifact name of the new artifact. Defaults to the name of the target artifact.--output-path, to set path to output Artifact file. Defaults to target_artifact.delta.mender (as shown above)--layer-deltas, to enable an extra step attempting to calculate deltas between layers of similar images.The --layer-deltas option requires xdelta3 available for both, the generator
and the Update Module (on the device). It may reduce the size of the delta
Artifact, however, it is advised to compare the result to a result of running
the generator without the option and consider which delta Artifact to use
because layer deltas are expensive to resolve on the device (and xdelta3 is
required on the device, as mentioned above).