Docker cookbook · Intermediate
Use private package credentials in a build without leaking them
Install from a private npm, PyPI or Maven registry during the build without the token ending up in the image.
Approach
Mount the credential only for the RUN step that needs it with a BuildKit secret mount. It never appears in a
layer, the image config or the build history.
Solution
# syntax=docker/dockerfile:1
FROM node:24-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]
docker build --secret id=npmrc,src=$HOME/.npmrc -t app:dev .
# in CI: docker build --secret id=npmrc,env=NPMRC_CONTENT ...
Pitfalls
ARG NPM_TOKENorENV NPM_TOKEN: visible indocker historyordocker inspect.COPY .npmrc .followed byRUN rm .npmrc: the file stays in the earlier layer.
Variations
- SSH mounts (
--mount=type=ssh) for private Git dependencies. - Build-time secrets from CI secret stores via
docker/build-push-action'ssecretsinput.
Further reading: Build secrets
Reference: https://docs.docker.com/build/building/secrets/
More Docker recipes
- Add a healthcheck to an HTTP service
- Build a layered image for a Spring Boot app
- Build a production image for a Node.js service
- Build a production image for a Python web app
- Build, cache and push images in GitHub Actions
- Build one image tag for amd64 and arm64
- Configure nginx from environment variables
- Develop with Compose and live reload