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
Your main issue are these lines in your docker-compose file:
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 thenode
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.
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 answerpackage.json
and installing deps withnpm ci
asroot
user, only switching tonode
user at the end of build process. You should usenode
from the beginning to avoid files owned byroot
such as: