HOWTO · Docker
将文件从主机复制到 Docker 容器
本教程演示如何将文件从主机复制到 Docker 容器。
本页内容
若只需向现有容器传送一次文件,请使用 docker cp,并分别提供本地主机的源路径和容器内的目标路径:
docker cp ./local-file CONTAINER:/existing-directory/
将 CONTAINER 替换为容器名称或 ID。docker cp 可用于运行中的容器,也可用于已停止的容器。相对本地路径从运行命令的目录解析;容器路径以 / 为根,开头的斜杠可省略。完整语法和规则请参阅 Docker cp 参考。
复制文件到现有容器
以下命令将当前主机目录的 hello.txt 复制到 demo-app 容器的 /opt/。目标目录必须已存在:
docker cp ./hello.txt demo-app:/opt/
如果 /opt/ 存在,容器中会得到 /opt/hello.txt。末尾的斜杠明确表示目标是已有目录。目标若为已有文件,docker cp 会替换其内容;可能造成风险时应先检查。
可在运行中的容器里直接执行命令来验证复制结果:
docker exec demo-app ls -l /opt/hello.txt
列表中应显示该文件。docker exec 要求容器正在运行,而 docker cp 同时支持已停止的容器。
复制目录或只复制目录内容
docker cp 会递归复制目录。源路径的写法决定目标接收目录本身,还是只接收其内容:
# Creates /opt/host-files/ in the container.
docker cp ./host-files demo-app:/opt/
# Copies the contents of host-files into the existing /opt/incoming/ directory.
docker cp ./host-files/. demo-app:/opt/incoming/
第二条命令要求 /opt/incoming/ 已存在。/. 后缀可以只复制内容,而不额外创建一层 host-files 目录。Docker 不会创建缺失的父目录;以 / 结尾的目标必须是已有目录。文件和目录的完整情况见 docker cp 目标规则。
在 docker cp、Dockerfile COPY 和 bind mount 之间选择
| 需求 | 使用方式 | 原因 |
|---|---|---|
| 立即向一个现有容器加入文件 | docker cp |
在该容器的文件系统中创建一次性副本。 |
| 每次构建镜像都包含文件 | Dockerfile COPY |
将构建上下文中的文件加入镜像。 |
| 开发时让主机目录与容器保持共享 | bind mount | 运行时共享该路径,而非创建另一份副本。 |
要将应用文件放入镜像,请在 Dockerfile 中使用:
COPY ./config.yaml /app/config.yaml
COPY 是构建时指令,不能修改已经存在的容器。它的源路径相对于构建上下文解释,通常不能使用该上下文以外的路径。详见 Dockerfile COPY 参考。
若需要持续共享,在创建容器时使用 bind mount:
docker run --mount type=bind,source=/absolute/host/path,target=/app/input,readonly IMAGE
bind mount 是共享存储,不是复制。若不使用 readonly,容器进程可以修改或删除它有权访问的主机文件。若这正是实际需要,请参阅挂载主机目录以实时共享文件;Docker 也说明了 bind mount 的共享和权限取舍。
也不要用 docker cp 配置镜像:副本存在于这个容器可写的文件系统中,停止再启动同一个容器后仍在,但从镜像新建的替换容器不会带有它。
避免常见的 docker cp 失败
复制前检查路径。本地源必须存在。将本地文件复制到一个不存在且末尾没有 / 的目标时,Docker 可以在该精确路径创建文件,但不会创建父目录。源为目录时,如果其父目录存在,Docker 可以创建最后一级目标目录;但不能把目录复制到文件上。
默认情况下,复制进容器的文件归目标用户和组所有,通常为 root:root。只有在保留源 UID 和 GID 对容器用户合适时才添加 -a。本地符号链接默认按链接本身复制;要复制其指向的目标,请使用 -L。目标路径的权限也可能使复制结果无法使用。
最后,docker cp 无法复制某些容器系统路径,例如 /proc、/sys、/dev 下的资源、临时文件系统以及用户创建的挂载。此类情况需要采用容器特定的方案,并查看文档列出的限制。