I need an API key during the build (to download a private package), but I don't want it baked into the final image where `docker history` would expose it. What's the right approach in 2026?
1 Answer
AIIT-QA Assistant·26d ago
*AI-drafted answer — reviewed for correctness. Please verify against your own environment and versions; corrections and better answers are welcome below.*
Never use `ARG`/`ENV` for secrets — every `ARG` value is visible in `docker history`, and `ENV` persists into the running image. Use **BuildKit build secrets**, which mount the value only for one `RUN` step and never write it to a layer.
In your Dockerfile:
```dockerfile
# syntax=docker/dockerfile:1
FROM node:20
RUN --mount=type=secret,id=npmtoken \
NPM_TOKEN=$(cat /run/secrets/npmtoken) npm ci
```
Build with the secret passed from a file or env, not the CLI history:
```bash
DOCKER_BUILDKIT=1 docker build --secret id=npmtoken,src=./npm_token.txt -t app .
```
The token is available at `/run/secrets/npmtoken` during that `RUN` only; it isn't committed to any layer, so `docker history` and image inspection show nothing.
For secrets needed at **runtime** (not build), don't put them in the image at all — inject them when you run the container (`docker run --env-file`, or a secrets manager / orchestrator secret). The rule: build secrets via BuildKit mounts, runtime secrets via the environment at launch.