Dockerfile中的DSL语法

ADD

添加文件或目录或远程文件url,如果是个压缩包,会自动解压,来自远程url的资源不会被解压缩

语法1:ADD [--chown=:] ...

语法2:ADD [--chown=:] ["",... ""]

注意点1:如果以斜杠/结尾,则认为是一个目录,的内容将以/base()的格式写入;如果不是,的内容将被写入

注意点2:可以使用通配符*或者?

注意点3:如果指定了多个资源,无论是直接还是由于使用通配符,那么必须是一个目录,并且必须以斜杠/结尾

注意点4:如果不存在,则会在其路径中创建所有缺失的目录

注意点5:待添加的本地源文件必须放在build context目录下

ADD log ./image_log
ADD --chown=1 log* ./
ADD l?g /home/

ARG

定义一个变量,与ENV不同,仅在构建时生效,定义时尽量给默认值,不设定默认值变量为空

语法:ARG [=]

ARG VER=latest
ARG STR="hello"

CMD

docker run时运行该命令,在build时期不运行

语法1:CMD ["executable","param1","param2"] ,exec形式写法,首选

语法2:CMD ["param1","param2"] ,作为ENTRYPOINT的默认参数传入

语法3:CMD command param1 param2 ,shell形式写法

注意点1:一个Dockerfile中只能有一条CMD指令。如果列出多个CMD,则只有最后一个CMD生效。

注意点2:CMD的主要目的是为执行容器提供默认值(通常为可执行文件)。也可以忽略可执行文件,在这种情况下,还必须指定ENTRYPOINT指令,即语法2的用法。

注意点3:如果用户指定了docker run的命令行参数,那么它们将覆盖CMD中指定的默认值。命令行参数位置为后。

注意点4:如果使用shell形式的CMD,那么和ENTRYPOINT的注意点4一样,将在/bin/sh -c中执行

注意点5:与ENTRYPOINT的注意点5一样的问题

CMD ["echo", "-e", "hello"]
CMD echo -e hello
#和ENTRYPOINT配合使用,作为默认参数传入
ENTRYPOINT ["echo", "-e"]
CMD ["hello"]

COPY

拷贝文件或目录,用法几乎和ADD一致,ADD的注意点也是适用的,但不会解压文件,也无法使用url拷贝远程文件

语法1:COPY [--chown=:] ...

语法2:COPY [--chown=:] ["",... ""]

注意点1:不会复制目录本身,只会复制其下的内容

注意点2:可以设置COPY参数——from=,用来拷贝上一个构建阶段的镜像(用FROM ..AS )或者已构建的镜像中的内容。

注意点3:待复制的本地源文件必须放在build context目录下

COPY log ./image_log
COPY --chown=1 log* ./
COPY l?g /home/

ENTRYPOINT

docker run时运行该命令,在build时期不运行

语法1:ENTRYPOINT ["executable", "param1", "param2"] ,exec格式

语法2:ENTRYPOINT command param1 param2 ,shell格式

注意点1:一个Dockerfile中只能有一条ENTRYPOINT指令。如果列出多个ENTRYPOINT,则只有最后一个ENTRYPOINT生效。

注意点2:docker运行的命令行参数将被附加在执行表单ENTRYPOINT的所有元素之后,并将覆盖使用CMD指定的所有元素。命令行参数位置为后。

注意点3:可以使用docker run --entrypoint标志覆盖ENTRYPOINT指令。

注意点4:shell形式写法防止使用任何CMD或run命令行参数来修改启动参数,但有一个缺点,即ENTRYPOINT将作为/bin/sh -c的子命令启动,它接受信号但不传递信号给子命令。这意味着可执行文件不会是容器的PID 1,也不会收到Unix信号,所以你的可执行文件不会收到来自docker stop 的SIGTERM,但利用exec启动可以避免该问题,例如ENTRYPOINT exec top -b。

注意点5:与shell形式不同,exec形式不调用命令shell。这意味着正常的shell处理不会发生。例如,ENTRYPOINT ["echo", "HOME"]不会对HOME进行变量替换。如果需要shell处理,那么要么使用shell形式,要么直接执行shell,例如:ENTRYPOINT ["sh", "-c", "echo $HOME"]

