Berechtigung für Unix-Socket, der als Volume im Docker-Container montiert ist, verweigert

Berechtigung für Unix-Socket, der als Volume im Docker-Container montiert ist, verweigert

Ich versuche, mein aktuell auf meinem Server laufendes Nginx in einen Container zu packen. Dazu habe ich folgende Docker-Compose-Datei erstellt:

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"

Alles funktioniert einwandfrei, aber das Problem besteht darin, dass auf meinem Hostsystem immer noch php-fpm „nativ“ (nicht dockerisiert) ausgeführt wird und ich deren Sockets für meinen Nginx-Container verwenden möchte (daher die Zeile volumes: - "/run/php:/run/php").

Die Berechtigungen der Sockets sind srw-rw---- www-data:www-data. Daher habe ich den Container-Benutzer zur Gruppe 33 hinzugefügt (das sind www-data auf meinem Host-System -> group_add: ["33"]). Wenn ich im Container die Gruppen-IDs überprüfe, 33wird die ID tatsächlich dem aktuell angemeldeten Benutzer hinzugefügt:

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

Wenn ich jedoch eine Website aufrufe, die mit PHP betrieben wird, erhalte ich in den Nginx-Protokollen folgende Fehlermeldung:

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"

Irgendwelche Hinweise oder Lösungen, was fehlen könnte, damit es funktioniert?

Antwort1

Ich habe ein bisschen gegraben :)

Wenn Sie den Container aufrufen, in dem das Nginx-Image ausgeführt wird, können Sie sehen, dass einige Nginx-Prozesse ausgeführt werden:

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

Einige werden als ausgeführt root, andere als nginxBenutzer.

rootSie haben den Benutzer der Gruppe in Ihrer Docker-Compose-Datei hinzugefügt www-data, aber auch ohne das sollte der Root-Benutzer über alle erforderlichen Berechtigungen für den Zugriff auf den PHP-UNIX-Socket verfügen.

Sie können die Berechtigungen mit dem Befehl testen test. Geben Sie den Exit-Code aus, um zu sehen, ob der Befehl erfolgreich war oder nicht. Wie Sie sehen, kann der Root-Benutzer die Socket-Datei lesen, aber nicht ausführen:

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

Der permission deniedFehler wird also wahrscheinlich von dem nginx workerProzess verursacht, der als nginxBenutzer ausgeführt wird.

Lassen Sie uns zuerst die Berechtigungen für die Dateien im Docker-Container überprüfen ...

ls -algibt folgende Ausgabe aus:

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

besagt, dass die Socket-Datei dem „xfs“ gehört. Ein kurzer Blick auf die /etc/groupDatei im Container zeigt, dass die ID der xfsGruppe 33mit der ID auf dem Hostcomputer für die Gruppe identisch ist www-data.

Innerhalb des Containers können Sie den Nginx-Benutzer zur XFS-Gruppe hinzufügen:

addgroup nginx xfs

Das Problem sollte jetzt behoben sein.

Ich bin nicht sicher, wie Sie dies direkt in Ihre Erstellungsdatei einfügen (wie geben Sie an, welcher Benutzer zur Gruppe hinzugefügt werden soll?) – aber Sie könnten es in Ihrer Docker-Datei tun, wenn Sie ein neues Image erstellen können.

Nach dem Neustart des Containers scheinen die Berechtigungen jedoch bestehen zu bleiben.

Antwort2

Bestimmen Sie den Benutzer und die Gruppe, als die PHP-FPM auf dem Host ausgeführt wird. Normalerweise finden Sie diese Informationen in Ihrer PHP-FPM-Konfigurationsdatei (normalerweise unter /etc/php/7.x/fpm/pool.d/www.conf).

Aktualisieren Sie dann Ihr Docker-Compose und fügen Sie Folgendes hinzu

user: "your_php_user:your_php_group"

Antwort3

Alles funktioniert einwandfrei, aber das Problem besteht darin, dass auf meinem Hostsystem immer noch php-fpm „nativ“ (nicht dockerisiert) läuft und ich deren Sockets für meinen Nginx-Container verwenden möchte (daher die Zeilenvolumes: - "/run/php:/run/php").

Dies ist weder möglich noch sinnvoll.

Docker erzeugt seinen eigenen Netzwerk-Namespace, sodass Sie Ihren eigenen Firewall-Stack, IP-Stack und Unix-Netzwerk-Stack erhalten.

Auch wenn Sie das Berechtigungsproblem beheben, nehmen wir beispielsweise an, dass Sie sich manuell mit der Socket-Datei 666 beim Container anmelden docker execund chmodder Kürze halber davon ausgehen, dass auch keine Benutzernamensräume im Weg sind.

Was Sie verlangen, ist das Äquivalent von:

  1. Ausführen einer php-fpmInstanz system1mit einem Unix-Socket/var/run/php-fpm.sock
  2. Exportieren des /var/runPfads über NFS auf system1.
  3. Montage system1:/var/runauf system2. Ein völlig separates System.
  4. Ich versuche, connect()den besagten Unix-Socket Socket einzuschalten system2und erwarte system1eine Antwort mit php-fpm.

So wie Sie das eigentlich machen sollten (sollten Sie eigentlichwollenum dies zu tun, was eine separate Angelegenheit ist) besteht darin, die Instanz über IP abzuhören php-fpm– sie also host_system:12345beispielsweise an zu binden. Verwenden Sie dann nginxin, containerum eine Verbindung herzustellen mit host_system:12345.


Das ist alles einfach falsch. Hören Sie nicht auf mich. Wenn Sie einen gut benannten Unix-Socket erstellen, der in einem der beiden Namespaces verfügbar ist und dessen Pfad von beiden Namespaces gemeinsam genutzt wird, wird bei einer Verbindung zu diesem Unix-Socket eine Verbindung zum anderen Namespace hergestellt!

https://lore.kernel.org/all/[email geschützt]/T/

Dieser Patch behebt dieses Problem speziell. Als ich das getestet habe, ist es offensichtlich schon sehr lange her! :)

Der einzige Fall, in dem dies nicht der Fall zu sein scheint, ist die anonyme Erstellung von Unix-Sockets. Dies ist jedoch eine ziemlich Linux-spezifische und nicht oft verwendete Funktion von Unix-Sockets.

verwandte Informationen