如何用 docker compose cp 在本地文件系统与服务容器之间复制文件?
【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose
当你用 Docker Compose 运行多容器应用后,经常需要在宿主机(本地文件系统)和服务容器之间传递文件:把配置、脚本塞进容器,或者把容器里生成的日志、结果文件取出来。docker compose cp就是为这件事设计的命令,它支持文件和目录的双向复制,并且以“服务名”而不是容器 ID 作为定位方式。本文以仓库中端到端测试工程使用的 Compose 项目为例,演示完整的操作与验证路径。
准备条件
- 已安装 Docker Compose CLI:Windows 和 macOS 上它随 Docker Desktop 提供;Linux 上需要从本仓库的 release 页面下载二进制文件,重命名为
docker-compose后放入$HOME/.docker/cli-plugins或系统级插件目录(见 README 的 “Where to get Docker Compose” 一节)。 - 一个已经
docker compose up启动、且目标服务有运行中容器的项目。cp依赖运行中的容器,服务没有容器时会直接报错no container found for service ...。
下面示例使用仓库测试工程的 Compose 定义 pkg/e2e/testdata/TestCopy/compose.yaml,它启动一个长期存活的容器,便于随时拷入拷出文件:
services: nginx: image: alpine init: true command: sleep infinity本地准备好一个源文件cp-me.txt(文档示例中内容为hello world),以及一个目录cp-folder(内含cp-me.txt,文档示例内容为hello world from folder)。
命令语法与路径规则
cp命令的两种用法(来自 cmd/compose/cp.go 的命令定义):
docker compose cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|- docker compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH- 带
SERVICE:前缀的参数指向容器内路径,不带前缀的本地路径自动对应本地文件系统; - 参数支持绝对本地路径(如
/tmp/data),相对路径若以./开头,即使包含:也按本地路径处理(例如./file:name.txt不会误判为服务名); - 用
-代替本地路径表示标准输入/输出,详见后文“用标准输入输出替代文件”。
可选参数(来自 docs/reference/compose_cp.md):
| 参数 | 说明 |
|---|---|
--all | 把run命令创建的一次性容器也纳入目标 |
-a,--archive | Archive 模式,复制所有 uid/gid 信息 |
--dry-run | 以 dry run 模式执行命令 |
-L,--follow-link | SRC_PATH 为符号链接时始终跟随链接 |
--index | 服务有多个副本时指定容器序号,默认0(不指定副本) |
把本地文件复制到容器
在服务容器已启动的前提下执行:
docker compose cp ./cp-me.txt nginx:/tmp/default.txt这会读取本地相对路径(或任意本地路径)下的cp-me.txt,写入服务nginx容器的/tmp/default.txt。容器内目标不存在时,只要其父目录存在即可成功;容器内目标可以是目录也可以是普通文件,其他类型会导致destination "..." must be a directory or a regular file错误。
用docker exec验证文件确实进入容器(<project>替换为你项目名,多副本时容器名为<project>-nginx-1等):
docker exec <project>-nginx-1 cat /tmp/default.txt文档示例输出为hello world,这是测试文件的内容,用于确认拷贝成功。
把容器中的文件复制到本地
方向反过来,SERVICE:SRC_PATH作为第一个参数:
docker compose cp nginx:/tmp/default.txt ./from-default.txt执行后本地工作目录会出现from-default.txt,可用任意方式查看其内容确认,例如:
cat ./from-default.txt文档示例中该文件内容为hello world。
目录同样支持双向复制,命令形式与文件一致,只是路径指向目录:
# 本地目录 -> 容器 docker compose cp ./cp-folder nginx:/tmp # 容器目录 -> 本地 docker compose cp nginx:/tmp/cp-folder ./cp-folder2仓库测试用docker exec <project>-nginx-1 cat /tmp/cp-folder/cp-me.txt验证目录进入容器后内容可读,用检查本地./cp-folder2/cp-me.txt的内容验证目录拷出成功(文档示例内容均为hello world from folder)。
多副本服务:默认行为与 --index
测试用例 pkg/e2e/cp_test.go 用 5 个副本演示了副本相关的规则,如果你的服务设置了多副本(如docker compose up -d --scale nginx=5),需要注意:
- 本地复制到服务:默认写到所有副本。验证方式是对任意副本分别执行
docker exec检查,例如docker exec <project>-nginx-3 cat /tmp/default.txt应能看到文件。 - 服务复制到本地:默认只从第 1 个副本读取。
- 用
--index指定单个副本(序号从 1 开始,如--index=3对应nginx-3):
# 只写入第 3 个副本 docker compose cp --index=3 ./cp-me.txt nginx:/tmp/indexed.txt # 从第 3 个副本读取 docker compose cp --index=3 nginx:/tmp/indexed.txt ./from-indexed.txt测试中对未指定的副本执行docker exec <project>-nginx-2 cat /tmp/indexed.txt预期以退出码 1 失败,说明--index只影响所选副本,其余副本不会收到文件。
用标准输入输出替代文件
路径参数中的-表示标准流:
- 容器到终端:
docker compose cp nginx:/tmp/default.txt -,内容会输出到 stdout; - 标准输入到容器:
docker compose cp - nginx:/tmp/,从 stdin 读取并写入容器内的目录,此时容器内目标必须是目录,否则报错destination "..." must be a directory。
限制与注意事项
- 不支持服务之间直接复制:源和目标同时写成
SERVICE:PATH形式时,命令会报copying between services is not supported。需要中转的话,先从服务拷到本地,再从本地拷到另一个服务。 --all的作用范围:默认cp的目标不含run命令创建的一次性容器;服务以run方式运行了一次性容器时,加--all才会把这些容器纳入目标(参考 docs/reference/compose_cp.md 的选项说明)。-L, --follow-link:容器内 SRC_PATH 是符号链接时,默认复制链接本身,加-L会跟随链接复制实际内容(见 pkg/compose/cp.go 中copyFromContainer的处理逻辑)。--dry-run:以 dry run 模式执行,用于在不实际执行的情况下查看命令行为。
完整命令选项以 docs/reference/compose_cp.md 为准;cp在命令总览中的位置见 docs/reference/compose.md。如果你的场景是“从服务取文件到本地”之外的方向(例如容器之间搬运文件),当前文档不支持直接跨服务复制,需要走本地中转。
【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考