ENTRYPOINT ["echo", "-e", "hello"]
ENTRYPOINT echo -e hello
#和CMD配合使用
ENTRYPOINT ["echo", "-e"]
CMD ["hello"]

ENV

设定环境变量,作用范围是后续的命令以及在image中

语法:ENV =

ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV OTHER_NAME="John Jams" OTHER_DOG=Other\ Dog \
    OTHER_CAT=Tom

EXPOSE

设定容器运行时监听的网络端口,默认为tcp

语法:EXPOSE [/...]

注意点:在docker run时可以使用-p参数来覆盖

EXPOSE 80
EXPOSE 8080/udp

FROM

引入基础镜像

语法:FROM [--platform=] [:] [AS ]

注意点:平台,tag,name都可以省略

FROM --platform=linux/amd64 ubuntu:20.04 AS eastcom-ubuntu

HEALTHCHECK

告诉Docker如何测试容器,以检查容器内进程是否仍在正常工作,因为可能出现容器内进程在运行但是状态出现问题例如死循环。

语法1:HEALTHCHECK [OPTIONS] CMD command 通过在容器内运行命令检查容器运行状况,命令的退出状态表示健康状态:0,健康;1,不健康;2,保留

[OPTIONS]可以设置以下配置 --interval=DURATION (default: 30s) --timeout=DURATION (default: 30s) --start-period=DURATION (default: 0s) --retries=N (default: 3)

语法2:HEALTHCHECK NONE 禁用从base镜像继承的任何健康检查

注意点:一个Dockerfile中只能有一条HEALTHCHECK指令。如果列出多个HEALTHCHECK,则只有最后一个HEALTHCHECK生效。

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

LABEL

为镜像设置元数据标签

语法:LABEL = = = ...

注意点:可设置多个,构建完毕后可用docker inspect 查看

LABEL version=1.0
LABEL name=Jerry year=20

MAINTAINER

标明作者,官网已注明弃用

语法:MAINTAINER

MAINTAINER EASTCOM-CLOUD

ONBUILD

将任意一个触发命令(除ONBUILD、FROM和MAINTAINER指令,后两者指令可能不会被触发)添加到父image(也就是该dockerfile构建的image)中,在子image FROM 父image时触发该命令

语法:ONBUILD

ONBUILD RUN echo "build2"

RUN

在新镜像层运行命令并提交结果。生成的提交镜像将用于Dockerfile中的下一步。

语法:RUN 或RUN ["executable", "param1", "param2"]

注意点:注意需要转义反斜杠

RUN mkdir /vol
RUN ["/bin/bash", "-c", "echo eastcom > /vol/hello.txt"]

SHELL

使用设定的shell来覆盖默认值(linux下为sh,Windows下为cmd),对后续所有命令生效

语法:SHELL ["executable", "parameters"]

注意点:要注意的是只能使用JSON格式的写法

SHELL ["/bin/bash", "-c"]

STOPSIGNAL

停止容器时向容器内应用程序发送定义的信号

若不定义,docker守护进程也会发送默认信号SIGTERM然后等待一小段时间,以便进程可以正常退出。如果该进程未在宽限期内终止(默认为10秒,可自定义),它将发送SIGKILL

当容器内程序能侦听不同信号时,例如用户自定义的信号SIGUSR1,这个命令比较有用,可以用来覆盖默认值。

语法:STOPSIGNAL signal

STOPSIGNAL SIGKILL
STOPSIGNAL 9

USER

指定image中的用户名和可能的组

语法1:USER [:]

语法2:USER [:]

注意点:需要先执行命令添加用户和组,并且后续的dockerfile命令都是以该用户执行

RUN groupadd -r eastcom && useradd -r -g eastcom Tom
USER Tom:eastcom

VOLUME

在容器内创建一个具有指定名称的挂载

语法:VOLUME ["/data"]或VOLUME /data

注意点:主机目录在创建或者运行时声明不能在dockerfile中声明,挂载点本质上是依赖于主机的。这么做是为了保持映像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。

在docker run时若没指定宿主机的路径,则使用默认路径/var/lib/docker/volumes//_data

VOLUME ["/vol"]

