docker-node
docker-node copied to clipboard
Permission issues with the default non-root user on npm start
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).
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 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"]
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.
@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.
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
@mremes a bit of nitpick too but the port in your env var doesn't match the port you expose. Is that intentional?
@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 😄
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
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.
@pecho that was the original problem though. When code and modules are installed as root you get tons of permission issues.
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/