Dockerfile 指令详解
COPY 复制文件
命令格式:
- COPY [--chown=<user>:<group>] <源和路径>... <目标路径>
- COPY [--chown=<user>:<group>] ["<源和路径>",... "<目标路径>"]
和 RUN
指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。
COPY
指令将从构建上下文目录中 <源路径>
的文件/目录复制到新的一层的镜像内的 <目标路径>
位置。
<源路径>
可以是多个, 甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match
规则。
<目标路径>
可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR
指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
注意:使用 COPY
指令,源文件的各种元数据都会保留。比如读,写,执行权限,文件变更时间等。
在使用该指令的时候还可以加上 --chown=<user>:<group>
选项来改变文件的所属用户及所属组。
如果源路径为文件夹,复制的时候不是直接复制该文件夹,而是将文件夹中的内容复制到目标路径。
ADD 更高级的复制文件
ADD
指令和 COPY
的格式和性质基本一致。但是在 COPY
基础上增加来一些功能。
<源路径>
可以是一个URL
,这种情况下,Docker 引擎会试图去下载这个链接的文件放到<目标路径>
去。下载之后的文件权限自动设置为600
,如果这并不是想要的权限,那么还需要增加额外的一层RUN
进行权限调整,另外,如果下载的是一个压缩包,需要解压缩,也一样还需要额外的一层RUN
指令进行解压缩。因此,这个功能其实并不实用,不推荐使用- 如果
<源路径>
为一个tar
压缩文件的话,压缩格式为gzip
,bzip2
以及xz
的情况下,ADD
指令将会自动解压缩到<目标路径>
在 Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY
,因为 COPY
的语义很明确,就是复制文件。最适合使用 ADD
的场景,就是提及的需要自动解压缩的场合。
另外需要注意的是,ADD
指令会另镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
CMD 容器启动命令
CMD
指令的格式和 RUN
相似,也是两种格式:
- shell
格式:CMD <命令>
- exec
格式: CMD ["可执行文件", "参数1", "参数2"...]
- 参数列表格式:CMD ["参数1","参数2"...]
。在指定了 ENTRYPOINT
指令后,用 CMD
指定具体的参数
在指令格式上,一般推荐使用 exec
格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 "
, 而不要使用单引号
如果使用 shell
格式的话,实际的命令会被包装为 sh -c
的参数的形式进行执行。比如:
systemd
去启动后台服务,容器内没有后台服务的概念。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其他辅助进程不是它需要关心的东西。
ENTRYPOINT 入口点
ENTRYPOINT
的格式和 RUN
指令格式一样,分为 exec
格式和 shell
格式。
ENTRYPOINT
的目的和 CMD
一样,都是在指定容器启动程序及参数。
ENTRYPOINT
在运行时也可以替代,不过比 CMD
要略显烦琐,需要通过 docker run
的参数 --entrypoint
来指定
当指定了 ENTRYPOINT
后,CMD
的含义就发生了改变,不再是直接的运行其命令,而是将 CMD
的内容作为参数传给 ENTRYPOINT
指令,换句话说实际执行时将变为:
ENV 设置环境变量
格式有两种:
- ENV <key> <value>
- ENV <key1>=<value1> <key2>=<value2>
ARG 构建参数
格式: ARG <参数名>[=<默认值>]
构建参数和 ENV
的效果一样,都是设置环境变量。所不同的是,ARG
所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。docker history
还是可以看到所有值的。
Dockerfile
中的 ARG
指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build
中用 --build-arg <参数>=<值>
来覆盖。
ARG指令有生效范围,如果在 FROM
指令之前指定,那么只能用于 FROM
指令中。对于多阶段构建,尤其要注意这个问题。