WORKDIR

进入某一路径下目录,若该目录不存在,则会创建后进入

语法:WORKDIR /path/to/workdir

WORKDIR /home

Dockerfile

#定义一个变量,与ENV不同,仅在构建时生效,定义时需要给默认值
#语法:ARG <name>[=<default value>]
ARG VER=20.04

#引入基础镜像
#语法:FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
#平台,tag,name都可以省略
FROM --platform=linux/amd64 ubuntu:${VER} AS eastcom-ubuntu

#标明作者,官网已注明弃用
#语法:MAINTAINER <name>
MAINTAINER EASTCOM-CLOUD

#为镜像设置元数据标签
#语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...
#可设置多个,构建完毕后可用docker inspect <container-name>查看
LABEL version=1.0

ARG STR="Hello"

#进入已存在的目录
#语法:WORKDIR /path/to/workdir
WORKDIR /home

#使用设定的shell来覆盖默认值(linux下为sh,Windows下为cmd),对后续所有命令生效
#语法:SHELL ["executable", "parameters"]
#注意点:要注意的是只能使用JSON格式的写法
SHELL ["/bin/bash", "-c"]

#在新镜像层运行命令并提交结果。生成的提交镜像将用于Dockerfile中的下一步。
#语法:RUN <command>或RUN ["executable", "param1", "param2"]
#注意点:注意需要转义反斜杠
RUN mkdir /vol
RUN ["/bin/bash", "-c", "echo $STR > /vol/greeting"]

#在容器内创建一个具有指定名称的挂载点
#语法:VOLUME ["/data"]或VOLUME /data
#注意点:主机目录在创建或者运行时声明不能再dockerfile中声明,挂载点本质上是依赖于主机的。为了保持映像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。
#在docker run时若没指定宿主机的路径,则使用默认路径/var/lib/docker/volumes/<volume ID>/_data
VOLUME ["/vol"]

#设定容器运行时监听的网络端口,默认为tcp
#语法:EXPOSE <port> [<port>/<protocol>...]
#注意点:在docker run时可以使用-p参数来覆盖
EXPOSE 80/tcp

#设定环境变量,作用范围是后续的命令以及在image中
#语法:ENV <key>=<value>
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV OTHER_NAME="John Jams" OTHER_DOG=Other\ Dog \
    OTHER_CAT=Tom

RUN groupadd -r eastcom && useradd -r -g eastcom Tom
#指定image中的用户名和可能的组
#语法1:USER <user>[:<group>]
#语法2:USER <UID>[:<GID>]
#注意点:需要先执行命令添加用户和组
USER Tom:eastcom

#添加文件或目录或远程文件url,如果是个压缩包,会自动解压,来自远程url的资源不会被解压缩
#语法1:ADD [--chown=<user>:<group>] <src>... <dest>
#语法2:ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
#注意点1:如果<dest>以斜杠/结尾,则认为是一个目录,<src>的内容将以<dest>/base(<src>)的格式写入;如果不是,<src>的内容将被写入<dest>
#注意点2:可以使用通配符*或者?
#注意点3:如果指定了多个<src>资源,无论是直接还是由于使用通配符,那么<dest>必须是一个目录,并且必须以斜杠/结尾
#注意点4:如果<dest>不存在,则会在其路径中创建所有缺失的目录
ADD log ./image_log
ADD --chown=1 log* ./
ADD l?g /home/

#拷贝文件或目录,用法几乎和ADD一致,ADD的注意点也是适用的,但不会解压文件,也无法使用url拷贝远程文件
#语法1:COPY [--chown=<user>:<group>] <src>... <dest>
#语法2:COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
#注意点1:不会复制目录本身,只会复制其下的内容
#注意点2:可以设置COPY参数——from=<name>,用来拷贝上一个构建阶段的镜像(用FROM ..AS <name>)或者已构建的镜像中的内容。
COPY log ./image_log
COPY --chown=1 log* ./
COPY l?g /home/

#将任意一个触发命令(除ONBUILD、FROM和MAINTAINER指令,后两者指令可能不会被触发)添加到父image(也就是该dockerfile构建的image)中,在子image FROM 父image时触发该命令
#语法:ONBUILD <INSTRUCTION>
ONBUILD RUN echo "build2"

