Build Context(构建上下文)
在使用docker build命令通过Dockerfile创建镜像时,会产生一个build context(构建上下文)。所谓的构建上下文就是docker build命令的PATH或URL指定的路径中的文件的集合。在镜像build过程中可以引用上下文中的任何文件,比如我们要介绍的ADD和COPY指令就可以引用上下文中的文件。
ADD
ADD指令用于将构建上下文中指定的文件添加到镜像中的,支持两种形式的写法:
ADD src dest
ADD ["src", "dest"]
ADD指令有以下几个特点:
1. 如果指定的 src 是归档文件(tar, zip, tgz, xz 等)会自动将其解压。
2. 如果指定的 src 是目录,只会添加目录中的内容而不包含目录自身。
3. 如果指定的 src 是 URL 地址,会从 URL 地址下载文件并将其添加到 dest,如果下载的文件是归档文件不会自动解压。
通过一个简单的栗子来说明
当前构建上下文目录结构:
root# tree
.
├── a
│ ├── a.log
│ └── b.log
├── alpine-minirootfs-3.9.3-x86_64.tar.gz
├── a.txt
└── Dockerfile
1 directory, 5 files
1 | FROM scratch |
执行docker build -t alpine .构建镜像:
root# docker build -t alpine .
Sending build context to Docker daemon 2.689MB
Step 1/6 : FROM scratch
--->
Step 2/6 : WORKDIR /workspaces
---> Running in 669cd08b2be7
Removing intermediate container 669cd08b2be7
---> 894324123641
Step 3/6 : ADD alpine-minirootfs-3.9.3-x86_64.tar.gz /
---> 471bc43f5e0c
Step 4/6 : ADD a.txt .
---> d22c05b89d9d
Step 5/6 : ADD a .
---> 54a77a7a1dd8
Step 6/6 : ADD https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master .
Downloading 537kB
---> a443738c3f2f
Successfully built a443738c3f2f
Successfully tagged alpine:latest
Step 1/6获取空白镜像,Step 2/6指定镜像工作空间为/workspaces,Step 3/6添加alpine-minirootfs-3.9.3-x86_64.tar.gz归档文件到镜像中,Step 4/6添加a.txt文件到镜像中,Step 5/6添加a目录到镜像中,Step 6/6下载归档文件并添加到镜像中。
执行docker run -it alpine /bin/sh启动容器:
root# docker run -it alpine /bin/sh
/workspaces # ls /
bin etc lib mnt proc run srv tmp var
dev home media opt root sbin sys usr workspaces
/workspaces # ls -l
total 708
-rw-r--r-- 1 root root 0 May 13 08:56 a.log
-rw-r--r-- 1 root root 0 May 13 08:55 a.txt
-rw-r--r-- 1 root root 0 May 13 08:56 b.log
-rw------- 1 root root 721697 Jan 1 1970 master
可以看到alpine-minirootfs-3.9.3-x86_64.tar.gz文件添加到/根目录,由于是归档文件被自动解压了。a.txt文件添加到当前目录,也就是工作目录(/workspaces)。a目录中的内容添加到当前目录(只添加目录中的内容而不包含目录自身),https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master下载的归档文件添加到当前目录,不会自动解压(URL下载和归档解包功能不能一起使用)。
解决添加目录,只添加目录中的内容而不包含目录自身的问题
上面的栗子可以看出,本意是要添加a目录到镜像中,结果只添加a目录下面的内容到镜像中。解决这个问题也很简单,稍微修改下Dockerfile文件:
1 | ADD a . |
改为:
1 | ADD a ./a |
解决从 URL 地址下载归档文件不自动解压的问题
解决从URL地址下载归档文件不自动解压的问题,思路也很简单,不自动解压那我们手动解压就是了:
1 | ADD https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master . |
上面的方法虽然可行,但Docker官方不建议这么使用!Docker官方建议我们当需要从远程复制文件时,最好使用curl或wget命令来代替ADD命令。原因是,当使用ADD命令时,会创建更多的镜像层,当然镜像的size也会更大。现在我们使用wget来替代上面的命令:
1 | RUN wget https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master && unzip master && rm master |
COPY
COPY指令用于将构建上下文中指定的文件复制到镜像中的,同样支持两种形式的写法:
COPY src dest
COPY ["src", "dest"]
与ADD不同的是COPY不会自动解压归档文件,也不支持URL作为src参数,因此不能用于从远程位置下载文件。COPY可以看做是ADD的精简版本。
使用 ADD 还是 COPY?
使用ADD还是COPY?Docker团队的建议是在几乎所有情况下都使用COPY。唯一需要使用ADD的情况是需要自动解压归档文件。ADD通过URL下载文件则使用curl或wget代替。