Dockfile 是一种被 Docker 程序解释的脚本,Dockerfile 由一条一条的指令组成,每条指令对应 Linux 下面的一条命令。Docker 程序将这些 Dockerfile 指令翻译真正的 Linux 命令。
Dockerfile 有自己书写格式和支持的命令,Docker 程序解决这些命令间的依赖关系,类似于 Makefile。 Docker 程序将读取 Dockerfile,根据指令生成定制的 image。Dockerfile 明确的表明 image 是怎么产生的。有了 Dockerfile,当需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
RUN 命令有两种模式
RUN <command>
(shell 模式, 直接执行 shell 命令, 在 Linux 上默认执行的是 /bin/sh -c
,在 Windows上默认执行的是 cmd /S /C
)
RUN ["executable", "param1", "param2"]
(exec 模式)
RUN 的换行符是 \
注意:多行命令不要写多个 RUN,原因是 Dockerfile 中每一个指令都会建立一层.多少个 RUN 就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
RUN 是构件容器时就运行的命令以及提交运行结果。
CMD
命令有三种模式:
CMD ["executable","param1","param2"]
(exec 模式, 这是默认模式)
CMD ["param1","param2"]
(ENTRYPOINT 的默认 parameters)
CMD command param1 param2
(shell 模式)
注意:因为参数传递后,docker 解析的是一个 JSON array, 所以参数一定要用双引号 "
,不能是单引号 '
。
CMD 是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子。
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
为 image 添加 LABEL, LABEL 可以为多个键值对,可以写成如下形式。
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
需要注意的是,最好不要写成多个 LABEL, 最好写成一行,太长的话使用 \
进行换行,重复的 Key 会被覆盖。
MAINTAINER
MAINTAINER <name>
EXPOSE
EXPOSE <port> [<port>/<protocol>...]
该命令通知 Docker 在运行的时候侦听指定的网络端口。可以指定侦听的是 TCP 还是 UDP,如果未指定协议,则默认为 TCP。
如果同时侦听 TCP 和 UDP 的 80 端口:
EXPOSE 80/tcp
EXPOSE 80/udp
需要注意的是,此方式暴露出的端口并不会直接让主机监听,注意如果想监听,需要在 Docker 启动时加上 -p
参数。
docker run -p 80:80/tcp -p 80:80/udp ...
ENV <key> <value>
ENV <key>=<value> ...
此命令的功能为设置环境变量,差别在于第一种一行只能设置一个,第二种可以再一行设置多个。
For example:
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
ADD 命令有两种模式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
(如果路径中带空格需要使用此模式)
<src>
可以包含通配符,匹配的规则使用的是 Go 的 filepath.Match 。
For example:
ADD hom* /mydir/ # adds all files starting with "hom"
ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
<dest>
可以是一个绝对路径,也可以是相对于 WORKDIR
的路径。
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
如果包含特殊字符,则需要使用 Golang 规则进行转换,防止将特殊字符当成通配符处理. 例如要拷贝文件名为 arr[0].txt
的文件。
ADD arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/
如果将 <src>
写成 URL,则类似于 wget
命令。
ADD http://example.com/foobar /
尽量不要把 <scr>
写成一个文件夹,如果 <src>
是一个文件夹,会复制整个目录的内容,包括文件系统元数据。
COPY 包含两种模式:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
(如果路径中带空格需要使用此模式)
COPY 是复制命令,与 ADD 的差别在于,<src>
只能是本地文件,其他用法一致
ENTRYPOINT
ENTRYPOINT 有两种模式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec form, preferred)
ENTRYPOINT command param1 param2
(shell form)
功能是设定启动时执行的默认命令。
与CMD比较说明:
只能写一条,如果写了多条,那么只有最后一条生效
容器启动时才运行,运行时机相同
ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖
如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ls -al
那么将执行ls -al ,top -b不会执行。
设置变量命令,ARG 命令定义了一个变量,在 docker build
创建镜像的时候,使用 --build-arg <varname>=<value>
来指定参数。如果用户在 build 镜像时指定了一个参数没有定义在 Dockerfile 中,那么将有一个 Warning。
[Warning] One or more build-args [foo] were not consumed.
ONBUILD
ONBUILD [INSTRUCTION]
此命令只有在另一个 image 以此 image 作为基础镜像,在 Build 时执行。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
此命令会在另外一个 image 以此 image 为基础镜像 build 时执行。
STOPSIGNAL
STOPSIGNAL signal
此命令设置镜像的退出信号。