Dockerfile指令大全

Dockerfile文件由一系列指令和参数组成。指令的一般格式为INSTRUCTION arguments。具体来说,包括"配置指令"(配置镜像信息)和"操作指令"(具体执行操作)。每条指令,如FROM,都是大小写不敏感的。但是为了区分指令和参数,强烈建议统一使用大写字母。Dockerfile中的指令会按顺序从上到下执行,所以应根据需要合理安排指令的顺序。一个Dockerfile文件以FROM指令作为构建开始的第一个指令。每条指令都会创建一个新的镜像层并对镜像进行提交。Dockerfile目前支持的指令中具体如下表所述:

分类指令描述
配置指令ARG定义创建镜像过程中使用的变量
配置指令FROM指定所创建镜像的基础镜像
配置指令LABEL为生成的镜像添加元数据标签信息
配置指令MAINTAINER(deprecated)指定镜像的作者,不推荐使用,可以使用LABEL指令替换
配置指令EXPOSE声明镜像内服务监听的端口
配置指令ENV指令环境变量
配置指令ENTRYPOINT指定镜像的默认入口命令
配置指令VOLUME创建一个数据卷挂载点
配置指令USER指定运行容器时的用户名和用户组等信息
配置指令WORKDIR配置工作目录
配置指令ONBUILD创建子镜像时指定自动执行的操作指令
配置指令STOPSIGNAL指定退出的信号值
配置指令HEALTHCHECK配置所启动容器如何进行健康检查
配置指令SHELL指定默认shell类型
操作指令RUN运行指定命令
操作指令CMD启动容器时指定默认执行的命令
操作指令ADD添加内容到镜像
操作指令COPY复制内容到镜像

更多Dockerfile指令的介绍可以参考Docker官网Dockerfile reference一文。

ARG

ARG指令用来定义构建镜像过程中需要使用的变量。指令格式如下:

ARG <name> [=<default value>]

在Dockerfile文件中使用ARG指令的示例如下:

ARG IMAGE_VERSION
RUN echo $IMAGE_VERSION

可见,这里使用$+变量的方式引用声明的变量。
这样在执行docker build时,可以通过–build-arg参数来为变量赋值。

$docker build --build-arg IMAGE_VERSION=V1

当使用docker build命令成功构建镜像后,ARG声明的变量将不再存在 (ENV指定的变量将在镜像中保留)。也就是说,ARG指令声明的变量,只存在构建阶段,并不会代入到镜像中,更不可能出现在容器中。
Docker内置了一些镜像创建变量,用户可以直接使用而无须声明,包括(不区分大小写)HTTP PROXY 、HTTPS PROXY、FTP PROXY、 NO PROXY等。
更多ARG介绍可以参考官网ARG一文。

FROM

FROM指令用来指定一个父镜像,以开始新的构建阶段。Dockerfile支持在一个文件中使用多个FROM指令,以创建多个镜像。FROM的指令格式如下:

FROM [--platform=<platform>] <image>[:<tag>|@<digest>|-] [AS <name>]

其中,–platform参数用来指定镜像应用的平台,主要应用于多平台场景,如linux/amd64或linux/arm64 等;tag和digest用来指定需要引用的镜像的tag,如果不指定,则使用latest。如果一个Dockerfile中需要创建多个镜像,会使用到多个FROM。如果下一个FROM指令中需要使用上一个FROM指令构建的镜像,可以现在上一个FROM指令中定义别名,也即使用AS <name>。某些场景下,不需要父镜像,如构建一个操作系统镜像,这时可以使用"FROM scratch"这个指令来表示不需要父镜像。
可以在FROM指令前使用ARG指令,但是FROM前的指令只能用于FROM指令,不能用于FROM后的指令,如果需要使用,还需重新声明。之所以会这样,是因为FROM代表一次构建,如果在FROM之前声明变量,则这个变量是在这次构建之外的,也就无法在构建中使用。示例如下:

ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version

上述示例中,ARG中定义的第一个VERSION只能用于FROM指令,FROM后面的指定无法使用。为了使用VERSION变量,在RUN指定前又声明了一个VERSION。
更多FROM指令介绍可以参考官网FROM一文。

LABEL

LABEL指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像。格式为

LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL <key>=<value> \<key>=<value> \<key>=<value> \...

可以使用上面两种方式的任何一种方式来使用LABEL,为生成的镜像添加元数据标签信息。如果LABEL的key或value包含空格、点号等特殊字符,可以使用双引号来引用。使用示例如下:

LABEL version=V1
LABEL "image verison"="V1.0.0"
LABEL author="hello-world@github.com" date="2024-03-07"
LABEL author="hello-world@github.com" \date="2024-03-07"

