Skip to main content
RunBook Academy

← All labs in Docker & Containers

Lab · intermediate · ~30 min

Lab 8: Use BuildKit build secrets

B · Nested virtualisationC · Simulation

Objectives

  • Pass a build secret via `--secret`
  • Verify the secret does not appear in any layer
  • Use ssh mount for private git repositories

Prerequisites

  • Lab 7: BuildKit multi-stage

Objective

Build an image that consumes a private pip index requiring a token. Use a BuildKit secret mount so the token exists only for the duration of the pip install step and never lands in a layer.

Tasks

Task 1: Create the secret file

mkdir -p ~/secret-lab && cd ~/secret-lab
echo 'pypi-AgENdGVzdHRva2VuMTIzNDU2Nzg5MA' > .pypi-token
chmod 0400 .pypi-token

Task 2: Author the Dockerfile

# syntax=docker/dockerfile:1.7
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./

# Mount the token ONLY for this single RUN step.
RUN --mount=type=secret,id=pypi,dst=/run/secrets/pypi_token \
    sh -c 'pip install --index-url https://upload.pypi.org/legacy/ \
                  --extra-index-url https://myorg:pypi-token-value@pypi.example.com/simple/ \
                  -r requirements.txt 2>/dev/null; \
           PIP_TOKEN=$(cat /run/secrets/pypi_token) && \
           pip config set global.index-url "https://myorg:${PIP_TOKEN}@pypi.example.com/simple/" && \
           pip install -r requirements.txt'

# In a real image, prefer configuring pip via env at runtime instead.
COPY app.py ./
USER 10001:10001
ENTRYPOINT ["python3", "/app/app.py"]

(For this lab we just demonstrate the mount; the actual install fails without a real PyPI server, which is fine.)

Task 3: Build with the secret

DOCKER_BUILDKIT=1 docker build --secret id=pypi,src=.pypi-token -t myorg/private:1.0.0 .

Task 4: Verify the secret is not in the image

# Inspect every layer for the token
docker save myorg/private:1.0.0 -o /tmp/img.tar
mkdir -p /tmp/img-layers && cd /tmp/img-layers
tar xf /tmp/img.tar
for d in */; do
  if grep -r 'pypi-token-value' "$d" 2>/dev/null; then
    echo "LEAK in $d"; exit 1
  fi
done
echo "OK: token not in any layer"

# Inspect history
docker history myorg/private:1.0.0 --no-trunc | grep -i 'pypi-token-value' && echo 'LEAK' || echo 'OK'

The token should not appear anywhere in the image’s filesystem or history.

Task 5: SSH mount (optional)

If you have an SSH key with access to a private git repo:

# Authorize your host's ssh agent
ssh-add ~/.ssh/id_ed25519

# In the Dockerfile
RUN --mount=type=ssh git clone git@github.com:myorg/private-repo.git
DOCKER_BUILDKIT=1 docker build --ssh default -t myorg/private:1.0.0 .

Cleanup

docker rmi myorg/private:1.0.0
rm -rf ~/secret-lab /tmp/img.tar /tmp/img-layers
shred -u .pypi-token  # securely delete

Verification status

Last reviewed
2026-08-09
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.