docker build + private NPM (+ private docker hub)
Solution 1
I found a somewhat elegant-ish solution in creating a base image for your node.js / io.js containers (you/iojs
):
- log in to your private npm registry with the user you want to use for docker
- copy the
.npmrc
file that this generates
Example .npmrc
:
registry=https://npm.mydomain.com/
username=dockerUser
[email protected]
strict-ssl=false
always-auth=true
//npm.mydomain.com/:_authToken="someAuthToken"
- create a
Dockerfile
that copies the.npmrc
file appropriately.
Here's my Dockerfile
(based on iojs:onbuild
):
FROM iojs:2.2.1
MAINTAINER YourSelf
# Exclude the NPM cache from the image
VOLUME /root/.npm
# Create the app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Copy npm config
COPY .npmrc /root/.npmrc
# Install app
ONBUILD COPY package.json /usr/src/app/
ONBUILD RUN npm install
ONBUILD COPY . /usr/src/app
# Run
CMD [ "npm", "start" ]
- Make all your node.js/io.js containers
FROM you/iojs
and you're good to go.
Solution 2
In 2020 we've got BuildKit available. You don't have to pass secrets via COPY
or ENV
anymore, as it's not considered safe.
Sample Dockerfile
:
# syntax=docker/dockerfile:experimental
FROM node:13-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN --mount=type=ssh --mount=type=secret,id=npmrc,dst=$HOME/.npmrc \
yarn install --production --ignore-optional --frozen-lockfile
# More stuff...
Then, your build command can look like this:
docker build --no-cache --progress=plain --secret id=npmrc,src=/path-to/.npmrc .
For more details, check out: https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information
Solution 3
For those who are finding this article via google and are still looking for an alternative way that doesn't involve leaving you private npm tokens on your docker images and containers:
We were able to get this working by doing the npm install
prior to the docker build
(By doing this it lets you have your .npmrc
outside of your image\container). Once the private modules have been installed locally you can copy your files across to the image as part of your build:
# Make sure the node_modules contain only the production modules when building this image
COPY . /usr/src/app
You also need to make sure that your .dockerignore
file doesn't exclude the node_modules
folder.
Once you have the folder copied into your image, the trick is to to npm rebuild
instead of npm install
. This will rebuild any native dependancies that are effected by any differences between your build server and your docker OS:
FROM nodesource/vivid:LTS
# For application location, default from nodesource is /usr/src/app
# Make sure the node_modules contain only the production modules when building this image
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN npm rebuild
CMD npm start
Solution 4
I would recommend not using a .npmrc
file but instead use npm config set
. This works like a charm and is much cleaner:
ARG AUTH_TOKEN_PRIVATE_REGISTRY
FROM node:latest
ARG AUTH_TOKEN_PRIVATE_REGISTRY
ENV AUTH_TOKEN_PRIVATE_REGISTRY=${AUTH_TOKEN_PRIVATE_REGISTRY}
WORKDIR /home/usr/app
RUN npm config set @my-scope:registry https://my.private.registry && npm config set '//my.private.registry/:_authToken' ${AUTH_TOKEN_PRIVATE_REGISTRY}
RUN npm ci
CMD ["bash"]
![GTF](https://i.stack.imgur.com/kOThB.jpg?s=256&g=1)
GTF
Co-founder and CTO of Converge - using physical data from sensor networks to digitise the construction industry. I programme mostly in node.js / javascript and python, and am playing with clojure and rust. Occasionally I have to dip into C (sadface), and I use postgres and rabbitmq a lot.
Updated on January 16, 2022Comments
-
GTF over 2 years
I have an application which runs in a Docker container. It requires some private modules from the company's private NPM registry (Sinopia), and accessing these requires user authentication. The Dockerfile is
FROM iojs:latest
.I have tried:
1) creating an .npmrc file in the project root, this actually makes no difference and npm seems to ignore it 2) using env variables for
NPM_CONFIG_REGISTRY
,NPM_CONFIG_USER
etc., but the user doesn't log in.Essentially, I seem to have no way of authenticating the user within the
docker build
process. I was hoping that someone might have run into this problem already (seems like an obvious enough issue) and would have a good way of solving it.(To top it off, I'm using Automated Builds on Docker Hub (triggered on push) so that our servers can access a private Docker registry with the prebuilt images.)
Are there good ways of either: 1) injecting credentials for NPM at build time (so I don't have to commit credentials to my Dockerfile) OR 2) doing this another way that I haven't thought of ?
-
James Hush about 9 yearsI ended up doing a similar thing today. It's the only secret key out of all my projects that I need at build time :(. I think this is the best solution currently, thanks for posting your answer!
-
magohamote almost 8 yearsHere is the official dock about private npm repo and Docker: docs.npmjs.com/private-modules/docker-and-private-modules
-
Paul T. Rawkeen almost 4 yearsBeware
MAINTAINER
is deprecated, useLABEL
instead. -
Paul S over 2 yearsYou are using root user, security recommendation is to user
USER node
. However this is broken, see github.com/docker/for-mac/issues/3668. I don't have a solution yet.