docker-node icon indicating copy to clipboard operation
docker-node copied to clipboard

Permission issues with the default non-root user on npm start

Open mremes opened this issue 6 years ago • 11 comments

While building a hello-world application using node as the base image, I encountered this boot time (while running npm start) problem with the default non-root user's file permissions:

...
/webapp/node_modules/mkdirp/index.js:90
                    throw err0;
                    ^

Error: EACCES: permission denied, mkdir '/webapp/node_modules/.cache'
    at Object.mkdirSync (fs.js:775:3)
    at sync (/webapp/node_modules/mkdirp/index.js:71:13)
    at sync (/webapp/node_modules/mkdirp/index.js:77:24)
    at sync (/webapp/node_modules/mkdirp/index.js:77:24)
    at save (/webapp/node_modules/@babel/register/lib/cache.js:50:20)
    at internalTickCallback (internal/process/next_tick.js:70:11)
    at process._tickCallback (internal/process/next_tick.js:47:5)
    at Function.Module.runMain (internal/modules/cjs/loader.js:777:11)
    at executeUserCode (internal/bootstrap/node.js:342:17)
    at startExecution (internal/bootstrap/node.js:276:5)
    at startup (internal/bootstrap/node.js:227:5)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
...

The Dockerfile is below.

Notice the commented out command which changes the node user as the owner of the application working directory. That – obviously – fixes the permission issue.

FROM node:alpine

ENV FRONT_URL=http://localhost:5000

WORKDIR /webapp

COPY package.json .
RUN npm install

COPY config.js index.js logs.txt ./
COPY server ./server

EXPOSE 8000

# This fixes the problem
# RUN chown -R node: /webapp
USER node
CMD ["npm", "start"]

I'm not that familiar with Node so that I'd have intuition on whether this is related to some package in the packages.json or is this problem related to this project (though the stack trace looks like this is related to the npm internals).

mremes avatar Jan 13 '19 13:01 mremes

I guess you should place your app in a folder that is owned by the executing user or writable, e.g. /home/node/webapp.

see also https://github.com/nodejs/docker-node/issues/603#issuecomment-354765372

CCFenner avatar Jan 18 '19 08:01 CCFenner

@CCFenner that doesn't seem to solve the problem. Here's a Dockerfile with the suggested working directory. Running the commented out chown command fixes the problem again.

FROM node:alpine

ENV FRONT_URL=http://localhost:5000

WORKDIR /home/node/webapp

COPY package.json .
RUN npm install

COPY config.js index.js logs.txt ./
COPY server ./server

EXPOSE 8000

# This, again, fixes the problem
# RUN chown -R node: /home/node/webapp
USER node
CMD ["npm", "start"]

mremes avatar Jan 22 '19 08:01 mremes

If you are working in the user context you should be able to switch to user node in the beginning. Maybe that solves the permission issues.

CCFenner avatar Jan 22 '19 09:01 CCFenner

@mremes all of the COPY in your docker are run as root so the files created are owned by root. The USER directive should be before the WORKDIR command.

LaurentGoderre avatar Jan 22 '19 13:01 LaurentGoderre

If I remember correctly, if the WORKDIR command has to create a folder, it creates it as root so you can instead do

USER node

RUN mkdir /home/node/webapp

WORKDIR /home/node/webapp

LaurentGoderre avatar Jan 22 '19 13:01 LaurentGoderre

@mremes a bit of nitpick too but the port in your env var doesn't match the port you expose. Is that intentional?

LaurentGoderre avatar Jan 22 '19 13:01 LaurentGoderre

@CCFenner that intuitively should work (as the workdir should get created by the USER user) but it errors on build-time as npm install doesn't have permissions to install locally.

@LaurentGoderre that worked out, cool! The only thing is that that's not a documented practice. As it seems there are multiple, obvious ways to make it work. So my primary concern is with the documentation as it states that

FROM node:6.10.3
...
# **At the end**, set the user to use when running this image
USER node

So now it boils down to selecting the practice to document. I'm neither familiar with the contribution guidelines or the underlying parent Dockerfiles so if someone more close to the project can fix this, then that'd good.

RE nitpick: FRONT_URL is not related to the exposed port but is an endpoint URL (frontend server) to be whitelisted by that application (backend server) for CORS purposes.

It's fun to see that all this discussion spurred from my course assignment. I hope "fixing" this will result someone avoiding encountering this 😄

mremes avatar Jan 22 '19 21:01 mremes

IMHO it should probably be

FROM node

# Perform root tasks such as install OS package (via apt or APK)

USER node

# Copy your app and install your node dependencies

LaurentGoderre avatar Jan 22 '19 21:01 LaurentGoderre

Unless the app needs to modify its own source at runtime (which is almost never the case), it's a better practice to install as root.

pesho avatar Jan 23 '19 01:01 pesho

@pecho that was the original problem though. When code and modules are installed as root you get tons of permission issues.

LaurentGoderre avatar Jan 23 '19 03:01 LaurentGoderre

Guys there is a way to solve this in Docker.

https://docs.docker.com/engine/reference/builder/#copy

e.g. COPY --chown=node:node --from=build-image /home/node/app/remove_source_maps.sh /home/node/app/

basickarl avatar Jun 25 '19 09:06 basickarl