需要说明的是,使用FROM构建的镜像会继承父镜像(parent)的LABEL信息。如果LABEL中存在同名的key,则最近定义的key的value将覆盖已存在的key的value。
可以使用docker image inspect命令来查看指定镜像中包含的LABEL信息。示例如下:

$ docker image inspect --format='{{json .Config.Labels}}' target-image-name-or-id

更多LABEL指令介绍可以参考官网LABEL一文。

MAINTAINER(deprecated)

MAINTAINER指令可以用来指定镜像作者信息。格式为:

MAINTAINER <name>

不推荐使用MAINTAINER来指定镜像作者信息,推荐使用LABEL来指定镜像作者信息。使用LABEL来记录作者信息会以元数据方式存储,可以通过docker image inspect命令方便的查询。使用LABEL指令记录镜像作者信息示例如下:

LABEL author="hello-world@github.com" date="2024-03-07"

EXPOSE

EXPOSE指令用来声明镜像内服务监听的端口。指令格式为:

EXPOSE <port> [<port/<protocol>...]

一个服务可能需要监听多个端口,且不同的端口使用的协议不同。使用示例如下:

EXPOSE 22
EXPOSE 22/tcp
EXPOSE 80/udp

在EXPOSE指令中,如果不指定协议,则默认是tcp协议。
注意该指令只是起到声明的作用,并不会自动完成端口的映射。如果要映射端口出来,在启动容器时可以使用-P参数 (Docker主机会自动分配一个宿主机的临时端口)或-p HOST_PORT:CONTAINER_PORT参数(具体指定所映射的本地端口)。不推荐EXPOSE的使用方式,因为EXPOSE并不会完成容器到宿主机的端口映射,只是起到一个声明的效果。如果期望使用EXPOSE指令,还需和docker run命令的-P参数联合使用。这显然不符合关注点分离思想,且-P参数会分配一个随机端口,不推荐使用这种方式。
更多EXPOSE指令介绍可以参考官网EXPOSE一文。

ENV

ENV指令用来定义环境变量。指令格式为:

ENV <key1> <value1>  
ENV <key1>=<value1> <key2>=<value2>  

在使用ENV指令定义环境变量时,key和value之间的等号可以省略,但是不推荐这么做,因为省略等号后,一个ENV指令只能定义一个key-value。推荐使用带等号的方式定义环境变量。
一个ENV指令可以同时定义多个key-value,且对于特殊字符,可以使用双引号包裹。使用示例如下:

ENV JAVA_HOME=/etc/bin JRE="/etc/jre"  
ENV "JAVA HOME"="/etc/bin"

与ARG指令定义的变量只能应用于镜像构建阶段不同,ENV指令不仅可以应用于镜像构建阶段,还会持久化到镜像中,并可在容器运行时使用。
ENV定义的环境变量在Dockerfile中使用的方式与ARG定义的变量的使用方式一致,都是使用$+变量名的方式,使用示例如下:

ENV JAVA_HOME=/etc/bin JRE="/etc/jre"  
RUN echo $JAVA_HOME

可以使用docker image inspect命令来查看指定镜像中包含的ENV信息。示例如下:

$ docker image inspect --format='{{json .Config.Env}}' target-image-name-or-id

更多ENV指令介绍可以参考官网ENV一文。

CMD

CMD指令用来指定启动容器时默认执行的命令。支持三种格式:

CMD ["executable","param1", "param2"],exec模式,相当于执行 executable param1 param2,推荐方式  
CMD command param1 param2, shell模式,在默认的shell中执行,提供给需要交互的应用  
CMD ["param1","param2"],exec模式,提供给ENTRYPOINT指令的默认参数  

每个Dockerfile中,只能有一条CMD指令。如果出现了多个CMD指令,不会报错,但只有最后一条会被执行。如果用户启动容器时候手动指定了运行的命令(作为docker run命令的参数),则会覆盖掉CMD指定的命令。
CMD指令中的命令不会在镜像构建中执行,而是在启动容器时执行。更多CMD指令介绍可以参考官网CMD一文。

ENTRYPOINT

ENTRYPOINT指令用来指定默认可执行文件。支持两种格式:

ENTRYPOINT ["executable", "paraml1", "param2"],exec模式,相当于执行 executable param1 param2
ENTRYPOINT command param1 param2,shell模式,在默认的shell中执行,提供给需要交互的应用  

在执行docker run命令时,对于CMD指令,docker run命令中的参数会覆盖CMD指令中的参数,而对于ENTRYPOINT指令中的参数,而不会被覆盖,ENTRYPOINT指令中的参数会被保留。但是,如果docker run命令中使用了–entrypoint选项,则也将覆盖ENTRYPOINT指令指定的命令。
与CMD指令一样,每个Dockerfile中只能有一个ENTRYPOINT,如果出现了多个ENTRYPOINT指令,只有最后一个起效。

