Deleting a secret in a later Dockerfile instruction only changes the final filesystem view. The bytes written by an earlier instruction stay in that earlier image layer, and any argument passed with ARG can stay visible in the image’s history. Removing the secret from your current build does not undo either exposure, so the fix is to stop the secret from entering the image in the first place and to rotate any credential that already did.
Why a later delete doesn’t clean up the image
Each Dockerfile instruction that changes the filesystem produces a layer, and an image is the stack of those layers. Docker’s build cache documentation describes this layer model, and the guide to using the build cache walks through how each instruction becomes a layer.
As an Amazon Associate I earn from qualifying purchases.
Consider a Dockerfile that copies a credential file in one step and deletes it in the next:
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →COPY credentials.json /app/credentials.json
RUN use-credentials /app/credentials.json && rm /app/credentials.json
The final container does not show /app/credentials.json, because the merged filesystem no longer contains it. The layer created by the COPY instruction, however, still holds the file’s contents. A later layer records a deletion; it does not rewrite the earlier layer. Anyone who can pull the image and inspect its layers can recover the original bytes.
#1 Best Overall
Where a secret can leak from a build
A secret can be exposed through more than one surface, and each one needs a separate check:
| Surface | What it holds | What it means for a deleted secret |
|---|---|---|
| Final filesystem | The merged view a running container sees | A deleted file is usually absent here, so this is the surface people check first and the one that gives false reassurance. |
| Image layers | Filesystem changes contributed by each instruction | Bytes written by an earlier COPY, ADD, or RUN remain in that layer after a later delete. |
| Image history and metadata | Build instruction and argument information | Values passed with ARG can appear in docker history. The Dockerfile reference says build arguments are visible there, and in max mode provenance attestations in the described Buildx GitHub Actions context (see the Dockerfile reference). |
| Local build cache | Reusable results of build steps | Cache reuse is a different question from what the image contains. Secret values are not part of cache checksums, so changing one does not by itself invalidate a cached step (see cache invalidation). |
| Exported cache | Cache results written to external storage | Access and retention depend on the chosen backend. Cache artifacts can carry whatever was written into the filesystem during the build (see cache storage backends). |
Check what is already exposed
Before you change the Dockerfile, establish what the existing artifacts contain. Work through these checks in order:
Rank #2
- List the instructions that touched the credential. Look for
ARGorENVlines that hold a token, and forCOPYorADDlines that brought in a key file. - Run
docker history --no-trunc <image>and look for argument values in theCREATED BYcolumn. This is the check that matters forARGleakage. - Inspect the layers themselves when a file was copied or written. A deleted file that appears in an earlier layer is still present in the image, even though it is absent from
docker run ... lsinside the container. - If the build produced provenance attestations with Buildx, check those too.
- Check whether any image, registry tag, or exported cache has been pushed or shared. Each copy needs the same assessment.
A clean result from step 2 does not mean the image is safe. Step 3 is the one that catches credentials written into a layer and later removed.
Recommended Free Tools
Pass the secret with a build secret mount
Docker’s build secrets guide states the rule directly: build arguments and environment variables are inappropriate for passing secrets because they persist in the final image. The SecretsUsedInArgOrEnv build check flags this pattern and points to the secret mount as the alternative.
Rank #3
- Made in USA - Proudly produced in Ohio by a Veteran-owned business
- Comprehensive Coverage: This BookFactory log book includes essential fields such as post/shift, time of change, date, weather conditions, and a designated space for detailed notes. This ensures that all relevant information is captured and easily accessible.
- Sturdy Cover: The trans-lux cover protects the log book from wear and tear, ensuring its longevity and maintaining the integrity of your recorded data.
- Essential Security Tool: This log book is an indispensable tool for any organization that values security and accountability. It helps to prevent misunderstandings, improve communication, and ensure a smooth transition between shifts.
- Wire-O with Trans-lux cover, 100 Pages, Dimensions 8.5" x 11" - (Security-Pass-Down) Reorder SKU: LOG-100-7CW-PP(Security-Pass-Down)
The corrected workflow has three parts:
- Pass the credential from the client with
docker build --secret id=aws,src=$HOME/.aws/credentials .. Theidis the name the Dockerfile refers to, andsrcis the local file. - In the Dockerfile, consume the secret in the one
RUNinstruction that needs it:RUN --mount=type=secret,id=aws AWS_SHARED_CREDENTIALS_FILE=/run/secrets/aws aws s3 cp s3://example-bucket/file.txt /app/file.txt - Do not copy the secret anywhere else in the build. Docker documents that the secret is available to the instruction for its duration and is not persisted in the final image or its metadata.
Two practical notes. The secret mount exists only while that RUN executes, so a command that writes the credential into the filesystem, a log, or an output file has reintroduced the problem. Also check that the command itself does not echo the value. Those are behaviour issues inside your own script, not Docker behaviour.
How caching interacts with secrets
BuildKit cache reuse is not evidence that a secret was stored in the image. Docker’s cache invalidation guide says secret contents are not part of cache checksums. Changing the value of a secret does not invalidate a cached instruction, but changes to the secret’s ID and mount path do participate in the checksum.
Rank #4
If a step must rerun after a credential rotates, do not pass the secret as a build argument to force the rebuild. Add a non-secret, changing value, such as a build date or version number, that the instruction depends on. The credential itself stays in the secret mount.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rotate and rebuild
Once you know which credentials were exposed, work through the remediation in this order:
Best Value
- Rotate every exposed credential. Treat anything copied into a layer, passed through
ARG, or visible in history or provenance as compromised. Deleting it from the current Dockerfile is not evidence that earlier artifacts are safe. - Rebuild from the corrected instructions using
--secretand--mount=type=secret, then confirm withdocker historythat no value appears. - Handle pushed artifacts separately. Deleting a tag does not remove earlier layers from a registry, exported caches, or copies held by other systems. Purge and retention steps depend on the registry or cache backend, so consult that backend’s documentation.
- Review cache exports. If the build exported cache to external storage, confirm who can read it and how long it is kept, and treat any cache that may contain the credential as sensitive.
Checklist for future builds
- No credential appears in an
ARG, anENV, or a file copied into the image. - Every secret is passed with
--secretand consumed withRUN --mount=type=secret. - No cache-busting value contains secret material.
- Image history, provenance where generated, and any exported cache are reviewed before sharing.
These rules are based on Docker’s current documentation. Check the linked pages when you upgrade Buildx or BuildKit, because command syntax and build checks can change between releases.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




