Docker BuildKit Secrets Don't Leak Into Images
The Problem
I needed to pull from a private npm registry during build:
# DON'T DO THIS
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
RUN npm install
RUN rm .npmrc # Still in a previous layer!
The token is baked into the image history, even after deletion.
The Solution
# syntax=docker/dockerfile:1
FROM node:20
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm install
Build with:
docker build --secret id=npmrc,src=$HOME/.npmrc .
Why It Works
BuildKit secrets are mounted temporarily during the RUN command and never written to the image layers. They exist only in memory during that step.
Other uses:
# SSH keys for private git repos
RUN --mount=type=ssh git clone [email protected]:private/repo.git
# Generic secrets
RUN --mount=type=secret,id=api_key \
API_KEY=$(cat /run/secrets/api_key) ./configure
Requires BuildKit (default in Docker 23+). For older versions:
DOCKER_BUILDKIT=1 docker build ...
Caught this in a security review. The secrets were “deleted” but visible in docker history. Now I know better.