CMD和ENTRYPOINT的关系

CMD指令和ENTRYPOINT均用来定义启动容器时需要执行的命令。两者需遵循以下规则:
(1) Dockerfile中至少有一个CMD或ENTRYPOINT指令。
(2) 每个Dockerfile中只能有一个ENTRYPOINT/CMD生效,如果出现了多个ENTRYPOINT/CMD指令,只有最后一个起效。
(3) 当容器是一个可执行程序时,应该优先使用ENTRYPOINT。
(4) CMD可用来为ENTRYPOINT提供默认参数,也可用来在容器中执行临时命令(ad-hoc command)。
(5) docker run命令中的参数会覆盖CMD指令中的相同参数,但不会覆盖ENTRYPOINT。如果docker run命令中使用–entrypoint选项,则会覆盖ENTRYPOINT指令中的命令。
CMD和ENTRYPOINT的关系可以用下表表示:

No ENTRYPOINTENTRYPOINT exec_entry p1_entryENTRYPOINT [“exec_entry”, “p1_entry”]
No CMDerror, not allowed/bin/sh -c exec_entry p1_entryexec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry exec_cmd p1_cmd
CMD exec_cmd p1_cmd/bin/sh -c exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

上表中,如果一个Dockerfile中即不存在CMD指令,也不存在ENTRYPOINT指令,则会导致构建报错。对同时存在CMD指令和ENTRYPOINT指令的场景,要根据指令使用的exec模式或shell模式,进行如下划分:如果ENTRYPOINT指令是shell模式,则会忽略CMD指令;如果ENTRYPOINT指令是exec模式,CMD指令是exec模式,则CMD指令的命令失效,参数会追加到ENTRYPOINT指令上;如果ENTRYPOINT指令是exec模式,CMD指令是shell模式,则先执行ENTRYPOINT指令,再执行CMD指令。
更多ENTRYPOINT指令介绍可以参考官网ENTRYPOINT一文。

RUN

RUN指令用来执行构建命令。一条RUN指令会在当前镜像的最上层创建一个新的层。RUN指令支持两种格式:

## Shell form,默认在 shell 终端中运行命令
RUN [OPTIONS] <command> ...
## Exec form,使用 exec 执行,不会启动 shell 环境
RUN [OPTIONS] [ "<command>", ... ]

其中使用双引号的方式,会被解析为JSON数组,所以必须使用双引号。
如果需要使用其他类型shell,也可在exec格式中指定shell,示例如下:

RUN ["/bin/bash", "- C", "echo hello"]

但是,上述方式并不会更改当前构建上下文的默认shell,如果需要修改,可以使用SHELL指令。
注意,每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。所以,为减少镜像层数,通常将多个RUN指令合并成一条RUN指令执行,使用&&连接指令。当指令较长时,可以使用\来换行。示例如下:

RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \ 
&& rm -rf /var/cache/apt

更多RUN指令介绍可以参考官网RUN一文。接下来重点介绍RUN指令支持的OPTIONS。

–mount选项

RUN指令使用–mount选项来调整命令执行时的网络环境类型。–link选项是BuildKit的一个新功能,可能在不同版本的Docker中有所不同,在使用前需先确认该功能是否可以可用。指令格式如下:

RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]

type的类型常用类型有如下几种:
(1) bind:这种挂载类型允许将上下文或镜像中的目录(只读)绑定到正在构建的容器中。需要注意的是,由于RUN指令只在容器构建阶段生效,因此挂载的目录也仅在该阶段可访问。另外,由于每次RUN指令都会创建新的层,所以只有同一个RUN指令中才能访问挂载的目录。此外,仅支持挂载上下文或者引用的镜像中存在的目录,不能挂载宿主机上的目录或者上下文以及镜像中不存在的目录。
(2) cache:这种挂载类型允许挂载缓存目录,从而加速构建过程。它可以用于访问编译器、包管理器或其他构建工具的缓存目录,从而避免重复下载或编译相同的依赖项。
(3) tmpfs:这是Docker 18.09版本引入的一种新方式。它用于挂载一个临时文件系统(tmpfs)到容器中的某个目录,并在容器内执行指定的命令。使用这种方式,可以在运行容器时动态创建一个临时的文件系统,从而提高容器的性能和安全性,因为临时文件系统中的数据将不会被持久化。
除了上述三种类型外,RUN --mount可能还支持其他类型的挂载,具体取决于Docker的版本和配置,如secret、ssh等。

–network选项

RUN指令使用–network选项来调整命令执行时的网络环境类型。指令格式如下:

