Skip to content
Back to blog
Secrets

Preventing Secrets in Docker Images

How secrets accidentally end up baked into container image layers, and the build patterns that prevent it — including multi-stage builds and build secrets.

S
SecureScout Team· Security Engineering
July 15, 20265 min read

A surprising number of container images ship with credentials baked directly into a layer — not because anyone meant to, but because Docker's layer model makes it easy to leak a secret without noticing.

Why "delete it later" doesn't work

Docker images are built as a stack of layers, and each RUN, COPY, or ADD instruction creates a new one. If a secret is copied into the image in one layer and deleted in a later layer, the secret is still recoverable — it just requires extracting the earlier layer, which any tool that can pull the image can do.

# This does NOT remove the secret from the final image
COPY .env /app/.env
RUN rm /app/.env

Use multi-stage builds to keep secrets out of the final image

Multi-stage builds let you use a secret during the build process (e.g., to pull a private package) without it ever reaching the final image, because only the artifacts you explicitly copy forward make it into the last stage.

FROM node:20 AS builder
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install

FROM node:20-slim
COPY --from=builder /app/dist /app/dist

Use BuildKit's secret mount, not build args

ARG and ENV both persist secret values into image history. Docker BuildKit's --mount=type=secret flag makes a secret available only during a specific RUN instruction, without persisting it into any layer or the image metadata.

Scan images before pushing

Even with careful builds, image scanning as a backstop catches secrets that slip through — misplaced config files, debug artifacts, or a .env accidentally included via a broad COPY . ..

Use a proper .dockerignore

A missing .dockerignore is one of the most common causes of secrets ending up in images — COPY . . picks up .env, .git, and local credential files that were never meant to leave the developer's machine.

The fix isn't more vigilance during builds — it's a build pattern (multi-stage, BuildKit secrets, .dockerignore) that makes leaking a secret structurally difficult, not just discouraged.

dockercontainerssecret-detection

Frequently Asked Questions

If I delete a secret file in a later Dockerfile step, is it gone from the image?

No. Each instruction creates a new layer, and earlier layers remain in the image even if a later layer deletes the file. Anyone with the image can extract earlier layers and recover it.

Are environment variables set with ENV in a Dockerfile safe for secrets?

No. ENV values are baked into the image metadata and visible via `docker inspect` or `docker history`, even without extracting layers.

Related Articles

S

SecureScout Team

Security Engineering

Learn more →