Docker-node: Permissions error - after declaring USER and WORKDIR

Created on 16 May 2018  路  20Comments  路  Source: nodejs/docker-node

I have this:

FROM node:9
USER node
WORKDIR /home/node/app
COPY package.json .
RUN npm install --loglevel=warn;

and I get:

Step 20/24 : RUN  npm install --loglevel=warn;
 ---> Running in 8aa9717ac2be
npm WARN checkPermissions Missing write access to /home/node/app
npm ERR! path /home/node/app
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/home/node/app'
npm ERR!  { Error: EACCES: permission denied, access '/home/node/app'
npm ERR!   stack: 'Error: EACCES: permission denied, access \'/home/node/app\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/home/node/app' }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/node/.npm/_logs/2018-05-16T17_37_34_421Z-debug.log

this seems completely crazytown. How does my user not have access to this directory by default considering it was "created" by the WORKDIR command after USER was declared?

Most helpful comment

This has been a nightmare for me...
Can this be documented as what the Best Practice is suggesting to use USER node but doesn't provide a viable config?

All 20 comments

If I remember correctly, folder created by WORKDIR are owned by root even if they are created after the USER directive. Try creating the folder first

Yeah I tried that too, I still get permissions errors with this:

RUN mkdir -p /home/node/app
WORKDIR /home/node/app

I have the same issue

Just do this and call it a day lol

 RUN sudo chmod -R 777 /home/node/app

F it lol...just run that before and after npm install and you should be g2g. Even better, do this:

 RUN sudo chmod -R 777 /home/node

Correct me if I'm wrong. The doc is recommending us to declare user as node because Docker runs container as root by default.

So you declare it at the end

FROM node:9
WORKDIR /home/node/app
COPY package.json .
RUN npm install --loglevel=warn;
USER node

You should not run node as root, bad things can happen (see the last issue with changing files permissions).
I think you need to make sure that when the node user is created it has the right permissions over /home/node (eg. https://github.com/vvo/selenium-standalone/blob/master/Dockerfile#L29). Maybe the permissions are not well propagated to subsequent directories:

@ORESoftware do a docker exec ls -al /home/node/app and check who owns that?

@ORESoftware i believe this issue happens because only the /home/node directory is owned by the node user in the default node image. The /app directory is created and owned by root. If you change the WORKDIR to /home/node it should work.

@albertoantunes You are right, it worked for me. Here is my Dockerfile, hope it helps some with the same problem.

FROM node:8
USER node
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
WORKDIR /home/node
COPY package.json .
RUN npm install --only=prod
COPY . .

This has been a nightmare for me...
Can this be documented as what the Best Practice is suggesting to use USER node but doesn't provide a viable config?

@ORESoftware
I had the same issue, you can specify the user with the COPY command. See my Dockerfile:

FROM node:latest
USER node

ARG APP=app
ARG HOME=/home/node

ENV NPM_CONFIG_PREFIX=$HOME/.npm-global
ENV PATH=$PATH:$HOME/.npm-global/bin

COPY --chown=node:node ./$APP/package*.json $HOME/$APP/

The COPY is done by default with root (source):

All new files and directories are created with a UID and GID of 0, unless the optional --chown flag specifies a given username, groupname, or UID/GID combination to request specific ownership of the copied content.

Note that COPY --chown won't work with all docker versions (see here). Mine is 18.03.1-ce.

I had the same issue and here's my Dockerfile. This fixed it

#Choose the base image for the build
FROM node:8-alpine
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
RUN ["chmod", "755", "your-script.sh"]
EXPOSE 4140
CMD [ "node", "index.js" ]

The trick was to use

RUN ["chmod", "755", "your-script.sh"]

This worked for me.
A combination of using the existing /home/node dir to host the app files and specifying the user and group for the COPY commands.

FROM node:12.10.0-slim

USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app

COPY --chown=node:node package.json .
COPY --chown=node:node yarn.lock .

RUN yarn --pure-lockfile

COPY --chown=node:node . .

EXPOSE 4040

CMD [ "node", "index.js" ]

another working approach: start docker run with
-e npm_config_cache=/path/to/cache
and setup the folder e.g. in working dir

then I could use non-root user + get npm install working as it does not try to create a /.npm folder

I had a problem of creating files / directories while node app is running (logs directory for example, when I don't care about them and do not mount logs dir from host). Here is my solution:

RUN chown node:node /usr/src/app
USER node
CMD ["npm", "start"]

That way app can create new files / directories inside of /usr/src/app. All other files/dirs are owned by root, and can not be modified by app (totally fine for me).

yes but e.g. Jenkins setup working dir in pipeline approach on its own and you cannot really/easy/good overwrite it and you have to handle a different working dir so

@derhecht Sorry did not understood completely. If your comment was addressed to me, and it meant to say: when app is built on Jenkins it causes errors because of .npm dir, then here is the solution that we are using:

environment {
  HOME = '.'
}

Also do not forget to include .npm into your .dockerignore so that its content is not sent to daemon during build (not a big deal, but still).

This issue/discussion is currently the top Google hit for the terms:

docker Error: EACCES: permission denied, scandir

[ None of the solutions in this thread were the cause of my specific issue, so I'm adding a comment here. ]

In my case, I created a new LVM2 logical volume and mounted it to /var/lib/docker (i.e. so that Docker would have room to grow). Afterward, my builds began failing with the error message I quoted above. I determined the cause to be SELinux context. The fix was simply:

sudo /usr/sbin/restorecon -R /var/lib/docker

may anyone could use it, we solved Jenkins Docker scripted pipeline build with the following setup/commands/variables:
docker.image('node:8').inside("-e npm_config_cache=$env.WORKSPACE/.npm") { sh "npm install && export BABEL_CACHE_PATH=$env.WORKSPACE/.babel.json && npm run build" }

Note this comment in the Best Practices documentation: # At the end, set the user to use when running this image. What I ended up doing is running the Dockefile as the root user, then copying everything I need, using the --chown node:node flag in the COPY command when needed, then changing the user to node before running the application.

FROM node:14.15.4-slim
WORKDIR /home/node
COPY --from=build --chown=node:node ./ /home/node
ENV NODE_ENV="production"
ENV PORT="8080"
EXPOSE 8080
USER node
CMD ["node", "app.js"]

hi guys,

sometimes this happens - when the container you are trying to use (FROM) - set up the user already and it is different from the root. In this case permission is denied

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dgonzalez picture dgonzalez  路  18Comments

arcanis picture arcanis  路  26Comments

MylesBorins picture MylesBorins  路  17Comments

Hypnosphi picture Hypnosphi  路  19Comments

mikemaccana picture mikemaccana  路  24Comments