RUN --network=<TYPE>

支持的类型有:

Type描述
default在默认的网络环境运行命令,默认类型
none在没有网络访问的环境运行命令
host在宿主机的网络环境运行命令

–security选项

RUN指令使用–security选项来调整容器的安全模式。默认的安全模式是sandbox。当安全模式调整成insecure,则可以构建阶段以不安全模式运行没有沙箱的命令,这相当于运行docker run --privileged。使用示例如下:

## syntax=docker/dockerfile:1-labs
FROM ubuntu
RUN --security=insecure echo "hello world"

COPY

COPY指令用来复制文件或目录,并将其添加到容器的文件系统中。指令有两种格式:

COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]

其中使用双引号的方式,主要应用于路径中存在空格的情况,推荐使用带双引号的方式。
src指定的源路径可以有多个,且路径支持正则表达式的写法。src指定的源路径是相对于构建上下文所在的路径,而不是相对宿主机。
所谓Docker构建上下文,是指在进行Docker镜像构建时,传递给Docker构建命令(如docker build)的一组文件和目录。这些文件和目录包含了构建镜像所需的所有资源,如源代码、依赖项、配置文件等。构建上下文是Docker构建过程的基础,它定义了镜像的内容和结构。构建上下文可以是本地文件系统中的一个目录,也可以是一个远程的Git仓库或其他类型的资源。**当使用本地目录作为构建上下文时,通常需要将Dockerfile放在该目录的根目录下,并使用docker build命令指定该目录的路径。**Docker会递归地将该目录及其子目录中的所有文件打包到构建上下文中。注意,当使用标准输入(STDIN)构建镜像时(docker build - < somefile)时,构建上下文将不存在,这时COPY指令将失效。
dest只能有一个,要么是一个绝对路径,要么是一个基于WORKDIR的相对目录。
在使用COPY指令时,要遵循以下规范:
(1) src指定的路径必须在构建上下文中。对于需要访问构建上下文之外的路径将无法执行。如COPY …/path/file因为需要访问构建上下文之外的目录,所以在执行是会报错。
(2) 当src指定的是目录时,该目录下的所有内容都会拷贝到容器中,包括文件系统的元数据信息。注意,目录本身不会被拷贝。
(3) 如果dest指定的路径在容器中不存在,则会默认逐层创建。
更多COPY指令介绍可以参考官网COPY一文。接下来重点介绍COPY指令支持的选项:

–chown --chmod

COPY指令使用–chown和–chmod选项来调整用户/用户组,以及访问控制。注意,–chown和–chmod选项只支持Linux系统,对于Windows系统则不适用。使用格式如下:

COPY [--chown=<user>:<group>] [--chmod=<perms> ...] <src> ... <dest>

从构建上下文复制的文件或目录默认其UID和GID都是0。也就是说,一但使用USER去设置用户和用户组信息,则在使用COPY指令时,必须设置复制的文件或目录的UID和GID。此外,如果仅设置UID,而未设置GID,则GID和UID保持一致。使用示例如下:

COPY --chown=1000 --chmod=644 files* /somedir/
COPY --chown=1000:1000 --chmod=644 files* /somedir/

–link选项

COPY指令使用–link选项来创建新的镜像层,以便文件保持独立于其前身存在的层。使用–link选项后,Docker会创建一个新的层来保存COPY指令的结果,这个层将独立于之前的层。这有助于减少不必要的层,并提高构建效率,特别是在多阶段构建或频繁更改构建上下文的情况下。–link选项是BuildKit的一个新功能,可能在不同版本的Docker中有所不同,在使用前需先确认该功能是否可以可用。使用格式如下:

COPY [--link[=<boolean>]] <src> ... <dest>

ADD

ADD指令用来复制文件或目录或远程文件,并将其添加到容器的文件系统中。可以看到ADD指令和COPY指令功能类似,都是用来将文件复制到容器并添加到其文件系统。COPY指令和ADD指令的主要区别在于ADD指令支持自动解压缩和从URL复制文件,而COPY指令则仅支持本地文件的简单复制。根据实际需求,可以选择使用这两个指令中的任何一个。但为了避免不必要的解压缩和复杂性,通常建议优先使用COPY指令。
ADD指令有两种格式:

ADD [OPTIONS] <src> ... <dest>
ADD [OPTIONS] ["<src>", ... "<dest>"]

