Install a Private npm Package in a Dockerfile Without Leaking Credentials
Your team's Node.js application depends on a private npm package (@mycompany/logger)
hosted on an internal registry. The project directory ~/app/ includes an .npmrc file
with the credentials needed to install the package.
A colleague wrote a Dockerfile to containerize the application. They were careful to
add a RUN rm -f .npmrc step after installing dependencies to remove the credentials from the container filesystem.
But is that really enough to protect them?
Take a moment to explore the project:
cat ~/app/Dockerfile
cat ~/app/package.json
cat ~/app/.npmrc
Step 1: Build and push the image
Build the container image using the original, unmodified Dockerfile
and push it to registry.iximiuz.com:
docker build -t registry.iximiuz.com/my-app:insecure ~/app/
docker push registry.iximiuz.com/my-app:insecure
Step 2: Fix the credential leak
The RUN rm approach clearly isn't enough. Your task is to rewrite ~/app/Dockerfile
so that:
- The image still builds and runs correctly (the private dependency must be installed in the Dockerfile).
- The registry credentials never appear in any image layer.
Push the fixed image as registry.iximiuz.com/my-app:v1.0.0:
docker push registry.iximiuz.com/my-app:v1.0.0
Hint 1 - Why does 'RUN rm' not work?
Docker images are made of Layers.
Each filesystem-mutating instruction in a Dockerfile
(COPY, ADD, RUN, etc.) creates a new layer. RUN rm -f .npmrc only removes
the file in its and the consequent layers - the earlier layers starting with COPY .npmrc
still contain the file. Anyone with access to the image can extract individual
layers and recover the credentials.
Hint 2 - How to provide credentials without baking them in?
Docker supports build secrets - files that are temporarily mounted into a build step without being written to any layer.
Look into the RUN --mount=type=secret Dockerfile syntax and the corresponding
docker build --secret CLI flag.