Stage 4 · Provision
Registries & Security
Secrets
Keep secrets out of layers using BuildKit secrets, runtime mounts, env-file risks, and secret rotation.
Secret Exposure Risks
Secrets in container images are one of the most common security vulnerabilities. Hardcoded API keys, database passwords, and certificates in Dockerfiles end up in image layers, visible to anyone with access to the image. Even environment variables are visible in docker inspect.
| Method | Risk Level | Exposure |
|---|---|---|
| Hardcoded in Dockerfile | Critical | Visible in image history forever |
| ENV in Dockerfile | High | Visible in docker inspect |
| Environment variable at runtime | Medium | Visible in docker inspect and process listing |
| BuildKit secret mount | Low | Not in any layer, not in inspect |
| Docker secret | Low | Mounted as files, not in layers |
BuildKit Secrets
BuildKit secret mounts let you use secrets during the build process without including them in image layers. The secret is mounted temporarily during the RUN instruction and never stored in the image.
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
# Mount npm token as a secret during install
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci
COPY . .
CMD ["node", "server.js"]Build with: docker build --secret id=npmrc,src=.npmrc -t myapp . The .npmrc file is mounted during npm ci but never appears in any layer. It is not in docker history or the final image.
# SSH key for private repositories
docker build --secret id=ssh,src=$HOME/.ssh/id_rsa -t myapp .
# AWS credentials
docker build --secret id=aws,src=$HOME/.aws/credentials -t myapp .
# Git token
docker build --secret id=github_token,env=GITHUB_TOKEN -t myapp .The src flag reads from a file. The env flag reads from an environment variable. Both approaches keep the secret out of image layers.
Runtime Secret Mounts
# Mount a secret file at runtime
docker run -v /path/to/secret:/run/secrets/api_key:ro myapp
# Using Docker secrets (Swarm mode)
docker secret create api_key secret.txt
docker service create --secret api_key myapp
# Using tmpfs for in-memory secrets
docker run --tmpfs /run/secrets:rw,noexec myapp
# In compose.yaml
docker run -v ./secrets:/run/secrets:ro myappRuntime secret mounts provide secrets as files in /run/secrets/. The tmpfs option stores them in memory only. This is more secure than environment variables for large secrets.
Env File Risks
Environment variables containing secrets are visible in docker inspect, /proc/PID/environ, and process listings. They also appear in application logs if the application prints its environment. Use secret files instead of environment variables for sensitive data.
# Environment variables are visible everywhere
docker inspect mycontainer --format '{{.Config.Env}}'
# [DATABASE_URL=postgres://user:password@db:5432/app]
# Visible in process listing
docker exec mycontainer cat /proc/1/environ | tr ' ' '
'
# Even in docker history
docker history myapp --no-trunc | grep DATABASE_URLEnvironment variables are the least secure way to handle secrets. They persist in multiple places and are visible to anyone with Docker access.
ENV instructions in Dockerfiles bake secrets into image layers. Even if you override them at runtime, the original values are in the image history. Use BuildKit --mount=type=secret for build-time secrets.
Docker Secrets
Docker secrets are encrypted at rest and in transit. They are only available to services that explicitly request them. In Swarm mode, secrets are managed by the cluster and mounted as files in /run/secrets/.
# Create a secret
echo "mydbpassword" | docker secret create db_password -
# Create from a file
docker secret create api_key /path/to/api_key.txt
# Use in a service
docker service create \
--name api \
--secret db_password \
--secret api_key \
myapp
# Secrets are mounted at /run/secrets/db_password
# and /run/secrets/api_keyDocker secrets are encrypted in the Raft log and only decrypted on nodes running the service. They are mounted as files, not environment variables, preventing accidental exposure.
Secret Rotation
- Rotate secrets regularly — set calendar reminders
- Use short-lived tokens (OIDC, temporary credentials)
- Update secret in the secret store and restart services
- Verify old secrets are no longer in use
- Audit secret access logs
- Automate rotation where possible
For production, use HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager. These systems provide audit logging, automatic rotation, and fine-grained access control. Never store secrets in version control.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.