其中使用双引号的方式,主要应用于路径中存在空格的情况,推荐使用带双引号的方式,这和CMD指令一致。
与CMD指令一致,src指定的源路径可以有多个,且路径支持正则表达式的写法。src指定的源路径是相对于构建上下文所在的路径,而不是相对宿主机。
与CMD指令一致,dest只能有一个,要么是一个绝对路径,要么是一个基于WORKDIR的相对目录。
在使用ADD指令时,要遵循以下规范:
(1) src指定的路径必须在构建上下文中。对于需要访问构建上下文之外的路径将无法执行。如COPY …/path/file因为需要访问构建上下文之外的目录,所以在执行是会报错。
(2) 当src是一个URL,且dest是一个路径,从URL获取的内容将放置到dest的路径下,且访问权限为600。
(3) 当src指定的是目录时,该目录下的所有内容都会拷贝到容器中,包括文件系统的元数据信息。注意,目录本身不会被拷贝。
(4) 当src指定的是一个本地压缩包(格式是gzip、bzip2等),复制到容器后,会将其解压成目录。
(5) 如果dest指定的路径在容器中不存在,则会默认逐层创建。
更多ADD指令介绍可以参考官网ADD一文。接下来重点介绍ADD指令支持的OPTIONS。

–keep-git-dir选项

ADD指令使用–keep-git-dir选项保留.git目录。当基于HTTP或SSH协议从远程Git仓库获取文件或目录时,默认会排除.git目录。如果需要保留.git目录,则可以使用–keep-git-dir选项。示例如下:

ADD --keep-git-dir=true https://github.com/moby/buildkit.git#v0.10.1 /

–checksum选项

ADD指令使用–checksum选项来校验远程资源的checksum,目前只支持HTTP资源。示例如下:

ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz /

其他选项

对于–chown --chmod、–link等选项,其用法与CMD指令一致,有需要的同学可以参考下CMD指令。

USER

USER指令用来指定容器运行时的用户名(或UID)和可选的组名称(或GID)。USER指令会影响后续所有的RUN、CMD和ENTRYPOINT等指令的执行用户。因此,确保所选的UID和GID具有执行这些指令所需的适当权限是很重要的。
Linux使用用户和用户组进行权限分配。对业务应用来说,在设计时要考虑到是否以root用户运行,如果不是,则要考虑设置用户名。如果不指定用户名信息,则默认会使用root用户。因为root权限太高,对业务应用来说,尽量设置一个自己的用户。指令有两种格式:

USER <user>[:<group>]
USER <UID>[:<GID>]

user和group,UID和GID都是成对出现的。如果在设置user时,group缺省,则默认的group是通常是user,除非这个user已经存在,且已分配了一个group。同样的,如果使用USER指令仅设置UID,那么Docker也会为该UID分配一个默认的GID。这个默认的GID通常是与UID相同的值,除非该UID已经存在于/etc/passwd文件中并且有一个与之关联的GID。
设置user和group前,该user必须已经定义。增加user和group的命令如下:

$ useradd -u 1001 myuser,这里-u用来指定uid
$ groupadd -g 1001 mygroup,这里-g用来指定gid

推荐使用UID和GID,理由有两点:(1) 在Linux等操作系统内部识别的还是UID和GID,而不是GID;(2)如果使用user和group,还需保证这个user和group已经存在,而使用UID和GID,如果不存在,会创建一个新的用户。
在设置UID时,要考虑到UID的值大小问题。通常0用来代表系统管理员或root用户,而1-999一般会保留给系统使用。所以推荐业务应用使用1000及以后的值。注意,不同操作系统对值大小的划分可能不同,这里主要考虑Linux系统。
为了确保一致性和可预测性,最好在创建用户时同时指定UID和GID,这样可以避免任何潜在的混淆或冲突。如果确实只想设置UID并接受默认的GID,那么需要确保这符合当前业务的需求。使用示例如下:

USER 1000:1000

更多USER介绍可以参考官网USER一文。

VOLUME

VOLUME指令用来创建一个数据卷挂载点。VOLUME指令可以帮助将宿主机目录或者其他容器目录挂载到这个容器。VOLUME指令主要用在需要数据持久化场景。因为容器自身不能持久化运行时数据,容器重启后,之前容器运行时产生的数据将丢失。指令格式为:

VOLUME ["/data"]

注意,VOLUME指令只是声明了容器中需要挂载到宿主机或其它容器的目录,但是不能保证这个目录与宿主机或其他容器的目录的映射,也不能保证宿主机或其他容器的目录一定存在。正常的使用流程是:在Dockerfile中使用VOLUME指令声明容器需要与外部建立联系的目录,然后在容器启动时(也即执行docker run),指定映射关系(也即在docker run命令中增加-v参数)。将容器的/data目录映射到宿主机的/path/on/host目录的示例如下:

$ docker run -v /path/on/host:/data image-id-or-name

如果执行docker run命令未增加-v参数,则容器内的文件系统和宿主机目录将完成隔离。这意味着容器内部对文件的任何修改(创建、删除、更新)都不会反映到宿主机上,反之亦然。
更多VOLUME指令介绍可以参考官网VOLUME一文。

