This article is based on documentation originally published by Mesosphere for DC/OS and the Jenkins for DC/OS package.
Overview
By default, Mesosphere DC/OS runs workloads inside Docker containers to minimize host OS dependencies and to provide resilience against node failures. When you use Jenkins on DC/OS, the underlying Mesos scheduler dynamically creates Jenkins build agents as Mesos tasks, each running inside a Docker container. Your configured build steps then execute inside that same container.
Because builds commonly invoke Docker commands such as docker build or docker push, Mesosphere provides the mesosphere/jenkins-dind image (Docker-in-Docker) and configures Jenkins for DC/OS to use it by default. The image ships with several widely-used tools; the authoritative list is in the upstream Dockerfile.
If your builds require environment-specific packages or configurations that are not present in the default image, you can create a custom Docker image, push it to Docker Hub or a private registry, and point Jenkins at it. That registry must be reachable from every DC/OS agent node.
Minimum Requirements for a Custom Agent Image
At a minimum, every custom Jenkins agent image must include:
- OpenJDK 8 — Required by Jenkins to launch the agent process and register it with the Jenkins master.
- CA certificates — Required to verify SSL/TLS certificates when the agent communicates with external services.
The following packages are not strictly required but are commonly needed by build scripts:
- Bash — Many Jenkins build scripts rely on Bash as their shell interpreter.
- Git — Required to check out source code from Git repositories.
- OpenSSH client — Required when cloning repositories over SSH.
Creating a Custom Image Based on mesosphere/jenkins-dind
The recommended approach is to extend the official mesosphere/jenkins-dind base image rather than building a new image from scratch. This ensures you inherit the correct Java runtime, CA certificates, Docker daemon setup, and other baseline configuration.
The following example Dockerfile adds sbt (Scala Build Tool) to the base image. The RUN instruction downloads and extracts the sbt tarball into /usr/local and records the installed version in a build manifest file. (This pattern is adapted from the 1science/docker-sbt Dockerfile.)
FROM mesosphere/jenkins-dind:0.2.2
ENV SBT_VERSION 0.13.8
ENV SBT_HOME /usr/local/sbt
ENV PATH ${PATH}:${SBT_HOME}/bin
RUN curl -sL "http://dl.bintray.com/sbt/native-packages/sbt/$SBT_VERSION/sbt-$SBT_VERSION.tgz" \
| gunzip | tar -x -C /usr/local \
&& echo "- with sbt $SBT_VERSION" >> /root/.builtCode language: JavaScript (javascript)
After writing your Dockerfile, build and push the image:
# Build the image
docker build -t myorg/jenkins-agent-scala:latest .
# Push to Docker Hub (or substitute your private registry hostname)
docker push myorg/jenkins-agent-scala:latestCode language: PHP (php)
Ensure the image is accessible from all DC/OS agent nodes. If you are using a private registry, configure DC/OS agent credentials accordingly.
Managing SSH Host Keys
The default jenkins-dind image ships with GitHub’s SSH public keys pre-populated in /etc/ssh/ssh_known_hosts. If your Git server is not GitHub, SSH-based cloning will fail with a host-key verification error unless you add your server’s public key to that file.
Add the following lines to your Dockerfile, replacing my.git.server with your actual Git server hostname:
ENV SSH_KNOWN_HOSTS github.com my.git.server
RUN ssh-keyscan $SSH_KNOWN_HOSTS | tee /etc/ssh/ssh_known_hostsCode language: PHP (php)
ssh-keyscan contacts each hostname and writes its public key to stdout. Piping the output to tee appends the keys to the known-hosts file inside the image, so the SSH client will not prompt for confirmation at clone time.
Configuring Jenkins to Use the Custom Image
Once your custom image is available in a registry, you need to register it as a slave configuration in Jenkins so it can be selected by individual jobs.
- In the Jenkins web UI, go to Manage Jenkins → Configure System.
- Scroll to the Cloud section and click Advanced. A grey Add Slave Info button will appear.

- Fill in the slave info fields. Key settings include:
- Label string — A unique label you will use in job configurations to target this agent (for example,
scala-agent). - Usage — Leave as the default (Utilize this node as much as possible) unless you have a specific reason to restrict it.
- Jenkins slave CPUs — CPU shares allocated to the agent container itself.
- Jenkins slave memory in MB — Memory allocated to the agent container itself.
- Maximum number of executors per slave — How many Jenkins executors will run inside the single container.
- Jenkins executor CPUs — Estimated CPU shares per executor.
- Jenkins executor memory — Estimated memory per executor.
The actual resources requested from Mesos are calculated as follows:
actualCpus = slaveCpus + (maxExecutors * executorCpus) actualMem = slaveMem + (maxExecutors * executorMem)
- Label string — A unique label you will use in job configurations to target this agent (for example,
- Click Advanced again to expose the containerizer options. Select Use Docker Containerizer and enter your custom image name in the Docker Image field (for example,
myorg/jenkins-agent-scala:latest).
Note: If your custom image is a Docker-in-Docker image (that is, it needs to run Docker commands inside the container), you must also enable Docker Privileged Mode and specify a custom Docker command shell in this panel.
- Click Save.
Targeting the Custom Agent from a Jenkins Job
After the slave configuration is saved, you can restrict any job to run on the new agent by referencing its label.
- Open the job and click Configure.
- Check Restrict where this project can be run.
- Enter the Label String you defined in the slave configuration (for example,
scala-agent).
- Click Save.
When the job is triggered, the Mesos scheduler will spin up a new agent container using your custom image and route the build to it.
Summary
Customizing Docker containers for Jenkins agents on DC/OS follows a straightforward workflow:
- Extend
mesosphere/jenkins-dindwith your dependencies. - Add any required SSH host keys at image build time.
- Push the image to a registry accessible by all DC/OS agent nodes.
- Register the image as a new slave configuration in Jenkins, assigning it a label.
- Restrict individual jobs to that label so they run on the correct agent image.
This pattern keeps build environments reproducible and version-controlled without modifying the DC/OS host nodes directly.