前言

在日常的 Docker 使用中,我們經常需要在容器和宿主機之間傳輸文件。無論是日誌、配置文件,還是應用數據,學會如何高效地在兩者之間複製文件是每個開發者和運維工程師都必須掌握的技能。

方法一:docker cp 命令

docker cp 是最直接的方式,用於在容器和宿主機之間複製文件或目錄。

從宿主機複製文件到容器

docker cp /path/on/host <container_id>:/path/in/container

示例:

# 複製單個文件
docker cp config.txt my-container:/etc/config.txt

# 複製整個目錄
docker cp ./data my-container:/app/data

從容器複製文件到宿主機

docker cp <container_id>:/path/in/container /path/on/host

示例:

# 複製日誌文件
docker cp my-container:/var/log/app.log ./logs/

# 複製整個目錄
docker cp my-container:/app/output ./output

方法二:Docker Volume(卷)

Docker Volume 是推薦的長期數據存儲和共享方式,特別是在生產環境。

創建卷

docker volume create my-volume

運行容器時掛載卷

docker run -d --name my-container -v my-volume:/app/data image-name

訪問卷中的數據

卷會存儲在宿主機的 Docker 數據目錄中,通常位於 /var/lib/docker/volumes/

方法三:Bind Mount(綁定掛載)

Bind Mount 直接將宿主機的目錄或文件掛載到容器中。

基本語法

docker run -d -v /path/on/host:/path/in/container image-name

實際例子

# 掛載整個目錄
docker run -d --name web-server -v /home/user/www:/var/www/html nginx

# 掛載只讀
docker run -d --name app -v /config/app.conf:/etc/app.conf:ro my-app

# 掛載可讀寫
docker run -d --name app -v /data:/app/data:rw my-app

Bind Mount 的優勢

  • 直接訪問宿主機文件
  • 容器中的更改立即反映在宿主機
  • 性能較好
  • 便於開發和調試

方法四:COPY vs ADD(Dockerfile 中)

在構建 Docker 鏡像時,可以使用 COPY 或 ADD 指令來包含文件。

# 使用 COPY
FROM ubuntu:20.04
COPY local/file /container/path
COPY ./app /opt/app

# 使用 ADD(支持 URL 和自動解壓)
ADD https://example.com/file.tar.gz /tmp/
ADD ./app.tar.gz /opt/

性能對比

方法

速度

用途

持久性

docker cp

中等

臨時文件傳輸


Volume


數據持久化


Bind Mount


開發/調試


COPY/ADD


鏡像構建


常見場景和最佳實踐

場景 1:日誌收集

# 使用 Bind Mount 收集日誌
docker run -d -v /var/log/myapp:/var/log/app my-app

場景 2:開發環境同步

# 實時同步代碼
docker run -d -v $(pwd):/app --name dev-env my-dev-image

場景 3:配置管理

# 配置文件使用 Bind Mount(只讀)
docker run -d -v /etc/app/config.yml:/app/config.yml:ro my-app

最佳實踐

  1. 選擇合適的方法
  • 臨時文件:使用 docker cp
  • 持久數據:使用 Volume
  • 開發調試:使用 Bind Mount
  • 鏡像構建:使用 COPY/ADD
  1. 權限管理
  • 確保文件權限正確
  • 在容器中使用非 root 用户
  • 使用 :ro 標誌來限制寫入權限
  1. 性能優化
  • 避免複製大量小文件
  • 使用 .dockerignore 排除不必要的文件
  • 對大文件使用流式處理
  1. 錯誤處理
# 檢查容器是否存在
docker inspect <container_id>

# 查看容器日誌
docker logs <container_id>

# 檢查掛載情況
docker inspect -f '{{json .Mounts}}' <container_id>

故障排除

問題 1:Permission Denied(權限拒絕)

# 檢查文件權限
ls -l /path/to/file

# 修改權限
chmod 755 /path/to/file

# 或在 docker run 中指定用户
docker run -u 0 my-image

問題 2:文件不同步

# 確保使用了正確的掛載方式
# 如果是 Bind Mount,檢查路徑是否正確
docker inspect <container_id> | grep -A 10 Mounts

問題 3:容器內文件修改不反映到宿主機

# 檢查是否使用了 :ro(只讀)標誌
docker inspect -f '{{json .Mounts}}' <container_id>

# 移除 :ro 標誌重新掛載
docker run -v /host/path:/container/path:rw my-image

總結

Docker 與宿主機之間的文件複製有多種方法,每種方法都有其適用場景:

  • docker cp:簡單快速,適合一次性文件傳輸
  • Volume:企業級數據管理,提供最佳的持久化
  • Bind Mount:開發友好,實時反映文件變化
  • COPY/ADD:鏡像構建時的文件包含

選擇正確的方法能夠大大提高工作效率,希望本文能幫助你更好地使用 Docker。