示意圖:Docker UID/GID 權限關係
這次整理 Docker 多網站環境時,遇到一個很常見的問題:不同 container 裡的使用者 UID/GID 不一樣,結果 bind mount 到 host 的檔案權限就容易亂掉。
問題:
目前有這些服務:
- nginx
- php-fpm
- php82-fpm
- php83-fpm
- mysql
PHP-FPM 大多已經是:
uid=1000(www) gid=1000(www)
但是 Nginx worker 可能是:
uid=101(nginx) gid=101(nginx)
MySQL 則是自己的:
uid=27(mysql) gid=27(mysql)
這時候如果 PHP 建立檔案、Nginx 要讀檔,或者 host 要直接修改檔案,就可能遇到權限問題。
原則:
不要把所有 container 都硬改成同一個 UID。
應該分成兩類:
網站檔案:
nginx、php-fpm、php82-fpm、php83-fpm
資料庫資料:
mysql
也就是網站相關服務統一,MySQL 保持自己的使用者。
建議目標:
nginx worker -> 1000:1000
php-fpm -> 1000:1000
php82-fpm -> 1000:1000
php83-fpm -> 1000:1000
mysql -> 保持 mysql 預設 UID/GID
網站目錄可以整理成:
sudo chown -R 1000:1000 ./wwwroot
sudo chown -R 1000:1000 ./session
sudo chown -R 1000:1000 ./log/nginx
MySQL 資料目錄不要一起改。
如果 MySQL container 裡查到是 27:27:
sudo chown -R 27:27 ./data/mysql/data
Nginx 注意事項:
原本以為可以直接在 nginx.conf 寫:
user 1000 1000;
結果啟動時出現:
getpwnam("1000") failed
原因是 Nginx 的 user 指令會去找使用者名稱,不是單純用數字 UID。
比較好的方式是自建 Nginx image,在 image 裡建立一個 www 使用者,UID/GID 是 1000:1000,然後 nginx.conf 寫:
user www www;
驗證:
先讓 PHP 建立測試檔:
docker compose exec php-fpm sh -c 'echo ok > /var/www/permission-test.txt'
再讓 Nginx 讀取:
docker compose exec nginx sh -c 'cat /var/www/permission-test.txt'
回 host 看 owner:
ls -lan ./wwwroot/permission-test.txt
如果看到:
1000 1000
而且 Nginx 也能讀到 ok,表示權限大致整理好了。
結論:
遇到 Docker 權限問題,不要先用:
chmod -R 777
這只是把問題蓋掉。
比較好的做法是先弄清楚誰要讀、誰要寫,再把共同使用同一批檔案的 container 對齊 UID/GID。

0 意見:
張貼留言