Docker-node: access npm private packages on dockerhub

Created on 8 Apr 2016  路  10Comments  路  Source: nodejs/docker-node

Hi I am a docker noob, so excuse me if this is a dumb question.

I want to build a npm package on dockerhub, but my package have private dependencies.

I try to authenticate by defining my NPM authToken as a build-time environment variable in my Dockerfile.

I thought a line like this in my Dockerfile should work:
ARG NPM_TOKEN=00000000-0000-0000-0000-000000000000
but I get a 404 error.

Will this strategy work, or is there another way for the build server to get access to my private repos?

Most helpful comment

Setting the NPM_TOKEN environment is not possible to authenticate with npm. See npm/npm#8356 for a more detailed description of the issue.

What you can do instead is the following:

FROM node:argon

ENV NPM_TOKEN "00000000-0000-0000-0000-000000000000"

RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
RUN npm install

CMD ['node' 'index.js'] 

All 10 comments

Setting the NPM_TOKEN environment is not possible to authenticate with npm. See npm/npm#8356 for a more detailed description of the issue.

What you can do instead is the following:

FROM node:argon

ENV NPM_TOKEN "00000000-0000-0000-0000-000000000000"

RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
RUN npm install

CMD ['node' 'index.js'] 

Ah great, thanks for the quick response!

This npm blog post is really pretty misleading...

Is this still the recommended way to use npm private package with Docker?

In order for this to work, i need to leave NPM_TOKEN inside my code base.

For the record (and because this issue have pretty good google indexation), you can achieve it safely using build-args in your CI system.

Build command

docker build --build-arg NPM_TOKEN={you token here} -t image:tag .

Dockerfile

FROM node:7
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc && \
  npm install && \
  rm ~/.npmrc

You may still be interested @tuananh

@PuKoren exactly what I need. Many thanks.

Watch out! Your token is stored as a commit message in the docker history!

Read: https://blog.risingstack.com/private-npm-with-docker/ and https://docs.npmjs.com/private-modules/docker-and-private-modules

@VolleMelk what do you recommend?

If put in file and then removed in the same command it should not be kept into any layer
This is ok:

FROM node:7
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc && \
  npm install && \
  rm ~/.npmrc

but this is not:

FROM node:7
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
RUN  npm install
RUN  rm ~/.npmrc

@PuKoren It's not about the layer, it's in the _commit message_:

Dockerfile:

FROM microsoft/dotnet-framework:3.5
ARG NPM_TOKEN

RUN echo //registry.npmjs.org/:_authToken=%NPM_TOKEN% > C:\\.npmrc

Run with

docker build --build-arg NPM_TOKEN=this_is_my_test_token .

Console output:

D:\docker\test> docker build --build-arg NPM_TOKEN=this_is_my_test_token .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM microsoft/dotnet-framework:3.5
 ---> a0edc80e79f8
Step 2/3 : ARG NPM_TOKEN
 ---> Using cache
 ---> 1f0b9e5e6fd6
Step 3/3 : RUN echo //registry.npmjs.org/:_authToken=%NPM_TOKEN% > C:\\.npmrc
 ---> Running in 4620a638f2ec
 ---> 0a1a95f7f471
Removing intermediate container 4620a638f2ec
Successfully built 0a1a95f7f471

So far so good (it's not interpolating the environment variable, showing %NPM_TOKEN% instead of the actual value). And because of the redirect output operator (>) we're not seeing the result of the echo command.

But when we check the docker history of said image with docker history --no-trunc 0a1a95f7f471

D:\docker\test> docker history --no-trunc 0a1a95f7f471
IMAGE               CREATED        CREATED BY                                                                                                                                                                                                                   SIZE                COMMENT
sha256:0a1a95f7f471 3 minutes ago  |1 NPM_TOKEN=this_is_my_test_token cmd /S /C echo //registry.npmjs.org/:_authToken=%NPM_TOKEN% > C:\\.npmrc                                                                                                                  16.1MB
sha256:1f0b9e5e6fd6 3 minutes ago  cmd /S /C #(nop)  ARG NPM_TOKEN                                                                                                                                                                                              41kB
sha256:a0edc80e79f8 4 months ago   cmd /S /C DISM /Online /Add-Package /PackagePath:C:\build\microsoft-windows-netfx3-ondemand-package.cab &     DISM /Online /Add-Package /PackagePath:C:\build\patch\Windows10.0-KB3213986-x64.cab  &     rd /s /q C:\build   1.1GB
<missing>           4 months ago   cmd /S /C #(nop) ADD dir:3cf624d67eb78708ae0d25961d5ee719003484c897ad88949ce7509ea2c43768 in \build                                                                                                                          1.24GB
<missing>           4 months ago   Install update 10.0.14393.1480                                                                                                                                                                                               2.56GB
<missing>           11 months ago  Apply image 10.0.14393.0                                                                                                                                                                                                     7.68GB

We can see the value of the NPM_TOKEN as a build argument.

Perhaps squashing the commits will solve this, but I haven't got any experience with that

Update: I built an image using the same Dockerimage using docker build --build-arg NPM_TOKEN=this_is_my_test_token --squash . but it's still in the docker history

I even altered the Dockerfile to accept another ARG MORE_TOKENS and re-ran the build:

docker build --build-arg NPM_TOKEN=this_is_my_test_token --build-arg MORE_TOKENS=this_is_not_my_test_token --squash .

Docker history:

IMAGE                                                                     CREATED             CREATED BY                                                                                                                                                                                                                   SIZE                COMMENT
sha256:e9c0dba588007aad59869af9e4b0577140fe63a317a4c266eecc77ce7a31bf9c   26 seconds ago                                                                                                                                                                                                                                   16.1MB              merge sha256:b41440e2d6ca62e8d83f6453f00e3b52240dbc9869bbc1dda377eb1dc33770b0 to sha256:a0edc80e79f854bc3e2987e189e9ab253f0aef37448689d4279a0bfa0d3d4d55
<missing>                                                                 29 seconds ago      |2 MORE_TOKENS=this_is_not_my_test_token NPM_TOKEN=this_is_my_test_token cmd /S /C echo //registry.npmjs.org/:_authToken=%NPM_TOKEN% > C:\\.npmrc   
[.. more of the same here..]

@tuananh I didn't really have a solution for this, but then again I didn't really need the token during my _build_. I only need the token when running the container.

NPM interpolates environment variables inside .npmrc. I create an .npmrc file with

# [.. more Dockerfile here ..]
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
# [.. more Dockerfile here ..]

And I start the docker container with docker run --env NPM_TOKEN=this_is_my_token docker-image.

By using the docker run --env argument for secrets instead of the docker build ENV directive or docker build ARG directive with --build-arg argument has the following benefits:

  • The secret is not saved anywhere (layer or commit message) during build time
  • If the secret changes, you do not need to rebuild your docker image
  • You can use the same container with different secrets (ie: CI server and local development computer)

Yes, you need to supply your NPM_TOKEN each time you start the docker container.. but safety first ;-)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

actualben picture actualben  路  3Comments

kmetsalu picture kmetsalu  路  5Comments

eyaylagul picture eyaylagul  路  3Comments

kmleow picture kmleow  路  5Comments

linux17kartik picture linux17kartik  路  4Comments