skip to Main Content

We are trying to deploy a Node app to DigitalOcean using Docker. When I try to spin the app up I get this error:

npm ERR! code EACCES
npm ERR! syscall open
npm ERR! path /app/package.json
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, open '/app/package.json'
npm ERR!  [Error: EACCES: permission denied, open '/app/package.json'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'open',
npm ERR!   path: '/app/package.json'
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.

I have created a node user with sudo access, so I’m unsure how to address this issue. Dockerfile here:

# get node distro - should be consistent across environments
FROM --platform=linux/amd64 node:16.17.0

# copy package.json etc FIRST. any changes here invalidate cache for rest of file
# see https://docs.semaphoreci.com/article/81-docker-layer-caching
COPY package.json package-lock.json app/

# create home dir, where the app will be run
WORKDIR /app

# install our dependencies, for now we want to install ALL deps, including dev ones
# put before COPY, any changes in the cwd will invalidate the cache for this layer
RUN npm ci --platform=linux --progress=false

# below this point we don't need to worry about the cache
# copy everything not in .dockerignore to /app
COPY . .

# make sure we're not running root
USER node

# make sure node is owned by non-root user, otherwise node app will exit with 1
COPY --chown=node:node . /app

# expose ports to outside world
EXPOSE 3002 3003

CMD ["npm", "start"]

EDIT: Someone requested the method used to start the container. Here is that command:

docker-compose up -d --force-recreate --remove-orphans

EDIT: Including docker-compose.yml file by request.

this is the docker-compose file we use for running the site locally

# use as template for prod file on the remote server
# any changes made should be made there as well
version: '3'
services:
  app:
    image: image/name
    container_name: container_name
    command: "npm start"
    environment:
      - NODE_ENV=production
    ports:
      - "127.0.0.1:3002:3002"
    working_dir: /app
    volumes:
      - .:/app

2

Answers


  1. Your main issue are these lines in your docker-compose file:

    volumes:
      - .:/app
    

    They map the current directory to the /app directory in the container and hides all the files in the image, since they’re replaced with the current directory on the host.

    Usually when you map the current directory to a directory in the container like this, it’s because you’re doing development and you want changes to the host directory to be reflected in the container.

    When you deploy to production, you usually don’t want to do that and you want to use the files in the image. So the solution to your problem is to delete the 2 lines.

    If you do need to map the current directory to the /app directory, then you need to make sure that the node user in the container can access the files. You’re getting the error you see because the node user doesn’t have access to the files in the host directory.

    To give the node user access, you need to give it access to the files on the host.

    You can do that by making sure that a user with UID of 1000 or GID of 1000 can access the files on the host. The most common way of doing it is to create a group on the host with GID 1000 and change group ownership of the host files to 1000.

    The reason you want to use UID 1000 and GID 1000 is that those numbers are set up in the node Dockerfile, which you can see here. The user is created in line 5 and 6.

    But, as I said, the ‘correct’ solution is almost certainly to remove the volume mapping in your docker-compose file.

    Login or Signup to reply.
  2. Your setup has 2 issues:

    • docker-compose.yml will mount local directory in /app, hiding any data from built image as mentioned by @Hans Kilian’s answer
    • You are copying package.json and installing deps with npm ci as root user, only switching to node user at the end of build process. You should use node from the beginning to avoid files owned by root such as:
    # get node distro - should be consistent across environments
    FROM --platform=linux/amd64 node:16.17.0
    
    # make sure not running root
    USER node
    
    # copy package.json etc FIRST. any changes here invalidate cache for rest of file
    # see https://docs.semaphoreci.com/article/81-docker-layer-caching
    COPY package.json package-lock.json app/
    
    # create home dir, where the app will be run
    WORKDIR /app
    
    # install our dependencies, for now we want to install ALL deps, including dev ones
    # put before COPY, any changes in the cwd will invalidate the cache for this layer
    RUN npm ci --platform=linux --progress=false
    
    COPY . .
    
    # expose ports to outside world
    EXPOSE 3002 3003
    
    CMD ["npm", "start"]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search