22

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.

  • 1
    I'd delete the `volumes:` so that you're actually running the code built into the image. That also avoids the sorts of permission problems you're describing, and means changes to your `package.json` file will be honored. You can directly run `node` without Docker to do development, and to run developer-only tools like `eslint`. – David Maze Apr 14 '21 at 09:57
  • 1
    I wondered if I can do this since I want a complete dockerized development environment; I have two other services (back and mongo) in the `docker-compose`. Plus, it seems started to happen after the last CRA release, that configuration that I posted worked in previous versions. – Sebastián Suárez Valencia Apr 14 '21 at 17:16

13 Answers13

38

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.

M. Usatai
  • 512
  • 3
  • 3
  • 2
    Note that this will only work if the corresponding /usr/app/node_modules volume is removed. Otherwise, after changing the dockerfile, the docker compose command will use the same volume as before without this change in permissions, and it will keep failing – Daniel García Rubio Jun 19 '22 at 22:22
5

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.

  • 1
    In my case I forgot to add the node_modules to the .dockerignore file, so even though I was creating a user and telling docker to use that user to install the packages, later the COPY command was overriding the node_modules in the container with the local one. – Aikanáro Nov 02 '22 at 12:28
4

This is caused by a long-standing issue with NPM changing its process's UID which is now fixed NPM 9.

Specifically, it is described in this NPM RFC comment:

Docker volume mounts use the UID:GID of the host machine. The changes npm has made to infer the execution user from the UID:GID effectively break docker setups where the host users UID:GID does not match the node user on the container. Setting UID:GID in a .env file for each developer in our application is cumbersome and overall ridiculous. Stop trying to infer best security practices when it comes to running scripts, your job is to be a package manager

This fix is called out prominently in the v9.0.0 changelog announcement.

Related changes in NPM tracker:

Brady
  • 41
  • 2
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"]
hazartilirot
  • 195
  • 1
  • 2
  • 11
1

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
1

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
Frank Escobar
  • 648
  • 5
  • 15
1

In the DOCKER-COMPOSE File remove the volumes where you trying to exculde node_modules. It will work

1

Well Its clearly shown you don't have access in node modules in your docker container.I tried a lot, but below given form works for me.

RUN mkdir -p /usr/src/app

RUN chmod +rwx /usr/src/app

WORKDIR /usr/src/app

first give READ WRITE EDIT permission via above command for your work-directory file, then it will working fine.

0

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'
0

Move 'USER node' higher

I was only using Docker (no docker-compose) and the solution was to move USER node to before COPY package*...

Peter L
  • 2,921
  • 1
  • 29
  • 31
0

In Linux, You have to give read and write permissions to your React App.

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

Example

sudo chmod a+rwx my-app/node_modules

Happy Coding :)

Abhinav Singwal
  • 467
  • 1
  • 3
  • 10
0

In Mac you can run sudo chown -R $(whoami) path

Example: sudo chown -R $(whoami) react-survey-app/node_modules/.cache/.eslintcache

Vikas s kumar
  • 287
  • 3
  • 3
-1

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.

Loïc
  • 11,804
  • 1
  • 31
  • 49