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.

More docker tools

Docker Container Image Reference Parser Is that a registry or a Docker Hub user? Dockerfile Linter What this image will do to you later docker run to Kubernetes YAML And the flags that have no equivalent Docker Compose to Kubernetes And why depends_on has no equivalent Docker Logging Driver Generator json-file never rotates Dockerfile Non-Root USER Generator Numeric, or Kubernetes rejects it Docker OCI Image Labels Generator One of them actually does something Docker Hub Pull Rate Limit Calculator Counted per IP, not per person Docker Registry Storage Calculator Deleting a tag frees nothing Docker Build Context Analyzer All of it uploads before anything runs Docker Compose to docker run Converter Names stop resolving Docker Compose Version Migrator version: is obsolete now Docker Compose Network and Port Viewer Everything reaches everything Docker Command Explainer Which flags hand over the host Docker BuildKit Cache Mount Generator apt deletes the cache you just mounted Docker .dockerignore Pattern Tester *.log does not match logs/app.log Docker Image Manifest Viewer unknown/unknown is not broken Docker Image Config Viewer Anyone who can pull can read your Env Docker Registry Token Decoder Check the scope before the credentials Docker HEALTHCHECK Generator Docker does nothing when it fails Docker Network Subnet Calculator 31 networks, then it stops Docker History Analyzer The rm did not save anything Docker Run to Compose Converter Some flags have no equivalent Docker CMD and ENTRYPOINT Tester Why docker stop takes ten seconds Docker Port Mapping Tester -p reaches past your firewall Docker -v to --mount Converter -v invents missing directories Docker Restart Policy Simulator The backoff resets after ten seconds Docker Exit Code Explainer 137 is two different problems Docker CPU Limit Converter --cpu-shares limits nothing Docker Memory Limit Calculator -m 512m allows a gigabyte Docker Compose Interpolation Tester An unset variable is an empty string Docker Environment Variable Precedence Tester Your shell does not reach the container Docker Compose Override Merge Previewer An override can add a port, never remove one Dockerfile Multi-Stage Build Analyzer Which stages reach the image Dockerignore Validator It is not .gitignore

Elsewhere on the site