WORKDIR

WORKDIR指令用来设置工作目录。WORKDIR指令会影响后续所有的RUN、CMD、ENTRYPOINT、COPY、ADD等指令的工作目录。如果不指定WORKDIR,那么默认的工作目录是/,也即根目录。指令格式为:

WORKDIR /path/to/workdir

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的的路径,后续指令如果是参数是绝对路径,则会更新工作目录。例如:

WORKDIR /a  
WORKDIR b  
WORKDIR c  
RUN pwd
WORKDIR /e
RUN pwd

则第一个RUN pwd指令的工作目录为/a/b/c,第二个RUN pwd指令的工作目录为/e。为了避免出错,推荐WORKDIR指令中只使用绝对路径。
一般情况下,业务镜像都是基于基础镜像或父镜像构建,如果不设置自己的工作目录,则会集成基础镜像或父镜像的目录。为避免对基础镜像或父镜像产生影响,推荐业务应用设置自己的工作目录。
更多WORKDIR介绍可以参考官网WORKDIR一文。

ONBUILD

ONBUILD指令是Docker中的一个特殊指令,它用于向镜像中添加触发器。这些触发器将在以当前镜像作为基础镜像去构建下一级镜像时执行。换句话说,当某个镜像被用作另一个镜像的构建基础时,ONBUILD指令中指定的指令将在构建过程中被执行。指令格式如下:

ONBUILD <INSTRUCTION>

ONBUILD指令后面可以跟随其他Docker指令,如RUN、COPY等。这些指令在当前镜像构建时并不会被执行,而是在基于当前镜像构建新的镜像时才会被执行。这种机制使得ONBUILD指令非常适用于创建有继承关系的Dockerfile文件,即父镜像在被子镜像继承后,父镜像的ONBUILD指令会被触发。
ONBUILD指令的使用可以减少Dockerfile文件的重复内容编写,因为它允许你在基础镜像中定义一些通用的构建步骤,然后在继承该基础镜像的子镜像中自动执行这些步骤。但需要注意的是,ONBUILD指令只能在构建子镜像时执行,对孙子镜像的构建是无效的。此外,ONBUILD指令不能使FROM或MAINTAINER指令触发,且不允许使用ONBUILD ONBUILD来链接ONBUILD指令。示例如下:

ONBUILD COPY [".", "/var/testapp"]  
ONBUILD RUN go build /var/testapp  

跟随在ONBUILD后的指令不会在包含它们的Dockerfile被构建时被执行,这些指令会被记录在生成镜像的元数据ContainerConfig.OnBuild下。这个元数据会一直被保留,直到生成的镜像被另外的Dockerfile作为基础镜像,当一个下游的Dockerfile通过FROM指令使用上游的镜像(带有ONBUILD指令的Dockerfile产生的镜像),那么这些在ONBUILD后跟随的指令将会在FROM指令后,下一条指令前被执行。
更多ONBUILD介绍可以参考官网ONBUILD一文。

STOPSIGNAL

STOPSIGNAL指令用来设置容器退出时需要发送的系统调用信号。这个信号可以是一个有效的无符号数字,与内核系统调用表中的位置相匹配,如9,或者是SIG格式的信号量,如SIGKILL。如果未定义,则默认值为 SIGTERM。指令格式如下:

STOPSIGNAL signal

可以在在 docker run 和 docker create 上使用–stop-signal参数指定STOPSIGNAL,来覆盖DockerFile中定义的STOPSIGNAL。
更多STOPSIGNAL指令介绍可以参考官网STOPSIGNAL一文。

HEALTHCHECK

HEALTHCHECK指令用来对容器进行健康检查,确认容器是否正常。指令有两种格式:

HEALTHCHECK [OPTIONS] CMD command, 根据在容器中执行命令的返回值是否为 0 来判断容器是否健康,如果是0,表示健康,否则不健康  
HEALTHCHECK NONE, 禁止基础镜像中的健康检查  

启用健康检查后,容器会额外新增一个健康状态(health status)。当容器启动后,健康状态是starting;当健康检查通过后,健康状态是healthy;当健康检查失败后,健康状态是unhealthy。
HEALTHCHECK指令的OPTION支持如下参数:
-interval=DURAT工ON (default: 30s):过多久检查一次;
-timeout=DURATION (default: 30s):每次检查等待结果的超时;
–start-period=DURATION(default: 0s):初次检查开始时间,如果容器启动较慢,可以设置该参数,延后健康探测时间
-retries=N (default: 3):如果失败了,重试几次才最终确定失败
每个Dockerfile中,只能有一条HEALTHCHECK指令。如果出现了多个HEALTHCHECK指令,不会报错,但只有最后一条会生效。
更多HEALTHCHECK指令介绍可以参考官网HEALTHCHECK一文。

