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