Skip to main content
This example demonstrates how to build a Docker image within a Tekton Task using a Docker-in-Docker (DinD) sidecar.

Example

apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: dind-sidecar-
spec:
  taskSpec:
    steps:
    - image: mirror.gcr.io/library/docker@sha256:0752ca4e936da012c173c119217c0f9599b3b191c1557e53206d5d06d2627580
      name: client
      env:
      # Connect to the sidecar over TCP, with TLS.
      - name: DOCKER_HOST
        value: tcp://localhost:2376
      # Verify TLS.
      - name: DOCKER_TLS_VERIFY
        value: '1'
      # Use the certs generated by the sidecar daemon.
      - name: DOCKER_CERT_PATH
        value: /certs/client
      workingDir: /workspace
      script: |
          #!/usr/bin/env sh
          set -e
          # Run a Docker container.
          docker run busybox echo hello

          # Write a Dockerfile and `docker build` it.
          cat > Dockerfile << EOF
          FROM ubuntu
          RUN apt-get update
          ENTRYPOINT ["echo", "hello"]
          EOF
          docker build -t hello .
          docker images

          # ...then run it!
          docker run hello
      volumeMounts:
      - mountPath: /certs/client
        name: dind-certs

    sidecars:
    - image: mirror.gcr.io/library/docker@sha256:0752ca4e936da012c173c119217c0f9599b3b191c1557e53206d5d06d2627580
      name: server
      args:
        - --storage-driver=vfs
        - --userland-proxy=false
        - --debug
      computeResources:
        requests:
          memory: "512Mi"
      securityContext:
        privileged: true
      env:
      # Write generated certs to the path shared with the client.
      - name: DOCKER_TLS_CERTDIR
        value: /certs
      volumeMounts:
      - mountPath: /certs/client
        name: dind-certs
      # Wait for the dind daemon to generate the certs it will share with the
      # client. StartupProbe handles slow Docker daemon initialization.
      startupProbe:
        periodSeconds: 1
        failureThreshold: 30  # Allow up to 30 seconds for Docker daemon to start
        exec:
          command: ['ls', '/certs/client/ca.pem']
      # ReadinessProbe verifies Docker daemon is actually ready to accept commands.
      # Note: With k8s native sidecar support, startupProbe is honored but
      # readinessProbe may not be.
      readinessProbe:
        periodSeconds: 2
        exec:
          command: ['docker', 'info']

    volumes:
    - name: dind-certs
      emptyDir: {}

How It Works

1

Sidecar Starts Docker Daemon

The sidecar container runs a Docker daemon with TLS enabled. It generates certificates and writes them to a shared volume at /certs/client.
2

Startup Probes Wait for Daemon

The startupProbe waits for the certificates to be generated (up to 30 seconds). The readinessProbe verifies the daemon is ready to accept commands.
3

Client Connects to Daemon

The client step configures the Docker CLI to connect to the sidecar daemon using environment variables:
  • DOCKER_HOST=tcp://localhost:2376 - Connect via TCP
  • DOCKER_TLS_VERIFY=1 - Enable TLS verification
  • DOCKER_CERT_PATH=/certs/client - Use shared certificates
4

Build and Run Docker Image

The client step:
  1. Runs a simple busybox container to verify connectivity
  2. Creates a Dockerfile
  3. Builds an image tagged as hello
  4. Runs the newly built image

Security Considerations

The Docker daemon sidecar requires privileged: true to function. This grants significant permissions to the container. Only use this in trusted environments.

Docker Daemon Configuration

The daemon is configured with specific arguments:
  • --storage-driver=vfs - Uses VFS storage driver (slower but more compatible)
  • --userland-proxy=false - Disables userland proxy
  • --debug - Enables debug logging

TLS Certificate Sharing

The pattern for sharing TLS certificates:
  1. Sidecar sets DOCKER_TLS_CERTDIR=/certs to generate certs
  2. Both containers mount the same dind-certs volume
  3. Client reads certificates from /certs/client
  4. Docker CLI automatically uses these certificates

Expected Output

hello

Sending build context to Docker daemon...
Step 1/3 : FROM ubuntu
Step 2/3 : RUN apt-get update
Step 3/3 : ENTRYPOINT ["echo", "hello"]
Successfully built...
Successfully tagged hello:latest

REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
hello        latest    abc123def456   1 second ago    77.8MB

hello

Alternative Approaches

For production use, consider:
  • Kaniko: Builds images without requiring privileged mode
  • Buildah: Daemonless container builds
  • BuildKit: Modern Docker build backend with better caching
These alternatives are more secure and work better in restricted environments.

Key Concepts

  • Sidecars: Containers that run alongside task steps to provide services
  • Docker-in-Docker (DinD): Running Docker daemon inside a container
  • Startup Probes: Wait for slow-starting containers to be ready
  • Shared Volumes: Pass data between steps and sidecars
  • TLS Security: Secure communication between Docker client and daemon
  • Privileged Containers: Required for DinD but should be used carefully

Next Steps

Build docs developers (and LLMs) love