SHELL

SHELL指令用来设置镜像使用的默认shell。指令格式为:

SHELL ["executable" , "parameters"] 

Linux的默认shell是[“/bin/sh”, “-c”],Windows的默认shell是[“cmd”, “/S”, “/C”]。SHELL指令可以出现多次。每条SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令。使用示例如下:

FROM microsoft/windowsservercore## Executed as cmd /S /C echo default
RUN echo default## Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default## Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello## Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello

shell的调整会影响到以下三个指令:RUN、CMD 和 ENTRYPOINT。当调整shell时,要充分考虑对以上三个指令的影响。
更多SHELL介绍可以参考官网SHELL一文。

参考

https://yiyan.baidu.com/ 文心一言
https://docs.docker.com/reference/dockerfile/ Dockerfile reference
https://www.runoob.com/docker/docker-dockerfile.html Docker Dockerfile
https://www.cnblogs.com/dance-walter/p/9581508.html Dockerfile语法简介
https://zhuanlan.zhihu.com/p/419175543 Docker Dockerfile指令大全
https://blog.csdn.net/qq_62344659/article/details/131844959 Docker镜像的创建
http://www.dockerinfo.net/3328.html 精简 Docker 镜像
https://www.cnblogs.com/tkuang/p/17219527.html 在 Dockerfile 中以 scratch 为基础镜像 (FROM scratch)
https://blog.csdn.net/jthivan/article/details/50530955 UID详解
https://cn.linux-console.net/?p=20084 Linux 中的 UID 是什么?
https://blog.csdn.net/ximenjianxue/article/details/103127383 Linux用户不同UID分类区别
https://c.biancheng.net/view/3042.html Linux UID和GID(用户ID和组ID)
https://blog.csdn.net/WJSZMD/article/details/89331751 SIGINT,SIGKILL,SIGTERM信号区别
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ Dockerfile Best Practices guide

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/735476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Angular基础---HelloWorld---Day3

文章目录 0.ng-model 的几种不同的class属性1.ng-model 的引用与属性的调用2.表单验证&#xff1a; (模版引用变量、ngModel 、ngif一起使用&#xff09;3.根据class属性的值ng-invalid &#xff0c;设置动态变化的样式 0.ng-model 的几种不同的class属性 引用ng-model 元素的c…

数据体系规范化

基础是标准化、规范化 建立数据仓库,面向主题的、集成的、相对稳定的、反映历史变化的数据集合,以支持管理决策decision making 大数据:大量volumn、多样variety、快速velocity、价值密度低value、准确性veracity、可视化visualization、合法性validity 多源数据、多样数…

分布式执行引擎ray入门--(3)Ray Train

Ray Train中包含4个部分 Training function: 包含训练模型逻辑的函数 Worker: 用来跑训练的 Scaling configuration: 配置 Trainer: 协调以上三个部分 Ray TrainPyTorch 这一块比较建议直接去官网看diff&#xff0c;官网色块标注的比较清晰&#xff0c;非常直观。 impor…

MySQL-视图:视图概述、使用视图注意点、视图是否影响基本表

视图 一、视图概述二、使用视图注意点三、视图操作是否影响基本表 一、视图概述 在数据库管理系统中&#xff0c;视图&#xff08;View&#xff09;是一种虚拟表&#xff0c;它并不实际存储数据&#xff0c;而是基于一个或多个实际表的查询结果。视图提供了一种对数据库中数据…

题目 2132: T1268-完全背包问题

题目描述: 设有n种物品&#xff0c;每种物品有一个重量及一个价值。但每种物品的数量是无限的&#xff0c;同时有一个背包&#xff0c;最大载重量为M&#xff0c;今从n种物品中选取若干件(同一种物品可以多次选取)&#xff0c;使其重量的和小于等于M&#xff0c;而价值的和为最…

RabbitMQ备份交换机

1. 备份交换机 备份交换机可以理解为 RabbitMQ 中交换机的“备胎”&#xff0c;当我们为某一个交换机声明一个对应的备份交换机时&#xff0c;就是为它创建一个备胎&#xff0c;当交换机接收到一条不可路由消息时&#xff0c;将会把这条消息转发到备份交换机中&#xff0c;由备…

reids设计与实现(一)——数据对象

文章目录 1. 前言2. redis 动态字符串2.1. 字符串的数据结构&#xff1a;2.2. 剖析&#xff0c;length&#xff1b;2.3. 剖析&#xff0c;free&#xff1b;2.3. 使用c字符串函数&#xff1b; 3. redis 链表4. 字典5. 跳跃表 1. 前言 reids作为最常用的缓存数据库&#xff0c;深…

