I have the following Dockerfile for a React app:
## base image
FROM node:11.12.0-alpine
## set working directory
WORKDIR /usr/src/app
## add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
## install and cache app dependencies
COPY package.json /usr/src/app/package.json
COPY package-lock.json /usr/src/app/package-lock.json
RUN npm install react-scripts@3.0.1 -g --silent
RUN chown -R node:node .
USER node
RUN npm ci
## start app
CMD ["npm", "start"]
After setting up the work directory I copy the package.json
and package-lock.json
to Docker. Then I install a global package (react-scripts
). After that, I switch the owner of the working directory to the non-root user node
.
Then I install the rest of the packages with npm ci
as a normal user and start the app.
What happens when I want to add another package to my dependencies?
When I try to install a package locally, I get permission errors:
Missing write access to services/client/node_modules
errno -13
Error: EACCESS: permission denied, access 'services/client/node_modules'
What happens when I update package.json
and then run docker-compose build
?
npm ERR! cipm can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.
The command npm ci
installs packages from a clean slate and relies on package-jock.json
:
This command is similar to npm-install, except it’s meant to be used in automated environments such as test platforms, continuous integration, and deployment – or any situation where you want to make sure you’re doing a clean install of your dependencies. It can be significantly faster than a regular npm install by skipping certain user-oriented features. It is also more strict than a regular install, which can help catch errors or inconsistencies caused by the incrementally-installed local environments of most npm users.
Solution
Install the npm package via Docker/docker-compose. For example:
docker-compose run --rm client sh -c 'npm install'
(You can see my docker-compose.yml
file on GitHub.)
Then rebuild the docker images and run them:
docker-compose up -d --build