[Docker Course 4-13] Issue on npm install step

Hello there,

I’ve facing an issue while installing the app dependencies, returning an user permission denied while accessing the /app directory. Can you guys tell what am I missing?

Here is the Dockerfile:

FROM node:14.16.0-alpine3.13

RUN addgroup app && adduser -S -G app app
USER app

WORKDIR /app
COPY . .

RUN npm install


ENV API_URL=http://api.myapp.com/
EXPOSE 3000

and after running docker build -t react-app ., I get the following error:

Step 6/8 : RUN npm install
 ---> Running in 36bd85f20663
npm WARN deprecated babel-eslint@10.1.0: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated querystring@0.2.1: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
npm WARN deprecated rollup-plugin-babel@4.4.0: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-babel.
npm WARN deprecated @hapi/joi@15.1.1: Switch to 'npm install joi'
npm WARN deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated sane@4.1.0: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated @hapi/address@2.1.4: Moved to 'npm install @sideway/address'
npm WARN deprecated @hapi/topo@3.1.6: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/hoek@8.5.1: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/bourne@1.3.2: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated core-js@2.6.12: core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.
npm WARN checkPermissions Missing write access to /app
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^2.1.3 (node_modules/react-scripts/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/watchpack-chokidar2/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/webpack-dev-server/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN @babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.14.5 requires a peer of @babel/core@^7.13.0 but none is installed. You must install peer dependencies yourself.
npm WARN tsutils@3.21.0 requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta but none is installed. You must install peer dependencies yourself.

npm ERR! code EACCES
npm ERR! syscall access
npm ERR! path /app
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, access '/app'
npm ERR!  [Error: EACCES: permission denied, access '/app'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/app'
npm ERR! }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/app/.npm/_logs/2021-07-17T19_24_29_469Z-debug.log
The command '/bin/sh -c npm install' returned a non-zero code: 243

Hi,

here the solution:

  • since app user don’t have permissions on app folder and files that were created by root user,
    you need to give it after created user and before switch to app user

  • here the command : RUN chown -R app /app ,
    where here you are changing the owner of the folder and the files that in the future are created.

here final docker file:


FROM node:14.16.0-alpine3.13

WORKDIR /app/

# chown -R change the owner of app folder to app

# the node_modules will be owned by app too

RUN addgroup app && adduser -S -G app app && chown -R app /app

USER app

# When using COPY with more than one source file, the destination must be a directory and end with a /

COPY package*.json ./

RUN npm i

# When using COPY with more than one source file, the destination must be a directory and end with a /

COPY . ./

ENV API_URL=http://api.app.test

EXPOSE 3000

CMD [ "npm", "start" ]
3 Likes

Hi I have the same problem I try use your Dockerfile but I have next error:
Building backend
Sending build context to Docker daemon 292.9kB
Step 1/10 : FROM node:14.16.0-alpine3.13
—> 50bfd284aa0d
Step 2/10 : WORKDIR /app/
—> Using cache
—> 8287264d9518
Step 3/10 : RUN addgroup app && adduser -S -G app app && chown -R app /app
—> Using cache
—> eec0bd9ac2b4
Step 4/10 : USER app
—> Using cache
—> d7af4c69f930
Step 5/10 : COPY package*.json ./
—> Using cache
—> fb0c7dd10b1e
Step 6/10 : RUN npm i
—> Running in 8c671a881e9b
npm WARN vidly-backend@1.0.0 No description
npm WARN vidly-backend@1.0.0 No repository field.

npm ERR! Maximum call stack size exceeded

npm ERR! A complete log of this run can be found in:
npm ERR! /home/app/.npm/_logs/2021-08-20T04_06_12_916Z-debug.log
The command ‘/bin/sh -c npm i’ returned a non-zero code: 1
ERROR: Service ‘backend’ failed to build : Build failed

I researched and tested for 6 Hours and found that the below SCRIPT 1 as shown in Mosh’s lecture video is working only if you use the same version of node in video.

SCRIPT 1 - From Video

FROM node:14.16.0-alpine3.13

RUN addgroup app && adduser -S -G app app
USER app

WORKDIR /app

RUN npm install
EXPOSE 3000

CMD [“npm”, “start”]

SCRIPT 2 -

Latest and other alpine versions have default use NODE which is overriding our app users so below is the solution to use both NODE user and our app users.

###Using custom user i.e. app###

FROM node:16.10.0-alpine3.14

RUN addgroup app && adduser -S -G app app

USER app

WORKDIR /app

COPY --chown=app:node package*.json ./

RUN npm install

COPY --chown=app:node . .

EXPOSE 3000

CMD [“npm”, “start”]

###Using default user i.e. node###

FROM node:16.10.0-alpine3.14

RUN addgroup app && adduser -S -G app app

USER app

WORKDIR /app

COPY --chown=node:node package*.json ./

RUN npm install

COPY --chown=node:node . .

EXPOSE 3000

CMD [“npm”, “start”]

1 Like

I am also getting this error eventhough i’m using EXACTLY the same versions he uses in his course. Wouldn’t it be a good idea to fix the course instead of digging hyper-deep to try to find a work-around (that i don’t understand) to this problem ?

2 Likes

Thanks for working six hours to fix this. Unfortunately it does not work for me. I thought avoiding this kind of situation was one of the essential points of using Docker in the first place …
This is my error message from RUN npm install:

Error: EACCES: permission denied, mkdir ‘/app/node_modules’

@ [jediampm] This actually worked, thank you! I had that idea myself, but did not know about -R, so I failed. Linux is killing me …

EDIT: In fact, not so lucky after all. Trying to run the image, just another error:

Error: EACCES: permission denied, scandir ‘/app/src’

… and no idea where to fix the permissions. Anyone?

Maybe I’ve got it now. I had an error in the run command. The correct one is:

docker run -it react-app sh

EDIT: Sorry, this does not work either. There is not error message with this, but the script won’t compile or run either. Back to square one.

Perhaps an explanation why it works for Mosh in the video from this article: https://vsupalov.com/docker-shared-permissions/

if you’re using something like docker on mac, you won’t run into those permission issues, as the file sharing is done through NFS and your local files will have the right user.

And Mosh happens to use a Mac, so he does not see the issue. (Me: Debian on Chromebook)

EDIT2:
Finally got it to run by slightly changing the order of commands. This is my Dockerfile now:

FROM node:14.19.0-alpine3.14

#RUN apk add sudo

WORKDIR /app/

#Does not work:  https://vsupalov.com/docker-shared-permissions/

# When using COPY with more than one source file, the destination must be a directory and end with a /

COPY package*.json ./

RUN npm i

# When using COPY with more than one source file, the destination must be a directory and end with a /

COPY . ./

#https://github.com/mhart/alpine-node/issues/48
#The -S flag will add to system group which is equivalent to -r in Ubuntu.
RUN addgroup -S app  &&  adduser -S -G app app  &&  chown -R app /app

USER app

ENV API_URL=http://api.app.test

EXPOSE 3000

CMD [ "npm", "start" ]

Below is my commented Dockerfile which works, for those who are looking for a solution to the permission problems encountered.

NOTE: My directory structure looks like this:

Parent Root
├── Dockerfile
└── react-app
└── […]

So I’m copying “react-app”. Yours is different if you’re following the video exactly, so your COPY instructions will need to be altered.

# Create a node base image running node 16.14.0 on Alpine linux version 3.15
FROM node:16.14.0-alpine3.15

# As root, create a system-user group and system user
RUN addgroup app && adduser -S -G app app

# As root, create the application directory and reassign to system user and group
RUN mkdir /app && chown app:app /app

# Switch from root user to newly created system user
USER app

# Set working directory to be newly create /app directory, which app user owns
# ..., see note on previous RUN instruction
WORKDIR /app

# Copy and set owner of 3rd party application files
# - The --chown option would be required to allow system user access if /app were
#   ...not already owner, e.g.: COPY --chown=app:app react-app/package*.json
# - Copying only files required for 3rd party installation and then installing
#   ...the 3rd party libraries optimizes docker's image re-build process by 
#   ...separating/isolating these steps in their own layer. Doing so helps 
#   ...better utilize docker's caching mechanisms ("image layers") for rebuilds
COPY react-app/package*.json .

# Install 3rd-party application files
# - See previous note about optimization, caching, and image layers
# - Note: You'd get a permission error on build at this point IF system user (app)
#   ...does not own/have rwx permissions on /app directory.
RUN npm install

# Copy and set owner of application files 
# - The --chown option would be required to allow system user to utilize files if
#   ...system user were not already owner of /app, e.g.: COPY --chown=app:app react-app/
# - See previous note about optimization, caching, and image layers
COPY react-app/ .

# Set environment variables as desired
ENV API_URL=http://api.myapp.com

# Expose container on desired port
EXPOSE 3000

# Execute application start command
# - Prefer the 'execute form' of the CMD directive, ie. CMD ['npm', 'start']
#   ...The execute form will run the command in the current shell.
# - The 'shell form' (CMD npm start) would execute command in new shell, which,
#   ...unless required for some reason, is less efficient and starts new process
CMD ["npm", "start"]

Below is my commented Dockerfile which works, running on MacOS, FWIW.

Note my directory structure doesn’t match video exactly. So you’ll need to modify the COPY directives appropriately. Here’s my directory structure:

Parent Root
├── Dockerfile
└── react-app
└── […]

And here’s my commented Dockerfile:

# Create a node base image running node 16.14.0 on Alpine linux version 3.15
FROM node:16.14.0-alpine3.15

# As root, create a system-user group and system user
RUN addgroup app && adduser -S -G app app

# As root, create the application directory and reassign to system user and group
RUN mkdir /app && chown app:app /app

# Switch from root user to newly created system user
USER app

# Set working directory to be newly create /app directory, which app user owns
# ..., see note on previous RUN instruction
WORKDIR /app

# Copy and set owner of 3rd party application files
# - The --chown option would be required to allow system user access if /app were
#   ...not already owner, e.g.: COPY --chown=app:app react-app/package*.json
# - Copying only files required for 3rd party installation and then installing
#   ...the 3rd party libraries optimizes docker's image re-build process by 
#   ...separating/isolating these steps in their own layer. Doing so helps 
#   ...better utilize docker's caching mechanisms ("image layers") for rebuilds
COPY react-app/package*.json .

# Install 3rd-party application files
# - See previous note about optimization, caching, and image layers
# - Note: You'd get a permission error on build at this point IF system user (app)
#   ...does not own/have rwx permissions on /app directory.
RUN npm install

# Copy and set owner of application files 
# - The --chown option would be required to allow system user to utilize files if
#   ...system user were not already owner of /app, e.g.: COPY --chown=app:app react-app/
# - See previous note about optimization, caching, and image layers
COPY react-app/ .

# Set environment variables as desired
ENV API_URL=http://api.myapp.com

# Expose container on desired port
EXPOSE 3000

# Execute application start command
# - Prefer the 'execute form' of the CMD directive, ie. CMD ['npm', 'start']
#   ...The execute form will run the command in the current shell.
# - The 'shell form' (CMD npm start) would execute command in new shell, which,
#   ...unless required for some reason, is less efficient and starts new process
CMD ["npm", "start"]