Docker BuildKit Secrets Don't Leak Into Images

· 1 min read
docker security devops

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.

Available for rescue and re-platforming work

I take over platforms that already exist and are in trouble. Node, TypeScript, React and Laravel, mostly in regulated or high-traffic environments. If something needs rescuing, re-platforming or finishing, my full history is on the CV.

Related Posts

Comments