Error EACCES permission denied, using Docker Compose plugin on Ubuntu

Hi there,

I am not quite sure I post this issue in the correct Category. Whoever has the rights to, feel free to change it if it’s not.

I have an issue regarding permissions with pretty much all the projects I work on, in my team. Here are a few information about it :

  • we all work on the same repositories, with the exact same files and I am the only one having this issue.
  • we all use an updated version of Docker with Docker Compose plugin.
  • we all use 1001:1001 user and group because we’re given computers that already have a preconfig 1000:1000 user that we can’t use. This has been well established in the company and we are not to change it.
  • we work on different applications / repositories that are programmed in different languages. The issue happens with every one of them.
  • I work on Ubuntu 22.04.2 LTS 64 bits. I tried to uninstall and install Docker again as cleanly as I could yesterday, but still have the same issue.
  • my user has been added to the docker group.
  • in the given example as pretty much every other project, we mount a volume on the project sources so that we can change and not have to restart the container every time we do.

That being said, here is an example of a Makefile used in these repositories

APP_NAME = app
export DEV_UID = $(shell id -u)
export DEV_GID = $(shell id -g)
DOCKER_COMPOSE = docker compose
DOCKER_BUILD = BUILDKIT=1 $(DOCKER_COMPOSE) build
DOCKER_UP = $(DOCKER_COMPOSE) up -d
DOCKER_DOWN = $(DOCKER_COMPOSE) down
DOCKER_EXEC = $(DOCKER_COMPOSE) run
LOG_FILE = ./var/error.log
APP_ADDRESS = http://localhost:8081/

install: ## Install NodeJS sample App
	@$(MAKE) requirements

requirements: build
	@$(MAKE) start
	@echo "Installing dependencies"
	@$(DOCKER_EXEC) $(APP_NAME) npm install
	@echo "Installing SQLite migrations"
	@$(DOCKER_EXEC) $(APP_NAME) npx prisma migrate dev

build: ## build docker image
	$(DOCKER_BUILD)

start: ## start docker image
	$(DOCKER_UP)

Here is an example of Dockerfile

FROM node:18 AS core

RUN apt-get update \
    && apt-get install -y \
            git \
            unzip \
            curl \
            sqlite3 \
    && apt-get clean

###############################################################################

FROM core AS dev-tools

##Update npm
RUN npm install -g npm
##Install nodemon
RUN npm install -g nodemon

###############################################################################

FROM dev-tools as development

ARG USER=www-data
WORKDIR /srv/app
USER $USER

CMD nodemon

And here is the docker-compose.yml :

version: "3.9"

services:
  app:
    build:
      context: .
      target: development
      args:
        NODE_ENV: local
    environment:
      - HOME=/tmp
      - APP_ENV=${APP_ENV:-dev}
      - NODE_ENV=local
    volumes:
      - "./:/srv/app:rw"
    user: "${DEV_UID:-1000}:${DEV_GID:-1000}"
    restart: unless-stopped
    ports:
      - "8081:80"
    networks:
      - default

networks:
  default: ~

Here are my subuid and subgid files :

my-user:0:1000
my-user:1001:65536
company:100000:65536

my-user:0:1000
my-user:1001:65536
company:100000:65536

Still, when executing the make install command, every thing works fine until the requirements need to be installed. When trying to execute composer for php, npm for node or any other dependency manager, or any other command that needs to write files (happens also with sqlite db file creation), I have the following error :

Installing dependencies
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /srv/app/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/srv/app/node_modules'
npm ERR!  [Error: EACCES: permission denied, mkdir '/srv/app/node_modules'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/srv/app/node_modules'
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.

npm ERR! A complete log of this run can be found in: /tmp/.npm/_logs/2023-04-18T07_59_25_826Z-debug-0.log

Also happens when the node_modules / vendor / any other dependency folder is already created.
The only way I can make this work is by deleting the definition of DEV_UID and DEV_GID shell variables in my Makefile. This workaround has worked for a few month but is a bit dangerous as I can’t push it on our repositories with this change and it already incidentally happened a few times because of other changes I had to make for a feature.

Again, this is just an example. The issue is triggered on whatever project I work on that have a similar functioning.

Hopefully someone will be able to help me.

Do you think it is relevant? Are you using rootless Docker or user namespaces?

If you all use UID 1001 and GID 1001 then the files you mount from the host must be owned by UID 1001 or at least by the GID 1001 depending on who have permission to those files.

The files you want to mount was probably created by a user with UID 1000 you you have to fix it.

PS:: I am wondering what you think how easily your post was readable before I edited it to add code blocks :slight_smile: Please, always use code blocks for code and alway check the post after sending it to make sure it appears as you expected it. Tips: How to format your forum posts

Hey rimelek,

First of all thank you for replying. And thank you for editing the post as I did not check the “How to format your forum posts” before posting. It is in fact way more readable.

I am using userns-remap.

Yes, that was also my first guess. But the permissions on files are all good and set to myself and my user’s group.

main > ls -al
total 320
drwxrwxr-x 15 my-user my-user   4096 avril 20 10:10 .
drwxrwxr-x  5 my-user my-user   4096 mars  20 12:10 ..
-rw-rw-r--  1 my-user my-user   1151 avril 17 16:47 app.js
drwxrwxr-x  2 my-user my-user   4096 mars   1 10:57 bin
drwxrwxr-x  2 my-user my-user   4096 avril 17 16:47 client
drwxrwxr-x  3 my-user my-user   4096 avril 17 16:47 controllers
drwxrwxr-x  2 my-user my-user   4096 avril 17 16:47 data-access
-rw-rw-r--  1 my-user my-user    408 mars  28 10:41 docker-compose.yml
-rw-rw-r--  1 my-user my-user    530 avril 17 16:47 Dockerfile
-rw-rw-r--  1 my-user my-user     76 mars  15 17:15 .dockerignore
-rw-rw-r--  1 my-user my-user    613 avril 17 16:47 .env
-rw-rw-r--  1 my-user my-user   1295 avril  7 11:37 .env.local
-rw-rw-r--  1 my-user my-user   1192 avril  5 15:44 .env.test
drwxrwxr-x  2 my-user my-user   4096 mars  28 10:41 exceptions
-rw-rw-r--  1 my-user my-user    314 mars  15 17:15 .gitignore
-rw-rw-r--  1 my-user my-user   6442 mars  28 10:41 jest.config.js
-rw-rw-r--  1 my-user my-user   1486 avril 20 10:10 Makefile
-rw-rw-r--  1 my-user my-user    718 avril 17 16:47 package.json
-rw-rw-r--  1 my-user my-user 206683 avril 17 16:54 package-lock.json
drwxrwxr-x  3 my-user my-user   4096 avril 17 16:47 prisma
drwxr-xr-x  5 my-user my-user   4096 févr.  6 10:34 public
-rw-rw-r--  1 my-user my-user   4282 avril 17 16:52 README.md
drwxrwxr-x  2 my-user my-user   4096 avril 17 16:52 routes
drwxrwxr-x  5 my-user my-user   4096 avril 17 16:47 tests
drwxrwxr-x  5 my-user my-user   4096 avril 17 16:47 use-cases
drwxrwxr-x  2 my-user my-user   4096 avril 17 16:47 utils
drwxr-xr-x  2 my-user my-user   4096 avril  7 11:38 var
drwxrwxr-x  2 my-user my-user   4096 avril 17 16:47 views
> id my-user
uid=1001(my-user) gid=1001(my-user) groupes=1001(my-user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),135(sambashare),998(docker)

Nevertheless, when I start my container and go in it to check the permissions, here is the result :

/srv/app$ ls -al
total 320
drwxrwxr-x 15 node node   4096 Apr 20 08:29 .
drwxr-xr-x  1 root root   4096 Apr 20 08:40 ..
-rw-rw-r--  1 node node     76 Mar 15 16:15 .dockerignore
-rw-rw-r--  1 node node    613 Apr 17 14:47 .env
-rw-rw-r--  1 node node   1295 Apr  7 09:37 .env.local
-rw-rw-r--  1 node node   1192 Apr  5 13:44 .env.test
-rw-rw-r--  1 node node    314 Mar 15 16:15 .gitignore
-rw-rw-r--  1 node node    530 Apr 17 14:47 Dockerfile
-rw-rw-r--  1 node node   1488 Apr 20 08:29 Makefile
-rw-rw-r--  1 node node   4282 Apr 17 14:52 README.md
-rw-rw-r--  1 node node   1151 Apr 17 14:47 app.js
drwxrwxr-x  2 node node   4096 Mar  1 09:57 bin
drwxrwxr-x  2 node node   4096 Apr 17 14:47 client
drwxrwxr-x  3 node node   4096 Apr 17 14:47 controllers
drwxrwxr-x  2 node node   4096 Apr 17 14:47 data-access
-rw-rw-r--  1 node node    408 Mar 28 08:41 docker-compose.yml
drwxrwxr-x  2 node node   4096 Mar 28 08:41 exceptions
-rw-rw-r--  1 node node   6442 Mar 28 08:41 jest.config.js
-rw-rw-r--  1 node node 206683 Apr 17 14:54 package-lock.json
-rw-rw-r--  1 node node    718 Apr 17 14:47 package.json
drwxrwxr-x  3 node node   4096 Apr 17 14:47 prisma
drwxr-xr-x  5 node node   4096 Feb  6 09:34 public
drwxrwxr-x  2 node node   4096 Apr 17 14:52 routes
drwxrwxr-x  5 node node   4096 Apr 17 14:47 tests
drwxrwxr-x  5 node node   4096 Apr 17 14:47 use-cases
drwxrwxr-x  2 node node   4096 Apr 17 14:47 utils
drwxr-xr-x  2 node node   4096 Apr  7 09:38 var
drwxrwxr-x  2 node node   4096 Apr 17 14:47 views
node@f6134b959524:/srv/app$ id -u 
1000

It looks like Docker Compose couldn’t link my user to the one in the container, even when it’s clearly stated that I want it to do it in my docker-compose.yml file.

That’s the point of userns-remap. If you set the user id to 1001, it will be 1001 inside but not outside.

It doesn’t make sense to me. First I don’t think you could have two lines for the same user, but if you set the ID between 0 and 1000 that is basically just limiting the number of UID-s inside the container but it would practically disable the uer namespace. You can find out the required UID/GID (that you need to set on the mounted files) by using the following vommand:

docker run --rm -it -v $PWD:/app bash -c 'touch /app/test.txt`
ls -ln $PWD/test.txt
1 Like

This part caught my attention. You are right, it does not make sense. This is actually a fix given by my company to make one of our main project work. And it does its job.

But I tried to take it off and make my current project work. And it does. So the solution is to not limit the number of UID-s inside container and work on a better fix for the main project :sweat_smile:

Thanks a lot for your help.