#停止容器时向容器内应用程序发送定义的信号
#若不定义,docker守护进程也会发送默认信号SIGTERM然后等待一小段时间,以便进程可以正常退出。如果该进程未在宽限期内终止(默认为10秒,可自定义),它将发送SIGKILL
#当容器内程序能侦听不同信号时,例如用户自定义的信号SIGUSR1,这个命令比较有用,可以用来覆盖默认值。
#语法:STOPSIGNAL signal
STOPSIGNAL SIGKILL

#告诉Docker如何测试容器,以检查容器内进程是否仍在正常工作,因为可能出现容器内进程在运行但是状态出现问题例如死循环。
#语法1:HEALTHCHECK [OPTIONS] CMD command 通过在容器内运行命令检查容器运行状况,命令的退出状态表示健康状态:0,健康;1,不健康;2,保留
# [OPTIONS]可以设置以下配置
# --interval=DURATION (default: 30s)
# --timeout=DURATION (default: 30s)
# --start-period=DURATION (default: 0s)
# --retries=N (default: 3)
#语法2:HEALTHCHECK NONE 禁用从base镜像继承的任何健康检查
#注意点:一个Dockerfile中只能有一条HEALTHCHECK指令。如果列出多个HEALTHCHECK,则只有最后一个HEALTHCHECK生效。
HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

#docker run时运行该命令,在build时期不运行
#语法1:ENTRYPOINT ["executable", "param1", "param2"] ,exec格式
#语法2:ENTRYPOINT command param1 param2 ,shell格式
#注意点1:一个Dockerfile中只能有一条ENTRYPOINT指令。如果列出多个ENTRYPOINT,则只有最后一个ENTRYPOINT生效。
#注意点2:docker运行<image>的命令行参数将被附加在执行表单ENTRYPOINT的所有元素之后,并将覆盖使用CMD指定的所有元素。命令行参数位置为<image>后。
#注意点3:可以使用docker run --entrypoint标志覆盖ENTRYPOINT指令。
#注意点4:shell形式写法防止使用任何CMD或run命令行参数来修改启动参数,但有一个缺点,即ENTRYPOINT将作为/bin/sh -c的子命令启动,它接受信号但不传递信号给子命令。这意味着可执行文件不会是容器的PID 1,也不会收到Unix信号,所以你的可执行文件不会收到来自docker stop <container>的SIGTERM,但利用exec启动可以避免该问题,例如ENTRYPOINT exec top -b。
#注意点5:与shell形式不同,exec形式不调用命令shell。这意味着正常的shell处理不会发生。例如,ENTRYPOINT ["echo", "$HOME"]不会对$HOME进行变量替换。如果需要shell处理,那么要么使用shell形式,要么直接执行shell,例如:ENTRYPOINT ["sh", "-c", "echo $HOME"]
ENTRYPOINT ["echo", "-e"]

#docker run时运行该命令,在build时期不运行,同时下面的写法CMD作为ENTRYPOINT的入参
#语法1:CMD ["executable","param1","param2"] ,exec形式写法,首选
#语法2:CMD ["param1","param2"] ,作为ENTRYPOINT的默认参数传入
#语法3:CMD command param1 param2 ,shell形式写法
#注意点1:一个Dockerfile中只能有一条CMD指令。如果列出多个CMD,则只有最后一个CMD生效。
#注意点2:CMD的主要目的是为执行容器提供默认值(通常为可执行文件)。也可以忽略可执行文件,在这种情况下,还必须指定ENTRYPOINT指令,即语法2的用法。
#注意点3:如果用户指定了docker run的命令行参数,那么它们将覆盖CMD中指定的默认值。命令行参数位置为<image>后。
#注意点4:如果使用shell形式的CMD,那么和ENTRYPOINT的注意点4一样,<command>将在/bin/sh -c中执行
#注意点5:与ENTRYPOINT的注意点5一样的问题
CMD ["CMD"]

#上述ENTRYPOINT和CMD是常见的联合使用方式。主要用于每次运行相同的可执行文件,但运行参数会有变化的场景。
03-31 06:25