(EACCES: permission denied, mkdir '/usr/app/node_modules/.cache) How can I create a docker-compose file to make node_modules a non-root folder?

I'm trying to dockerize a simple create-react-app project. (Is the initial project after running npx create-react-app test, no files were changed).

The problem seems to be that in newer versions of React, they moved the annoying .eslintcache from the root folder to /node_modules/.cache, causing problems when the container is trying to run the application via docker-compose.

Dockerfile

FROM node:alpine

WORKDIR /usr/app

COPY package*.json ./

RUN npm install

RUN chown -R node.node /usr/app/node_modules

COPY . ./

CMD ["npm", "start"]

docker-compose

version: '3'
services: 
  test:
    stdin_open: true
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - CHOKIDAR_USEPOLLING=true
    volumes:
      - /usr/app/node_modules
      - .:/usr/app
    ports:
      - '3000:3000'

The container is logging this error message:

test_1   | Failed to compile.
test_1   | 
test_1   | EACCES: permission denied, mkdir '/usr/app/node_modules/.cache

As you can notice, I tried to set the node_modules folder owner to the node user (the default user for node:alpine), but it is not working; exploring the container, you can see that the node_modules folder is still owned by root:

drwxrwxr-x    5 node     node          4096 Apr 14 07:04 .
drwxr-xr-x    1 root     root          4096 Apr 14 07:08 ..
-rw-rw-r--    1 node     node           310 Apr 14 06:56 .gitignore
-rw-rw-r--    1 node     node           192 Apr 14 07:30 Dockerfile
-rw-rw-r--    1 node     node          3369 Apr 14 06:56 README.md
drwxrwxr-x 1061 root     root         36864 Apr 14 07:12 node_modules
-rw-rw-r--    1 node     node        692936 Apr 14 06:56 package-lock.json
-rw-rw-r--    1 node     node           808 Apr 14 06:56 package.json
drwxrwxr-x    2 node     node          4096 Apr 14 06:56 public
drwxrwxr-x    2 node     node          4096 Apr 14 06:56 src

I also tried to create the folder RUN mkdir -p /usr/app and use USER node but that end up in an issue where npm wasn't able to create the node_modules folder.

Is there any workaround where either .eslintcache is disabled or node_modules is owned by the node user?

Update

Apparently, this is occurring because I'm using Ubuntu and docker mounts volumes as root on Linux systems.


Solution 1:

Adding this line just after RUN npm install in your Dockerfile would solve the issue:

RUN mkdir -p node_modules/.cache && chmod -R 777 node_modules/.cache

Final Dockerfile

FROM node:alpine

WORKDIR /usr/app

COPY package.json .
RUN npm install

RUN mkdir node_modules/.cache && chmod -R 777 node_modules/.cache

COPY . .

CMD ["npm", "run", "start"]

Then you don't need to copy the node_modules folder from your local dir to the container. You can safely bookmark it.

Solution 2:

I've just stumbled across the same issue. If you're wondering how I dealt with it I simply added two lines before the last line. It worked like a charm.

FROM node:16.13.0-alpine

WORKDIR /app

COPY package.json ./
COPY package-lock.json ./

RUN npm config set unsafe-perm true
RUN npm install --silent

COPY . .

RUN chown -R node /app/node_modules

USER node

CMD ["npm", "start"]