Challenge, Medium,  on  Containers

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:

  1. The image still builds and runs correctly (the private dependency must be installed in the Dockerfile).
  2. 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.