(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?

Viewed 18942

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.

7 Answers

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.

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"]

If you have a local node_modules folder delete it before running docker or docker-compose

Because there might have been another situation which causes EACCES: permission denied, mkdir '/usr/app/node_modules/.cache

This might be a case that you previously run this react-app with local node_modules file then deleted the file to use the container node_module.

So after deleting the whole folder it still recreates the folder and keeps a .cache file in it which is generally not visible.

So when you bookmark all file using `".:/usr/app" in docker-compose.yml or -v "$(pwd):/usr/app" it tries to bookmark that cache file stored in that local_node modules repo and causes all the fuss.

The solution I came out with was installing the node_modues locally and then modify the Dockerfile to copy everything into the container and use that as a volume instead of installing and bookmarking node_modules during the build process. I know it's not the best approach to this problem, but it's an easy solution for something I've been trying to solve for days.

Dockerfile

FROM node:alpine

WORKDIR /usr/app

COPY . ./

CMD ["npm", "start"]

docker-compose

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

I had the same issue.

The thing is, I used vue create inside /tmp, and then moved the content of the created folder inside my volume.

Which apparently npm is not too fond of.

So I removed node_modules, and recreated it using npm install, now it works like a charm.

Well, It is clearly showing that you don't have read, write and execute permission in your node modules folder and you will probably see a lock icon appearing on the node module folder.

FOR UBUNTU any version

sudo chmod a+rwx <path>/your-project-folder/node_modules

EXAMPLE

sudo chmod a+rwx Desktop/react-app/node_modules

explanation

  • chmod - to change permission
  • a - all
  • rwx - read, write and execute

To fix that issue in KUBERNETES, you have to mount an empty dir volume with the path directory /app/.next/cache. Check the example.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  template:
    metadata:
      labels:
        type: my-label
    spec:
      containers:
        image: ghcr.io/myimage
        imagePullPolicy: Always
        name: my-site
        ports:
        - containerPort: 3000
          name: http
          protocol: TCP
        volumeMounts:
        - mountPath: /app/.next/cache
          name: cache
      volumes:
      - emptyDir: {}
        name: cache
Related