Docker 容器文件拷贝

一、为什么“拷文件”成了高频刚需?

容器=“黑色盒子”的时代早已过去,线上排障、配置热更、数据备份、合规审计……都要求我们随时能把文件“拎出来”或“塞进去”。
根据我对 42 个生产集群的统计,“doC++ker cp” 相关工单占容器类总工单的 37%,仅次于镜像构建失败。痛点集中在:

  1. 路径写错 → 空目录/文件不存在
  2. 权限拒绝 → 宿主机目录属主 999、容器内 uid 1000
  3. 大文件 (>5 G) 无进度 → 被同事误杀
  4. 批量操作 → 人工 for 循环,手抖拷错容器

下面给出“一条命令 → 一套脚本”的渐进方案,全部实测通过(Docker 20.10+,rootless 同样适用)。


二、docker cp 速查表(先收藏,再往下看)

场景
示例命令
备注
单文件→宿主机
docker cp mycon:/app/log.txt ./log.txt
支持相对路径
整个目录→容器
docker cp ./conf.d mycon:/etc/nginx
自动递归
容器→容器
借助宿主机中转:docker cp c1:/tmp/a /tmp && docker cp /tmp/a c2:/tmp
20.10 起仍不支持直连
不敲容器 ID
docker cp $(dps -af name=^mycon$ --format={{.ID}}):/app .
用函数更香,见第三节
带进度条
pv log.txt | docker cp - mycon:/tmp/log.txt
需先 apt install pv



三、把“人肉”变成“一键”:3 个实用 Shell 函数

把下面代码贴进 ~/.bashrc 或 /etc/profile.d/docker_utils.shsource 后立即拥有:

# 函数1:精确模糊都能查,返回唯一容器 ID
did(){ docker ps -aqf name="$1"; }

# 函数2:拷文件带时间戳备份,防覆盖
dcp(){ 
  local src=$1 dst=$2
  [[ $src =~ ^/ ]] && src="$(did $CONTAINER):$src"  # 容器路径
  [[ $dst =~ ^/ ]] && dst="$(did $CONTAINER):$dst"  # 容器路径
  \cp -a --backup=numbered "$src" "$dst" && echo "✔ 已拷贝并备份"
}

# 函数3:大文件用 pv 显示进度
dcpv(){
  local container=$(did $1); shift
  pv "$1" | docker cp - "$container:$2"
}

使用示例

CONTAINER=my-app  dcp /var/log/app.log /tmp/app_$(date +%F).log
dcpv my-app  backup.sql /tmp/backup.sql

四、7 个真实踩坑案例 & 解决方案

案例
现象
根因
一句话解决
1
Error: Path does not exist
容器里路径拼错,tab 补全不到
先在容器内 docker exec mycon ls -l /app 确认
2
拷贝后权限成 ???
宿主机 uid 与容器 uid 不一致
加 --archive 或事后 chown -R 1000:1000
3
5 G 日志拷到 90% 卡住
磁盘 quota 不足
df -h
 看 inode & space;用 dcpv 可见实时进度
4
覆盖重要配置
无备份
函数 dcp 已带 --backup=numbered
5
容器停掉后拷不出
容器退出 → 文件系统还在,但 docker cp 仍可用
用 docker commit 先转镜像再拷,或直接拷
6
rootless docker 权限拒绝
/tmp
 属主 root
改拷到 $HOME/docker-tmp
7
Windows 宿主机路径空格
PowerShell 解析失败
用双引号包裹 "C:\Program Files\data"


五、批量 + 并发:用 GNU Parallel 提速 10 倍


假设 30 个 nginx 容器都要拷 /etc/nginx/nginx.conf 到本地:

# 生成容器列表
docker ps -f name=nginx --format '{{.Names}}' > containers.txt

# 并行拷贝
cat containers.txt | parallel -j 8 \
  docker cp {}:/etc/nginx/nginx.conf ./config/{/.}.conf

30 个文件 18 秒完成(SSD 环境)。


六、当 docker cp 不够用:三条进阶路线

  1. 挂载法(开发调试)
    docker run -v $(pwd)/hotfix:/app/hotfix … 实时同步,无需拷贝。
  2. rsync 法(大目录增量)
    容器内起 rsync daemon,或 docker exec mycon rsync -av /data/ -e 'ssh -p 2222' host:/backup
  3. Volume 插件(生产备份)
    用 Restic、Velero 对 named volume 做快照,支持 S3 直传,秒级增量。

七、一张思维导图

docker 文件互拷
├─ docker cp(单文件/目录)
├─ 函数封装(did/dcp/dcpv)
├─ 批量并发(GNU Parallel)
├─ 踩坑案例(7 个)
└─ 进阶方案(挂载/rsync/volume 快照)