Skip to main content
To run Docker commands such as docker build and docker push in custom flow steps, add a Docker-in-Docker (docker:dind) sidecar to the deployment pod through the agent’s Helm values. The sidecar runs the Docker daemon, and your custom flow reaches it over TLS on localhost.

Prerequisites

  • A self-hosted Kubernetes agent. env zero-hosted agents don’t support this, because it requires changing the agent’s Helm values.
  • Kubernetes 1.29 or later. The sidecar is a native sidecar container, which Kubernetes enables by default from 1.29.
  • A cluster policy that allows privileged pods in the agent’s namespace.
The docker:dind container runs privileged. Anyone who can change a custom flow that runs on this agent can use the Docker daemon to gain root access to the node. To limit the impact, schedule deployment pods on dedicated nodes with deploymentAffinity and deploymentTolerations.
If your cluster blocks privileged pods, build images with a tool that doesn’t need a Docker daemon, such as Buildah.

Add the Docker sidecar

1

Add the sidecar to your Helm values

Add the following to your values.customer.yaml:
values.customer.yaml
  • restartPolicy: Always makes the init container a sidecar. It starts before the deployment container, and Kubernetes stops it when the deployment ends.
  • The startup probe holds the deployment until the Docker daemon accepts connections.
  • At startup, docker:dind generates TLS certificates and writes the client certificates to /certs/client. customVolumeMounts shares that directory with the deployment container.
  • The docker-data volume holds the images Docker pulls and builds in an emptyDir instead of the container’s filesystem. customVolumeMounts also mounts it in the deployment container, which doesn’t use it.
  • Size resources for your builds. In a namespace with a ResourceQuota, Kubernetes rejects the pod if the sidecar doesn’t set them.
  • podAdditionalEnvVars points the Docker CLI at the sidecar. Custom flow steps receive only allowlisted environment variables from the pod, and podAdditionalEnvVars adds these to the allowlist.
docker:29.9.0-dind is the version this page was tested with. For current versions, see the docker image tags on Docker Hub.
2

Apply the values

Upgrade the release with the same flags you used to install it:
The change applies to deployments that start after the upgrade.
3

Install the Docker CLI

The deployment image doesn’t include the Docker CLI. Install it in one of two ways:
  • In the custom flow. Run sudo apk add docker-cli docker-cli-buildx at the start of the step, as in the example below. The packages download on every deployment.
  • In a custom image. Add RUN apk add --no-cache docker-cli docker-cli-buildx to your Dockerfile and set dockerImage to the new image. See Extending deployment image.
If strictSecurityContext is true, sudo is blocked, so use a custom image.
4

Run Docker commands in your custom flow

This example builds an image from a Dockerfile next to env0.yml and pushes it to your registry before terraform init. Store the registry password in an env zero sensitive environment variable named REGISTRY_PASSWORD.
env0.yml
The step log shows the build output, followed by the pushed image digest.

Troubleshooting

Next steps