Dockerfile中DSL语法

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是常见的联合使用方式。主要用于每次运行相同的可执行文件,但运行参数会有变化的场景。
相关推荐
iconball6 小时前
个人用云计算学习笔记 --18(NFS 服务器、iSCSI 服务器)
linux·运维·笔记·学习·云计算
₯㎕星空&繁华17 小时前
阿里云服务器安装MySQL服务器
服务器·ubuntu·阿里云·云计算
你的大佬9991 天前
阿里云百炼ai模型
人工智能·阿里云·云计算
一只栖枝1 天前
备考华为HCIA - 云计算,培训与自学到底该怎么选?
云计算·华为认证·hcia·考证·职业规划
数据与人工智能律师2 天前
AI的法治迷宫:技术层、模型层、应用层的法律痛点
大数据·网络·人工智能·云计算·区块链
荣光波比2 天前
Docker(三)—— Docker Compose 编排与 Harbor 私有仓库实战指南
运维·docker·容器·云计算
企鹅侠客2 天前
mysqldump导入备份数据到阿里云RDS会报错吗
阿里云·adb·云计算
iHero2 天前
【Jitsi Meet】阿里云Docker安装Jitsi Meet后的调整
阿里云·docker·云计算
荣光波比2 天前
Ansible(三)—— 使用Ansible自动化部署LNMP环境实战指南
运维·自动化·云计算·ansible
荣光波比2 天前
Docker(五)—— Docker Compose 一键搭建 LNMP 架构并部署 WordPress
运维·docker·容器·云计算