
我嘗試將目前在我的伺服器上運行的 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
使用者身分運行。
您已將使用者新增root
至www-data
docker-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 exec
,chmod
為了簡潔起見,我們假設也沒有使用者命名空間。
您要求做的事情相當於:
- 使用 Unix 套接字運行
php-fpm
實例system1
/var/run/php-fpm.sock
/var/run
透過 NFS導出system1
.- 安裝
system1:/var/run
在system2
.一個完全獨立的系統。 - 嘗試將
connect()
Unix 套接字套接字開啟system2
並期望system1
以 回應php-fpm
。
你實際上應該這樣做的方式(實際上應該想要做到這一點(這是一個單獨的問題)是使用 IP 監聽實例php-fpm
——因此將其綁定到host_system:12345
例如。然後使用nginx
incontainer
連接到host_system:12345
.
這一切都是錯的。別聽我的。如果您建立一個命名良好的 unix 套接字,在任一命名空間中公開,並且路徑在兩個命名空間之間共享,則連接到該 unix 套接字將連接到另一個命名空間!
https://lore.kernel.org/all/[電子郵件受保護]/T/
這個補丁專門解決了這個問題。顯然,當我測試時,這是很久以前的事了! :)
唯一一次似乎並非如此的情況是在匿名 Unix 套接字創建案例中,但這是一個相當 Linux 特定且不經常使用的 Unix 套接字功能。