Contents

Docker權限問題

在使用 Docker 掛載目錄(bind mount)時,常常會遇到容器內部無法讀寫宿主機目錄的權限問題。這是因為容器內的使用者 UID/GID 與宿主機上的使用者 UID/GID 不同所導致的。

問題原因

Docker 容器中的程序預設以某個使用者身份執行(例如 www-data,UID=33),而宿主機上掛載的目錄擁有者可能是另一個使用者(例如 UID=1000)。當 UID 不符合時,容器內程序便無法寫入該目錄,產生 Permission denied 錯誤。

1
2
$ docker run -v /host/data:/container/data myimage
touch: /container/data/test.txt: Permission denied

解決方式

方法一:在 Dockerfile 中建立對應 UID 的使用者

1
2
3
4
5
6
7
FROM ubuntu:22.04

# 建立與宿主機相同 UID 的使用者
RUN groupadd -g 1000 appuser && \
    useradd -u 1000 -g appuser appuser

USER appuser

方法二:使用 --user 參數

執行容器時直接指定以宿主機使用者身份執行:

1
docker run --user $(id -u):$(id -g) -v /host/data:/container/data myimage

方法三:調整宿主機目錄的權限

1
2
3
4
5
# 設定目錄可被所有人讀寫(較不安全,僅用於開發環境)
chmod -R 777 /host/data

# 或設定特定群組可寫入
chown -R 1000:1000 /host/data

方法四:在容器啟動腳本中修正權限

entrypoint.sh 中動態修正權限:

1
2
3
#!/bin/bash
chown -R appuser:appuser /container/data
exec "$@"

Volume 與 Bind Mount 的差異

特性 Volume Bind Mount
管理方式 Docker 管理(docker volume 直接指定宿主機路徑
路徑 /var/lib/docker/volumes/... 任意宿主機路徑
權限問題 較少遇到 常見 UID/GID 不符
跨平台 較一致 Windows/Mac 行為不同
適用場景 生產環境資料持久化 開發時程式碼掛載

Volume 由 Docker 自動建立和管理,容器對 volume 擁有完整控制權,較不容易遇到權限問題。

Bind Mount 直接將宿主機路徑掛載進容器,因此宿主機的檔案權限設定直接影響容器內的存取。

最佳實踐

  1. 開發環境可使用 --user 搭配 bind mount,方便直接編輯程式碼
  2. 生產環境建議使用 Docker volume,並在 Dockerfile 明確設定執行使用者
  3. 避免在 Dockerfile 中使用 root 使用者執行應用程式,降低安全風險

參考資料