Docker COPY 复制文件夹的诡异行为

问题现象

在制作 docker 镜像时,有复制某一个路径下所有文件和文件夹到镜像的需求,写下了如下 dockerfile:

FROM alpine
WORKDIR /root/test_docker_proj
COPY * ./

原始目录结构是这样的:

/projects/test_docker_proj
├── Dockerfile
├── dir1
│   ├── dir11
│   │   └── file11
│   └── file1
└── file2

然而复制到 docker 镜像里的目录结构变成了这样:

/root/test_docker_proj
├── Dockerfile
├── dir11
│   └── file11
├── file1
└── file2

可以看到 dir1 这个文件夹并没有被复制到镜像里,但是 dir1 中的子文件夹和文件都被复制进来了,和 dir1 同级的文件也被复制了。也就是说,在 COPY 执行的过程中,第一层文件夹被「解包」了。

COPY/ADD 行为逻辑

为了确定 COPY 和相似的 ADD 命令的行为,做了以下测试:

FROM alpine

WORKDIR /root/test_docker_proj_1
COPY * ./

WORKDIR /root/test_docker_proj_2
ADD * ./

WORKDIR /root/test_docker_proj_3
COPY ./ ./

WORKDIR /root/test_docker_proj_4
ADD ./ ./

WORKDIR /root/test_docker_proj_5
COPY ./dir* ./

WORKDIR /root/test_docker_proj_6
ADD ./dir* ./

通过测试可以发现 COPY/ADD 命令有这么几个规则:

  1. ADD 命令和 COPY 命令在复制文件时行为一致
  2. 使用 * 作为 COPY/ADD 命令的源时候表示的是 ./*
  3. COPY/ADD 命令的源如果是文件夹,复制的是文件夹的内容而不是其本身
  4. COPY ./* target 中的 * 会被翻译成如下的逻辑:
COPY ./sub_dir1 target
COPY ./sub_dir2 target
COPY ./file1 target
COPY ./file2 target

文件系统里的文件夹和文件,本质上都是文件,我们熟悉的操作系统的 cp 命令在执行 cp * target 时会把文件夹当成文件一股脑的复制到目标路径下,可以认为复制了文件本身,而 docker 的 COPY/ADD 在复制文件夹时复制的是其内容

docker 的这种「奇怪」的逻辑已经被诟病许久了,但是似乎还没有要改变的意思,最新的进展可以参考下面两个 issue,在 docker 做出修改之前,只能在写 dockerfile 时候注意一下了。

参考文档

https://stackoverflow.com/questions/30256386/how-to-copy-multiple-files-in-one-layer-using-a-dockerfile

https://github.com/moby/moby/issues/15858

https://github.com/moby/moby/issues/29211

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • docker基本概念 1. Image Definition 镜像 Image 就是一堆只读层 read-only...
    慢清尘阅读 8,839评论 1 21
  • 在前面两节我们学习了如何安装以及简单的运行管理docker容器,在本节我们将会更多的探讨关于docker镜像的知识...
    井底蛙蛙呱呱呱阅读 4,155评论 0 5
  • 原文地址:https://github.com/KeKe-Li/docker-directive docker 存...
    萌面菠萝阅读 520评论 0 0
  • 实例来源:tofar 摘录来源:Docker — 从入门到实践 欢迎大家添加自己的实例 (email: yun_...
    molscar阅读 439评论 1 1
  • Docker简介Docker是一个由GO语言写的程序运行的“容器”; 目前云服务的基石是操作系统级别的隔离,在同一...
    gakiww阅读 570评论 0 0