web3 DePIN赛道之OORT

文章目录 什么是DePIN什么是oort背景&#xff1a;去中心化云计算场景团队OORT AIOORT StorageOORT Compute 参考 什么是DePIN DePIN是Decentralized Physical Infrastructure Networks的简称,中文意思就是去中心化的网络硬件基础设施,是利用区块链技术和代币奖励来调动分散在世…

mysql笔记:2. 表操作

文章目录 创建表创建表主键约束外键约束非空约束唯一约束默认值约束 查看数据表结构查看表详细结构 修改数据表修改表名修改字段名修改字段数据类型添加字段删除字段更改表的存储引擎 删除数据表删除没被关联的表删除被关联的表 数据表是数据库中最重要、最基本的操作对象&…

单例九品--第九品[可用的设计]

单例九品--第九品[可用的设计] 上一品引入写在前边代码部分实现方式的评注和思考写在最后 上一品引入 自第五品以来&#xff0c;为解决第四品的静态初始化灾难问题&#xff0c;将全局对象设置为指针类型&#xff0c;但是指针是有被修改的风险。所以第八品将全局单例对象封装在…

2024.02.07 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 腾讯TEG 2024 校招开放全新机会&#xff0c;持续热招&#xff08;内推&#xff09; 校招 | 腾讯TEG 2024 校招开放全新机会&#xff0c;持续热招&#xff08;内推&#xff09; …

【MATLAB】MATLAB学习笔记

MATLAB入门 基础操作变量命名数据类型逻辑和流程控制循环结构分支结构 绘图基本操作二维平面绘图绘图参数三位立体绘图图像窗口的分割 本文参考B站视频&#xff1a;BV13D4y1Q7RS 由于我对于C语言很熟悉&#xff0c;很多语法是会参考C来学 基础操作 清屏%% 清空环境变量及命令 …

图腾柱PFC工作原理:一张图

视屏链接&#xff1a; PFC工作原理

Java SE入门及基础(33)

final 修饰符 1. 应用范围 final 修饰符应该使用在类、变量以及方法上 2. final 修饰类 Note that you can also declare an entire class final. A class that is declared final cannot be subclassed. This is particularly useful, for example, when creating an imm…

docker学习笔记——Dockerfile

Dockerfile是一个镜像描述文件&#xff0c;通过Dockerfile文件可以构建一个属于自己的镜像。 如何通过Dockerfile构建自己的镜像&#xff1a; 在指定位置创建一个Dockerfile文件&#xff0c;在文件中编写Dockerfile相关语法。 构建镜像&#xff0c;docker build -t aa:1.0 .(指…

Effective C++ 学习笔记 条款22 将成员变量声明为private

下面是作者的规划。首先带你看看为什么成员变量不该是public&#xff0c;然后让你看看所有反对public成员变量的论点同样适用于protected成员变量。最后导出一个结论&#xff1a;成员变量应该是private。获得这个结论后&#xff0c;本条款也就大功告成了。 好&#xff0c;现在…

【Vue】生命周期

Vue生命周期 就是一个Vue实例从创建 到 销毁 的整个过程 生命周期四个阶段 1.创建阶段&#xff1a;创建响应式数据 2.挂载阶段&#xff1a;渲染模板 3.更新阶段&#xff1a;修改数据&#xff0c;更新视图 4.销毁阶段&#xff1a;销毁Vue实例 生命周期钩子 Vue生命周期过…

【每日一题】2834. 找出美丽数组的最小和-2024.3.8

题目&#xff1a; 2834. 找出美丽数组的最小和 给你两个正整数&#xff1a;n 和 target 。 如果数组 nums 满足下述条件&#xff0c;则称其为 美丽数组 。 nums.length n.nums 由两两互不相同的正整数组成。在范围 [0, n-1] 内&#xff0c;不存在 两个 不同 下标 i 和 j &…

阿里云实现两个VPC网络资源互通

背景 由于实际项目预算有限&#xff0c;两套环境虽然分别属于不同的专有网络即不同的VPC&#xff0c;但是希望借助一台运维机器实现对两个环境的监控和日常的运维操作 网络架构 如下是需要实现的外网架构图&#xff0c;其中希望实现UAT环境的一台windows的堡垒机可以访问生产…

前端软件工程师100问?

作为一个前端软件工程师&#xff0c;可能会遇到的问题非常多&#xff0c;以下是我为您精选的100个常见问题&#xff1a; 以上100个问题涵盖了前端开发的基础知识、框架应用、性能优化、安全性、兼容性、前沿技术等多个维度。作为前端软件工程师&#xff0c;了解这些问题有助于提…