1

I try to containerize my nginx running currently on my server. For this I created the following docker compose file:

version: "3.8"
services:
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    restart: unless-stopped
    group_add: ["33"]
    volumes:
      - "/etc/nginx-docker:/etc/nginx/conf.d:ro"
      - "/run/php:/run/php"
      - "/var/www:/var/www:ro"
    ports:
      - "8111:80"
      - "8443:443"

Everything works fine but the problem is, that I still have php-fpm's running "natively" (not dockerized) on my host system and I want to use their sockets for my nginx container (hence the line volumes: - "/run/php:/run/php").

The sockets' permissions are srw-rw---- www-data:www-data. Therefore I added the container user to the group 33 (which is www-data on my host system -> group_add: ["33"]). When I check in the container the group ids, the id 33 is indeed added to the currently logged in user:

/ # id -G
0 1 2 3 4 6 10 11 20 26 27 33
/ # id -u
0
/ # whoami
root

Nonetheless when I call a website powered by PHP I get in the nginx logs following error message:

2024/01/21 08:58:53 [crit] 21#21: *1 connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.192.68, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "op---s:8111"

Any hints or solutions what could be missing to make it work?

2
  • On what distribution are you running (Fedora/Ubuntu/...)? If you're on a RHEL-derivative, is SELinux enabled (what is the output of getenforce)?
    – larsks
    Commented Jan 22 at 0:56
  • @larsks I‘m on Debian. Commented Jan 22 at 12:02

3 Answers 3

3
+100

I've done some digging :)

If you enter the container running the nginx image, you can see that there's a couple of nginx processes running:

docker exec -it 43b5b971c433 /bin/sh

/ # ps -ef |grep nginx
    1 root      0:00 nginx: master process nginx -g daemon off;
   21 nginx     0:00 nginx: worker process
   22 nginx     0:00 nginx: worker process
   23 nginx     0:00 nginx: worker process
   24 nginx     0:00 nginx: worker process
   42 root      0:00 grep nginx

Some are run as root, and some as nginx user.

You have added the user root into the www-data group inside your docker-compose file, but even without doing that, root user should have all the permissions necessary to access the php unix socket.

You can test permissions with the test command. Output the exit code to see if the command has succeeded or not. As you can see, root user can read the socket file, but not execute it:

/run/php # whoami
root
/run/php # test -r  php8.1-fpm.sock; echo $?
0
/run/php # test -x  php8.1-fpm.sock; echo $?
1

So the permission denied error probably comes from the nginx worker process, run as nginx user.

Let's check the permissions for the files inside docker container first ...

ls -al gives the following output:

srw-rw----    1 xfs      xfs              0 Jan 25 08:58 php8.1-fpm.sock

saying that the socket file is owned by the "xfs". A quick look at the /etc/group file inside the container shows the ID of the xfs group being 33 - same as the ID on the host machine for the group www-data.

Inside the container, you can add the nginx user to the xfs group:

addgroup nginx xfs

The problem should be fixed now.

I'm not sure how to add this directly into your compose file (how do you specify which user to add to the group?) - but you could do it in your Dockerfile if you can make a new image.

After restarting the container, the permissions seem to persist, though.

3
  • 1
    If I add the xfs group to the root user and the nginx user and restart the container it indeed works. But I would prefer to not write my own Dockerfile for this. Commented Jan 26 at 20:26
  • 1
    I mounted a bash script into /entrypoint.d/ of the nginx container where I run the two addgroup commands and it seems to work. Commented Jan 26 at 21:09
  • I see - that's a good idea. Unless there's a command that works in docker compose for modifying (specified) users and their groups, I think you're stuck with bash scripts or Dockerfiles. Also, does it work with adding the xfs group to nginx user only?
    – GChuf
    Commented Jan 26 at 21:45
1

Determine the user and group that PHP-FPM is running as on the host. You can usually find this information in your PHP-FPM configuration file (commonly located at /etc/php/7.x/fpm/pool.d/www.conf)

Then update your docker-compose and add this

user: "your_php_user:your_php_group"
0

Everything works fine but the problem is, that I still have php-fpm's running "natively" (not dockerized) on my host system and I want to use their sockets for my nginx container (hence the line volumes: - "/run/php:/run/php").

This isn't possible or sensible.

Docker spawns its own network namespace, so you get your own firewall stack, IP stack and Unix network stack.

Even if you fix the permissions issue, lets say for example you login to the container manually with docker exec and chmod the socket file 666 and for the sake of brevity lets assume there are no user namespaces in the way too..

What you're asking to do is the equivalent of:

  1. Running a php-fpm instance on system1 with a Unix socket on /var/run/php-fpm.sock
  2. Exporting the /var/run path over NFS on system1.
  3. Mounting system1:/var/run on system2. A completely separate system.
  4. Trying to connect() to said Unix socket socket on system2 and expecting system1 to respond with php-fpm.

The way you should actually do this (should actually want to do this, which is a separate matter) is to listen on the php-fpm instance using IP -- so binding it to host_system:12345 for example. Then using nginx in container to connect to host_system:12345.


This is all just wrong. Dont listen to me. If you create a well-named unix socket, exposed in either namespace and the path is shared between both namespaces, connecting to that unix socket connect to the other namespace!

https://lore.kernel.org/all/[email protected]/T/

This patch specifically addresses it. Clearly when I tested this was a long long time ago! :)

The only time this doesn't appear to be the case is in the anonymous Unix socket creation case however that one is a pretty linux specific and not often used feature of unix sockets.

11
  • I would prefer sockets for performance reason. I've seen tutorials on the internet where they actually use sockets. But maybe they all were between a php-fpm docker container and a nginx container and not between a host php-fpm and a nginx docker container. Is it possible to do what I want by using a php-fpm docker container instead of running php-fpm natively on the host? Commented Jan 26 at 7:05
  • Personally I'd run the php-fpm instance in a pod associated with the nginx container. They will live in the same network namespace. Pods are a kubernetes/podman thing though. Commented Jan 26 at 8:07
  • 1
  • 1
    There are plenty of documented cases of people running docker commands on the host by bind-mounting the socket to a container and running docker buildx from a container, for CI/CD processes, for instance: kenmuse.com/blog/docker-from-docker-in-alpine-dev-containers
    – Marcel
    Commented Feb 1 at 15:41
  • 1
    @marcel I tried and tested, you're totally right! Providing the sockets path is not in the anonymous space, this really is valid. The more you know! Commented Feb 3 at 21:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .