不进入容器怎么读写文件?docker cp 看起来简单,但源路径末尾的 /.、目标路径存不存在、拷到挂载目录里,结果各不相同。这篇逐一实测,包括一个会悄悄丢文件的情形。
docker cp src {容器}:/d1(/d1 已存在):/d1 下:/d1/src/a.txt | /d1/src/sub/b.txt
docker cp src/. {容器}:/d2(/d2 已存在):/d2 下:/d2/a.txt | /d2/sub/b.txt
docker cp src {容器}:/d3/newname(/d3 不存在)→ 退出码 1;Error response from daemon: Could not find the file /d3 in container cc392b8bc1ce1c90fbd55d9efcca4f6
docker cp src {容器}:/newname(/newname 不存在,但上级 / 存在):/newname/a.txt | /newname/sub/b.txt(目录被改名为 newname)docker cp src 容器:/d1 在 /d1 已存在时会得到 /d1/src/…;docker cp src/. 容器:/d2 只拷内容。目标不存在但上级存在时,源目录被改名成目标名;上级也不存在则报错退出码 1。
宿主机文件属主 uid=501:不带 -a:501:20;带 -a(archive):501:20 容器里属主 1234:5678 的文件拷出来:不带 -a → 宿主机上 uid=501;带 -a → uid=501(带 -a 的 docker cp 退出码 0;输出 无)
在 macOS 的 Docker Desktop 上,拷进容器的文件属主是宿主机的 uid:gid(501:20),带不带 -a 一样;拷出时属主也是当前用户。这是这台机器上的观察,Linux 宿主机上默认的属主处理我没有测。
docker cp 到 命名卷 /vol:退出码 0;容器里读到 = one docker cp 到 bind mount /bnd:退出码 0;容器里读到 = one docker cp 到 tmpfs /tmp1:退出码 0;容器里读到 = cat: can't open '/tmp1/x.txt': No such f docker cp 到 普通可写层 /plain:退出码 0;容器里读到 = one tmpfs 目录里实际有什么:(空) bind mount 目录在宿主机上有 x.txt 吗?True 容器已停止:docker cp 进去 → 退出码 0;再 docker cp 出来 → 退出码 0,内容 one
拷到命名卷、bind mount 都成功;拷到 tmpfs 挂载点,命令退出码为 0 但文件不在。要往 tmpfs 里放文件,只能用 docker exec 之类的方式(本文没有逐一试)。
拷出容器里的符号链接 /lnk:不带 -L → 符号链接 → /etc/os-release;带 -L → 普通文件(189 字节) 拷出 /etc/hostname(Docker 为容器生成的文件):退出码 0;内容 = 3650c7c6d258;容器 ID 前 12 位 = 3650c7c6d258
默认拷出符号链接本身,-L 才拷内容。Docker 为容器生成的 /etc/hostname 也能拷出来,内容是容器 ID 的前 12 位。
64 MiB 拷进容器 3 次:[669, 1159, 799] ms(中位数 799);拷出 3 次:[612, 513, 438] ms(中位数 513) 拷回来的文件和原文件一致吗?True
64 MiB 拷进容器 0.7~1.2 秒,拷出 0.4~0.6 秒(3 次);内容一致。docker cp 是把文件打成 tar 流经 API 传输的,大量小文件的开销我没有测。