Dockerfile中有许多指令,详细且全面的介绍参考官方文档
FROM
指令格式:
FROM <image> [AS <name>]
或者
FROM <image>[:<tag>] [AS <name>]
或者
FROM <image>[@<digest>] [AS <name>]
FROM指令设置一个基础镜像,让后面的指令可以在一个镜像中运行,可以是任何在镜像库中存在的镜像,一般作为是Dockerfile的第一条指令
ARG
是唯一可以放在FROM
之前的指令FROM
可以在同一个Dockerfile里面出现多次tag
和digest
参数不是必填的,如果不填默认是latest
也就是最后的版本
了解FROM和ARG的交互方式
FROM
指令可以使用在FROM
之前声明的任何ARG
变量
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
FROM
之前声明的变量如果想在FROM
之后再次被其他指令使用需要重新声明
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
RUN
RUN
指令用于指定镜像被构建时要运行的命令。有两种格式:
RUN <command> (shell格式,命令在shell中执行)
RUN ["executable", "param1", "param2"] (exec格式)
可以用反斜杠\
表示换行
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
等同于
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
CMD
CMD
指令用于指定一个容器启动时要运行的命令。有三种格式:
CMD ["executable","param1","param2"] (exec格式,首选)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell格式)
如docker run命令可以覆盖CMD指令,如果在Dockerfile文件中指定了CMD指令,而同时在docker run命令行中指定了要运行的命令,命令行的命令会覆盖Dockerfile中的CMD指令。
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 multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
可以使用 docker inspect
命令查看这些标签
MAINTAINER (deprecated)
指定作者信息,指令格式:
MAINTAINER <name>
官方推荐使用LABEL
指令添加作者信息而不是使用MAINTAINER
指令,这样就可以使用docker inspect
命令查看这些信息
LABEL maintainer="SvenDowideit@home.org.au"
EXPOSE
开放容器内的端口给外部,可以指定端口是在TCP还是UDP上侦听,如果未指定协议,则默认值为TCP。
这个指令只是开放容器内部端口给外部,并不能指定宿主的映射端口,如果需要配置映射关系需要在 docker run
用 -p
指定端口映射关系。指令格式
EXPOSE <port> [<port>/<protocol>...]
例如开放容器内80的TCP和UDP,格式是一行,当然也可以写成两行
EXPOSE 80/tcp
EXPOSE 80/udp
ENV
ENV指令用来在镜像构建过程中设置环境变量,后续的RUN可以使用它所创建的环境变量。
指令格式:
ENV <key> <value>
ENV <key>=<value> ...
新建一个Dockerfile添加如下内容
FROM ubuntu
ENV env varible
生成镜像,运行容器,会看到声明的环境变量
[root@Charlie env]# docker build -t test/env .
···
[root@Charlie env]# docker run -it test/env /bin/bash
root@3a27a7e4598f:/# env
···
env=varible
···
如果在 docker run -e
指定了某个环境变量值,就会覆盖Dockerfile中原先的配置值
[root@Charlie env]# docker run -it -e "env=run_command" test/env /bin/bash
root@0cf1a2954574:/# env
···
env=run_command
···
ADD
是将宿主机文件复制到镜像中,指令格式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
<dest>
路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径;
<src>
可以是一个本地文件或者是一个本地压缩文件,还可以是一个url;
如果把<src>
写成一个url,那么ADD就类似于wget命令。
例如将构建目录下的 test.txt
文件复制到镜像中 /usr/local/test.txt
文件
ADD test.txt /usr/local/test.txt
文件源也可以使用url的格式,例如下载最新的wordpress压缩包 latest.zip
到/usr/local
命名为wordpress.zip
ADD https://wordpress.org/latest.zip /usr/local/wordpress.zip
如果将本地归档文件(tar archive),合法的归档文件(gzip、bzip2、xz)指向到文件夹,Docker会自动解压,下面会将latest.tar.gz
文件自动解压到镜像的/usr/local/wordpress/
目录下
ADD latest.tar.gz /usr/local/wordpress/
COPY
是将宿主机文件复制到镜像中,与ADD
功能相同,区别是ADD
可以使用url下载远程服务器的文件复制到镜像中,ADD
还可以自动解压某些压缩包,这两个功能COPY
都不可以。指令格式:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] (this form is required for paths containing whitespace)
ENTRYPOINT
CMD指令用于指定一个容器启动时要运行的命令。指令格式:
ENTRYPOINT ["executable", "param1", "param2"] (exec格式,首选)
ENTRYPOINT command param1 param2 (shell格式)
与CMD
功能类似,只能写一条,如果写了多条,只有最后一条生效,上文提到在运行docker run
命令行时如果指定了要运行的命令会覆盖Dockerfile中的CMD
指令,差异就在这里ENTRYPOINT
指令是无法被docker run
命令行指定的指令覆盖的。
如果在Dockerfile中同时写了ENTRYPOINT
和CMD
,它们两个会互相覆盖,谁在最后谁生效。
ENTRYPOINT
和CMD
不同组合的执行情况(这里展示效果不好可以直接去官网查看):
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
VOLUME
VOLUME
指令相当于创建一个挂载点,保存数据到容器挂载的这个文件夹。指令格式:
VOLUME ["/data"]
参数可以是个Json串,
VOLUME ["/var/log/"]
或者一个或多个值
VOLUME /var/log
VOLUME /var/log /var/db
当容器中的数据需要持久化的时候需要使用这个命令。
USER
设置启动容器的用户名(或者UID)和用户组(或者GID)来运行Dockerfile里面RUN
, CMD
and ENTRYPOINT
指令。指令格式:
USER <user>[:<group>]
USER <UID>[:<GID>]
WORKDIR
WORKDIR
指令设置RUN
, CMD
, ENTRYPOINT
, COPY
和 ADD
指令的工作目录,如果设置的工作目录不存在会自动创建。指令格式:
WORKDIR /path/to/workdir
WORKDIR
指令可以设置多次,下面例子的pwd
命令执行结果是 /a/b/c
:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
WORKDIR
指令还可以解析ENV
指令设置的环境变量,下面例子pwd
命令执行结果是/path/$DIRNAME
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
ARG
ARG
指令设置变量,指令格式:
ARG <name>[=<default value>]
在docker build创建镜像的时候,使用 --build-arg <varname>=<value>
来指定参数,如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning
[Warning] One or more build-args [foo] were not consumed.
一个Dockerfile文件中可以有一个或者多个ARG
定义的变量,如下的例子ARG
定义的参数都是可用的
FROM busybox
ARG user1
ARG buildno
···
也可以给变量设置一个默认值
FROM busybox
ARG user1=someuser
ARG buildno=1
···
ONBUILD
当一个Dockerfile文件中使用了ONBUILD
指令,生成了镜像A,这个镜像A中是不执行ONBUILD
指令的内容的,但是如果镜像B是以镜像A作为基础镜像时,镜像B中就会执行这个ONBUILD
指令。指令格式:
ONBUILD [INSTRUCTION]
STOPSIGNAL
STOPSIGNAL命令是的作用是当容器退出时给系统发送什么样的指令。指令格式:
STOPSIGNAL signal
HEALTHCHECK
指令格式:
HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令检查容器健康状况)
HEALTHCHECK NONE (在基础镜像中取消健康检查)
HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
CMD
后面可以接以下选项:
- –interval=DURATION (default: 30s)
- –timeout=DURATION (default: 30s)
- –start-period=DURATION (default: 0s)
- –retries=N (default: 3)
返回值:
- 0: success – 表示容器是健康的
- 1: unhealthy – 表示容器已经不能工作了
- 2: reserved – 保留值
如下例子:健康检查命令是:curl -f http://localhost/ || exit 1;两次检查的间隔时间是5秒;命令超时时间为3秒。
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
SHELL
指令格式:
SHELL ["executable", "parameters"]
SHELL指令允许覆盖用于shell形式的命令的默认shell 。Linux上的默认shell是["/bin/sh", “-c”]
,而在Windows上[“cmd”, “/S”, “/C”]
。
SHELL指令必须以JSON格式写入Dockerfile;
SHELL指令可以多次出现。每条SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令。