作為磁碟區安裝在 docker 容器中的 unix 套接字的權限被拒絕

作為磁碟區安裝在 docker 容器中的 unix 套接字的權限被拒絕

我嘗試將目前在我的伺服器上運行的 nginx 容器化。為此,我建立了以下 docker compose 檔案:

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"

一切正常,但問題是,我的主機系統上仍然有 php-fpm “本機”運行(不是 dockerized),並且我想將它們的套接字用於我的 nginx 容器(因此出現了這一行volumes: - "/run/php:/run/php")。

套接字的權限是srw-rw---- www-data:www-data.因此,我將容器使用者新增至群組 33(這是我的主機系統上的 www-data -> group_add: ["33"])。當我在容器中檢查群組 id 時,該 id33確實已新增至目前登入的使用者:

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

儘管如此,當我呼叫由 PHP 提供支援的網站時,我在 nginx 日誌中收到以下錯誤訊息:

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"

有什麼提示或解決方案可能會缺少使其工作嗎?

答案1

我已經做了一些挖掘:)

如果你進入執行 nginx 映像的容器,你可以看到有幾個 nginx 程序正在運行:

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

有些以 身分運行root,有些以nginx使用者身分運行。

您已將使用者新增rootwww-datadocker-compose 檔案內的群組中,但即使不這樣做,root 使用者也應該擁有存取 php unix 套接字所需的所有權限。

您可以使用test命令測試權限。輸出退出代碼以查看命令是否成功。如您所見,root 使用者可以讀取套接字文件,但不能執行它:

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

所以permission denied錯誤可能來自於nginx worker以使用者身分執行的進程nginx

我們先檢查一下 docker 容器內檔案的權限...

ls -al給出以下輸出:

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

表示套接字檔案歸“xfs”所有。快速查看/etc/group容器內的檔案會發現該xfs群組的 ID33與該群組在主機上的 ID 相同www-data

在容器內,您可以將 nginx 使用者新增至 xfs 群組:

addgroup nginx xfs

現在問題應該要解決。

我不確定如何將其直接添加到您的撰寫文件中(如何指定將哪個用戶添加到群組中?) - 但如果您可以製作新映像,則可以在 Dockerfile 中執行此操作。

不過,重新啟動容器後,權限似乎仍然存在。

答案2

確定 PHP-FPM 在主機上運行的使用者和群組。您通常可以在 PHP-FPM 設定檔中找到此資訊(通常位於 /etc/php/7.x/fpm/pool.d/www.conf)

然後更新你的 docker-compose 並加入這個

user: "your_php_user:your_php_group"

答案3

一切正常,但問題是,我的主機系統上仍然有 php-fpm “本機”運行(不是 dockerized),並且我想將它們的套接字用於我的 nginx 容器(因此行volumes: - "/run/php:/run/php")。

這是不可能的,也是不明智的。

Docker 產生了自己的網路命名空間,因此您可以獲得自己的防火牆堆疊、IP 堆疊和 Unix 網路堆疊。

即使您解決了權限問題,例如您使用套接字檔案 666 手動登入容器docker execchmod為了簡潔起見,我們假設也沒有使用者命名空間。

您要求做的事情相當於:

  1. 使用 Unix 套接字運行php-fpm實例system1/var/run/php-fpm.sock
  2. /var/run透過 NFS導出system1.
  3. 安裝system1:/var/runsystem2.一個完全獨立的系統。
  4. 嘗試將connect()Unix 套接字套接字開啟system2並期望system1以 回應php-fpm

你實際上應該這樣做的方式(實際上應該要做到這一點(這是一個單獨的問題)是使用 IP 監聽實例php-fpm——因此將其綁定到host_system:12345例如。然後使用nginxincontainer連接到host_system:12345.


這一切都是錯的。別聽我的。如果您建立一個命名良好的 unix 套接字,在任一命名空間中公開,並且路徑在兩個命名空間之間共享,則連接到該 unix 套接字將連接到另一個命名空間!

https://lore.kernel.org/all/[電子郵件受保護]/T/

這個補丁專門解決了這個問題。顯然,當我測試時,這是很久以前的事了! :)

唯一一次似乎並非如此的情況是在匿名 Unix 套接字創建案例中,但這是一個相當 Linux 特定且不經常使用的 Unix 套接字功能。

相關內容