Docker BuildKit Secret Mount Generator

Move a build-time credential out of ARG and into --mount=type=secret. The value then exists as a file during one RUN and is in no layer and no metadata.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Generate. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A token as a build argument

Recorded in the image history, where anybody who can pull can read it

ARG NPM_TOKEN
RUN npm ci

A key in an ENV

In the image config and in the environment of every container from it

ENV API_KEY=REPLACE_ME
RUN ./setup.sh

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Passing a token as a build ARG

    The value is recorded in the image metadata and docker history shows it to anybody who can pull the image. Removing the file it wrote changes nothing.

    Instead:Use RUN --mount=type=secret and pass it with --secret at build time.

  2. Fixing the Dockerfile and not rotating the credential

    Images already pushed still carry the value in their history. The fix protects future builds only.

    Instead:Rotate first, then rebuild. Treat anything already published as leaked.

  3. Writing the mounted secret to a file so a later step can use it

    That file is in the layer, which is exactly what the mount was avoiding.

    Instead:Do the work that needs the credential inside the same RUN.

ARG and ENV are both permanent records

An ARG's value is stored in the image metadata and shown by docker history. An ENV is in the image config and in every container started from it. Neither can be removed by a later instruction.

Deleting the file does not delete the record

The common attempt is to write the credential to a file, use it, and rm it in the same RUN. That does remove the file from the layer, and it does nothing about the ARG whose value is in the history. The record is the argument, not the file.

A secret mount is a file that exists for one instruction

It appears at /run/secrets/ID for the duration of that RUN and nowhere else. Read it into a shell variable inside the same instruction and let it go out of scope. Exporting it, or writing it under the build context, puts it straight back into a layer.

Two ways to supply it

--secret id=x,src=./file reads a file, and --secret id=x,env=VAR reads an environment variable, which is the form CI usually wants because the value is already in the runner's secret store.

Rotate before you fix

Changing the Dockerfile does not change images already pushed. Every tag built while the credential was in the history still carries it, and registry garbage collection does not remove a manifest anybody has pulled. Rotate first, then rebuild.

The failure mode without BuildKit is a good one

With DOCKER_BUILDKIT=0 the --mount flag is a syntax error, so the build stops rather than quietly building without the secret. That is much better than a silent partial success.

What this cannot see

Whether the credential is real, or where else it has been used. It reads the text you paste, in your browser, and never echoes a value it identified as a secret.