docker cp 是 Docker 容器与宿主机间双向复制文件/目录的最直接命令,支持运行或停止的容器,语法为 docker cp [OPTIONS] SRC_PATH DEST_PATH,其中路径可为相对或绝对路径,容器路径须以 / 开头。

docker cp 是最直接、最常用的方式,容器无论运行或停止都能用,不需要改镜像、不依赖挂载、也不用进容器执行命令。
用 docker cp 复制单个文件或整个目录
docker cp 的语法是:docker cp <宿主机路径> <容器名或ID>:<容器内路径>
常见操作:
复制单个文件(目标路径含文件名)
docker cp ./config.yaml nginx-container:/etc/nginx/conf.d/default.conf复制整个目录(注意宿主机路径末尾带
/,否则会被当作文本重命名)docker cp ./logs/ nginx-container:/var/log/app/容器名可以用 ID 替代,比如
abc123def456宿主机路径支持相对路径(如
./file.txt)和绝对路径(如/home/user/data.json)容器内路径必须是绝对路径,从
/开始,例如/app/config/,不能写成app/config
容易踩的坑:
- 目标目录不存在时,
docker cp会自动创建它,但只到最后一级;如果写成/a/b/c/d/file.txt而/a/b不存在,会失败 - 如果宿主机路径末尾没加
/,且目标容器路径是目录,Docker 会把源文件“重命名”为该目录名(例如docker cp dir nginx-container:/tmp→/tmp变成一个叫tmp的文件,不是目录) - 不支持复制
/proc、/sys、/dev、tmpfs或容器内 mount 的路径
容器正在运行?试试 docker exec + cat 流式写入
适用于无法用 docker cp(比如权限受限环境),且容器里有 sh 或 bash 和 cat。
命令格式:docker exec -i <容器名> sh -c 'cat > /path/in/container' < /host/file.txt
示例:docker exec -i redis-server sh -c 'cat > /data/init.sql' < ./init.sql
说明:
- 这种方式绕过文件系统层级,靠标准输入流写入,适合小文件
- 容器必须正在运行,且要有 shell 和
cat(Alpine 镜像默认有,scratch 镜像没有) - 不保留原始文件权限、时间戳、属主信息
- 如果目标路径父目录不存在,会报错(
sh: can't create /path/to/file: No such file or directory)
需要保留权限/时间戳?用 tar 管道
tar 方式能完整保留权限、所有者、时间戳、符号链接等元数据,适合生产环境配置同步。
命令格式:tar -cC /host/dir . | docker exec -i <容器名> tar -xC /container/target
示例(把当前目录下所有内容复制进容器 /app):tar -c . | docker exec -i app-server tar -xC /app
说明:
-
tar -cC中的-C指定打包起点目录,避免路径污染 -
tar -xC在容器内解包时也用-C切换根目录,确保路径干净 - 不依赖容器是否安装
tar?其实绝大多数基础镜像(Ubuntu、CentOS、Alpine)都自带 - 注意:如果宿主机目录里有设备文件、socket 或 FIFO,
tar会跳过或报错,需加--warning=no-file-ignored抑制
别忘了:复制后常要手动调整权限
docker cp 和 tar 方式复制进去的文件,UID/GID 默认继承宿主机用户(比如你本地是 UID 1000,进容器后还是 UID 1000),但容器内可能没有对应用户,导致服务读取失败。
典型表现:
- Nginx 启动报
open() "/etc/nginx/nginx.conf" failed (13: Permission denied) - Redis 拒绝加载
.rdb文件 - Python 应用提示
PermissionError: [Errno 13] Permission denied
解决办法(进容器后执行):
- 查看目标进程运行用户:比如
ps aux | grep nginx发现是www-data - 改属主:
chown www-data:www-data /etc/nginx/nginx.conf - 改权限(必要时):
chmod 644 /etc/nginx/nginx.conf - 更稳妥的做法是在 Dockerfile 里用
COPY+RUN chown固化,而不是运行时复制
真正麻烦的不是“怎么拷”,而是“拷完能不能用”——权限、路径存在性、用户上下文,这三个点漏掉一个,服务就起不来。


















