Permiso denegado para un socket Unix montado en un contenedor acoplable como volumen

Permiso denegado para un socket Unix montado en un contenedor acoplable como volumen

Intento contener mi nginx que se ejecuta actualmente en mi servidor. Para esto creé el siguiente archivo de composición acoplable:

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"

Todo funciona bien, pero el problema es que todavía tengo php-fpm ejecutándose "de forma nativa" (no acoplado) en mi sistema host y quiero usar sus sockets para mi contenedor nginx (de ahí la línea volumes: - "/run/php:/run/php").

Los permisos de los sockets son srw-rw---- www-data:www-data. Por lo tanto, agregué el usuario del contenedor al grupo 33 (que es www-data en mi sistema host -> group_add: ["33"]). Cuando reviso en el contenedor los ID de grupo, el ID 33se agrega al usuario actualmente conectado:

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

Sin embargo, cuando llamo a un sitio web impulsado por PHP, aparece en los registros de nginx el siguiente mensaje de error:

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"

¿Alguna sugerencia o solución que podría faltar para que funcione?

Respuesta1

He investigado un poco :)

Si ingresa al contenedor que ejecuta la imagen nginx, puede ver que hay un par de procesos nginx ejecutándose:

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

Algunos se ejecutan como rooty otros como nginxusuario.

Ha agregado al usuario rootal www-datagrupo dentro de su archivo docker-compose, pero incluso sin hacerlo, el usuario root debe tener todos los permisos necesarios para acceder al socket php Unix.

Puede probar los permisos con el testcomando. Genere el código de salida para ver si el comando se realizó correctamente o no. Como puede ver, el usuario root puede leer el archivo socket, pero no ejecutarlo:

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

Entonces, el permission deniederror probablemente proviene del nginx workerproceso, ejecutar como nginxusuario.

Primero verifiquemos los permisos para los archivos dentro del contenedor Docker...

ls -alda el siguiente resultado:

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

diciendo que el archivo socket es propiedad de "xfs". Un vistazo rápido al /etc/grouparchivo dentro del contenedor muestra que el ID del xfsgrupo es 33el mismo que el ID en la máquina host del grupo www-data.

Dentro del contenedor, puedes agregar el usuario nginx al grupo xfs:

addgroup nginx xfs

El problema debería solucionarse ahora.

No estoy seguro de cómo agregar esto directamente a su archivo de redacción (¿cómo se especifica qué usuario agregar al grupo?), pero podría hacerlo en su Dockerfile si puede crear una nueva imagen.

Sin embargo, después de reiniciar el contenedor, los permisos parecen persistir.

Respuesta2

Determine el usuario y el grupo que ejecuta PHP-FPM en el host. Generalmente puede encontrar esta información en su archivo de configuración PHP-FPM (comúnmente ubicado en /etc/php/7.x/fpm/pool.d/www.conf)

Luego actualice su docker-compose y agregue esto

user: "your_php_user:your_php_group"

Respuesta3

Todo funciona bien, pero el problema es que todavía tengo php-fpm ejecutándose "de forma nativa" (no dockerizado) en mi sistema host y quiero usar sus sockets para mi contenedor nginx (de ahí la línea volúmenes: - "/run/php:/run/php").

Esto no es posible ni sensato.

Docker genera su propio espacio de nombres de red, por lo que usted obtiene su propia pila de firewall, pila de IP y pila de red Unix.

Incluso si soluciona el problema de permisos, digamos, por ejemplo, que inicia sesión en el contenedor manualmente con docker execel chmodarchivo de socket 666 y, en aras de la brevedad, supongamos que tampoco hay espacios de nombres de usuario en el camino.

Lo que estás pidiendo hacer es el equivalente a:

  1. Ejecutar una php-fpminstancia system1con un socket Unix encendido/var/run/php-fpm.sock
  2. Exportando la /var/runruta a través de NFS en system1.
  3. Montaje system1:/var/runen system2. Un sistema completamente separado.
  4. Intentando connect()encender dicho socket Unix system2y esperando system1responder con php-fpm.

La forma en que realmente deberías hacer esto (en realidad deberíasdesearhacer esto, que es un asunto aparte) es escuchar en la php-fpminstancia usando IP, vinculándola, host_system:12345por ejemplo. Luego use nginxin containerpara conectarse a host_system:12345.


Todo esto está simplemente mal. No me escuches. Si crea un socket Unix con un buen nombre, expuesto en cualquiera de los espacios de nombres y la ruta se comparte entre ambos espacios de nombres, al conectarse a ese socket Unix, conéctese al otro espacio de nombres.

https://lore.kernel.org/all/[correo electrónico protegido]/T/

Este parche lo aborda específicamente. ¡Claramente, cuando probé esto fue hace mucho, mucho tiempo! :)

La única vez que este no parece ser el caso es en el caso de la creación anónima de sockets Unix; sin embargo, esa es una característica bastante específica de Linux y no se usa con frecuencia en los sockets Unix.

información relacionada