2

Welp, I invested three days into this, I figured I'll ask.

I boiled my problem down to this:

The app I'm dockerizing is nothing special:

# docker-compose.yml

services:
  php:
    image: php:8.1.5-fpm-bullseye
    volumes:
      - ./:/var/www

# this is the end goal: files writable by this image:
  nginx:
    image: "nginx:1.23-alpine"
    ports:
      - "8090:80"
    volumes:
      - .:/var/www

On my host machine the current user has: uid=1000(raveren) gid=1000(raveren)

But the files that end up in the mounted volume belong to root (id=0):

> docker compose exec php ls -l /var/www
total 3900
-rwxrwxr-x  1 root root   21848 Jul 19 11:52 Makefile
-rwxrwxr-x  1 root root    1153 Jul 18 07:03 README.md
# etc etc

How am I supposed to make some of the directories (i.e. cache, log, and potentially much more) writable for the www-data user that nginx is running on?

If the files belonged to a non-root user I could do that by either changing the www-data id to match the owner - or do something along the lines of this nice guide.

However, the problem I can't get past is: the containerized files don't "admit" that their owner is actually id=1000 and not root id=0.


I tried:

  • All variations of user directive - in yaml and Dockerfile
  • userns_mode: "host" in the yaml.
  • When I do docker compose exec chown 1000 testfile the owner on the host machine gets reflected as 100999. That's why I suspected userns because cat /etc/subuid gives raveren:100000:65536

Please advise!

raveren
  • 17,799
  • 12
  • 70
  • 83
  • can you `chown` it during the docker build? – Michael Delgado Jul 19 '22 at 22:04
  • Does this answer your question? [why doesn't chown work in Dockerfile?](https://stackoverflow.com/questions/26145351/why-doesnt-chown-work-in-dockerfile) – Michael Delgado Jul 19 '22 at 22:05
  • If you're just trying to run a PHP interpreter against local code, the Ubuntu repositories include a [php8.1 package](https://packages.ubuntu.com/jammy/php8.1) already; can you `sudo apt-get install php8.1` so you don't need to work around Docker's isolation features? – David Maze Jul 19 '22 at 23:21
  • Docker does not fake or translate UIDs or GIDs, nor does your container have any idea about the users on the system it may be running on. You're likely going to want to wrap both those containers in a Dockerfile that creates a user with UID 1000, and then configure nginx/fpm to run as that user. – Sammitch Jul 19 '22 at 23:26
  • @MichaelDelgado thanks for some hints! Unfortunately I can't chown the volume during build, but when I do it via `docker compose exec chown 1000 a` the owner on the host machine gets reflected as 100999. That's why I suspected [userns](https://docs.docker.com/engine/security/userns-remap/) because `cat /etc/subuid` gives `raveren:100000:65536`. So thanks, but no nudge yet :( – raveren Jul 20 '22 at 07:59
  • @DavidMaze: I need to dockerize the application, not make it run on my machine. – raveren Jul 20 '22 at 08:09
  • @Sammitch: yes it does, on Linux. From what I gather the owner SHOULD HAVE [STAYED at 1000](https://www.baeldung.com/linux/file-ownership-docker-container) - my problem is that it actually becomes 0! – raveren Jul 20 '22 at 08:09
  • If you're trying to Dockerize the application, so that you can run it on other systems without PHP or a local copy of the source code, then the `volumes:` blocks shouldn't be part of your setup. Instead `COPY` the source code into an image in a Dockerfile. That approach is unlikely to have the ownership issues you describe. – David Maze Jul 20 '22 at 09:54
  • thanks for your advise, @DavidMaze, however I am dockerizing the application for our developers to ease and unify their setup. `COPY` doesn't work for that scenario. – raveren Jul 20 '22 at 11:11
  • Oh chown will absolutely set file ownership to non-existant UIDs, but the fact remains that your containers are running as root, and writing files as root. Again, there is _no crossover_ in user existence between a container and the host OS, and you _must_ reconfigure the applications running inside the containers to run as the correct user/UID if you want files in mounted volumes to be written with the correct ownership from the perspective of the host machine. – Sammitch Jul 20 '22 at 21:33
  • @raveren on MacOS Docker does mask the user and group ID from the container to match the host one, it behaves differently from Linux https://stackoverflow.com/a/43213455/6182194 – javierlga Jul 21 '22 at 16:54
  • 1
    @Sammitch Docker on macOS does mask the UID/GID to match the one from the host, on Linux it doesn't. – javierlga Jul 22 '22 at 19:50

1 Answers1

0

I will answer my own question here, it turns out this was a bug of some software on my freshly installed test machine - most probably Docker. I spent too much time to care, it works everywhere but on this specific rig. <rant> so screw it and actually screw docker. After two years with it - just using for developer setups - I'm under the impression that each machine a dockerized app runs on - needs some special tweaking. </rant>

In several other machines everything works as expected: the user: directive in the yaml correctly assigns the user that the container runs as. The guide linked inside the question can help, or I did a slightly different approach which works as well:

# docker-compose.yml

services:
  php:
    build:
      context: ./docker/php
      args:
        DOCKER_UID: ${DOCKER_UID:-1000} # these values must be in ENV, eg .env file
    user:
      "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"
# Dockerfile
FROM php:8.1.5-fpm-bullseye

ARG DOCKER_UID

# lots of stuff here

# Create a user for provided UID from the host machine
RUN useradd -u ${DOCKER_UID} -m the-whale
RUN usermod -G www-data,the-whale,root,adm the-whale
raveren
  • 17,799
  • 12
  • 70
  • 83