Chapter 28Lesson 04~150 minutes

Secrets and Configuration Patterns, Runtime Injection, Environment Risk, Build Secrets, and External Secret Stores: Diagnostics, Failure Modes, Security, and Performance

Diagnose credential leakage and secret-handling failures by preserving build, image, inspect, mount, log, and provider evidence before applying the least-destructive correction.

Leak diagnosisBuild checksLogsImage historyRemediation

Learning objectives

  • Preserve first-failure evidence for credential and configuration incidents without spreading secret values.
  • Diagnose common leaks involving build contexts, ARG/ENV, image layers, logs, caches, and production credentials in build systems.
  • Use Docker build checks and metadata inspection as evidence rather than disabling controls.
  • Apply the smallest safe correction and prove the secret no longer crosses the wrong trust boundary.

1. Incident rule: preserve evidence, not the credential

When authentication fails, people often run env, enable debug tracing, print headers, or paste configuration into tickets. That can convert one incident into a credential leak. Preserve timestamps, error codes, secret IDs, provider request IDs, image/container IDs, mount metadata, and policy decisions. Redact or avoid the value itself.

2. Evidence-first diagnostic sequence

  1. Record docker version, context, Engine info, Buildx/BuildKit/Compose versions.
  2. Record exact source revision, Dockerfile/Compose files, image digest, and build reference.
  3. Inspect image config/history and the container configuration/mounts without printing known secret values.
  4. Check build logs, application logs, and Engine events for the synthetic secret marker only in a lab; in production search by safe IDs/metadata.
  5. Confirm the secret owner, provider, version, scope, expiration, and consumer authorization.
  6. Correct the narrowest layer and rerun only the failed scope.

3. Broken example: secret-shaped ARG/ENV

The following Dockerfile is intentionally wrong and uses only a fake placeholder. The point is to let Docker’s own build check explain the risk.

# syntax=docker/dockerfile:1
FROM alpine:3.22.1
ARG API_TOKEN
ENV API_TOKEN=$API_TOKEN
RUN echo "build step ran" > /status
mkdir -p da-ch28-broken && cd da-ch28-broken
# save the Dockerfile above as Dockerfile

docker buildx build --check . 2>&1 | tee build-check.txt || true

Expected interpretation on current Buildx/frontend versions: SecretsUsedInArgOrEnv warns that sensitive data should not use Dockerfile ARG/ENV. The correct response is not --privileged, not an unconfined security profile, and not disabling the check. Move the credential to a BuildKit secret mount.

4. Corrected build pattern

# syntax=docker/dockerfile:1
FROM alpine:3.22.1
RUN --mount=type=secret,id=api_token,required=true     test -s /run/secrets/api_token &&     printf '%s
' 'authenticated=yes' > /status
printf '%s
' 'FAKE-CH28-ONLY' > fake-token.txt
docker buildx build --check .
docker buildx build --secret id=api_token,src=fake-token.txt --load -t da-ch28:fixed .
docker image inspect da-ch28:fixed --format '{{json .Config.Env}}'
docker history --no-trunc da-ch28:fixed

Delete the fake token after the lab. In a real system, revoke the compromised credential before declaring remediation complete.

5. Failure modes and causal repairs

Failure Wrong shortcut Evidence Correction
.env/private key copied into context Delete it in a later layer Context rules, Dockerfile COPY, history/layer evidence, VCS state Remove from context/VCS, rotate credential, rebuild from clean source
ARG/ENV secret Rename variable to hide check Build check, image config/history BuildKit secret/SSH mount
Secret echoed to build/app log Rely only on log masking Log sink, CI transcript, external collector delivery Stop rendering value, rotate it, purge according to log-retention policy
Secret copied then removed Assume final filesystem is enough Layer/cache/export evidence Never persist it; rebuild cleanly
Compose local secret treated as encrypted store Assume /run/secrets implies encrypted at rest Compose source definition and host file ownership Protect source or integrate external/provider-native secret store
Production credential shared with build job “CI is trusted” Token scope, runner trust, job permissions Dedicated build identity with minimal scope/lifetime

6. Secret transformation is still leakage

Base64, URL encoding, substring printing, shell tracing, and JSON escaping do not make a credential safe. A masking engine may recognize the original value but miss a transformed derivative. Debug the protocol and authorization state: status code, secret ID, scope, audience, expiration, request ID, certificate chain, or file permissions.

7. Cache and exporter boundaries

BuildKit secret mounts are designed not to become layer content, but a build command can still deliberately write the value into a file, artifact, compiler output, test snapshot, or remote service. Treat builders and exported caches as trust domains. Do not share high-trust caches into lower-trust forks or public jobs without reviewing what the build can persist.

8. Cleanup and incident closure

For a real leak, “remove the file” is not closure. Revoke/rotate the credential, identify every copied surface (VCS, image registry, cache, logs, artifacts, tickets), replace affected artifacts, and record the first fixed digest/version. For this lab, remove only the exact fake-token files/images/containers you created.

Knowledge check

Why does deleting a secret in a later Dockerfile RUN not prove removal?

A build check reports SecretsUsedInArgOrEnv. What is the least-destructive correction?

What is wrong with printing a redacted or transformed credential for debugging?

Why is sharing production credentials with a build job a trust-boundary failure?

A runtime container works only when DB_PASSWORD is set through -e. Which state should you inspect first?

Next lesson

Next: Checkpoint Lab — Secrets and Configuration Patterns, Runtime Injection, Environment Risk, Build Secrets, and External Secret Stores

Continue with the next lesson in the course sequence and carry forward the evidence-first Docker operating model.

Official references and version notes

Version/platform baseline, verified 2026-09-22.

Docker Engine 29.8.1 is the current Engine release; Buildx 0.37.1 and BuildKit 0.33.0 are the current upstream baselines used for feature notes; Compose v5.5.1 is the current Compose release. Docker documents build arguments and Dockerfile environment variables as inappropriate for secrets because sensitive values can persist in image metadata/history, while BuildKit secret/SSH mounts expose credentials only to the build step. Compose secrets are granted per service and delivered as files (on Linux, local Compose uses a single-file bind mount); that is not the same storage/trust model as Swarm secrets or an external secret manager. Labs therefore record the actually installed Engine, Buildx, BuildKit, Compose, context, platform, and secret-delivery path before drawing conclusions.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.