当前位置: 首页 > news >正文

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

相关文章:

Dockerfile指令大全

Dockerfile文件由一系列指令和参数组成。指令的一般格式为INSTRUCTION arguments。具体来说&#xff0c;包括"配置指令"(配置镜像信息)和"操作指令"(具体执行操作)。每条指令&#xff0c;如FROM&#xff0c;都是大小写不敏感的。但是为了区分指令和参数&am…...

第八个实验:(A+B)-C的结果判断奇偶特性

实验内容:(A+B)-C的结果判断奇偶特性,最后显示结果 实验步骤: 第一步:建立项目 第二步:实验步骤,编写程序 第三步:实验结果...

设计模式:观察者模式 ⑧

一、思想 观察者模式是一种常见的设计模式&#xff0c;也称作发布-订阅模式。它主要解决了对象之间的通知依赖关系问题。在这种模式中&#xff0c;一个对象&#xff08;称作Subject&#xff09;维护着一个对象列表&#xff0c;这些对象&#xff08;称作Observers&#xff09;都…...

【重温设计模式】迭代器模式及其Java示例

迭代器模式的介绍 在编程领域&#xff0c;迭代器模式是一种常见的设计模式&#xff0c;它提供了一种方法&#xff0c;使得我们可以顺序访问一个集合对象中的各个元素&#xff0c;而又无需暴露该对象的内部表示。你可以把它想象成一本书&#xff0c;你不需要知道这本书是怎么印…...

(001)UV 的使用以及导出

文章目录 UV窗口导出模型的主要事项导出时材质的兼容问题unity贴图导出导出FBX附录 UV窗口 1.uv主要的工作区域&#xff1a; 2.在做 uv 和贴图之前&#xff0c;最好先应用下物体的缩放、旋转。 导出模型的主要事项 1.将原点设置到物体模型的底部&#xff1a; 2.应用修改器的…...

一文理解CAS和自旋的区别(荣耀典藏版)

目录 一、自旋 二、CAS 三、什么是 ABA 问题 大家好&#xff0c;我是月夜枫&#xff0c;通常在面试的时候&#xff0c;或者在学习的时候&#xff0c;经常性的会遇到一些关于锁的问题&#xff0c;尤其是面试官会提出提问&#xff0c;你对锁了解的多么&#xff1f;你知道锁的原…...

【吊打面试官系列】Java虚拟机JVM篇 - 关于内存溢出

大家好&#xff0c;我是锋哥。今天分享关于内存溢出的JVM面试题&#xff0c;希望对大家有帮助&#xff1b; 什么是内存溢出&#xff1f; 内存溢出&#xff08;OOM&#xff09;是指可用内存不足。程序运行需要使用的内存超出最大可用值&#xff0c;如果不进行处理就会影响到其他…...

思科网络中如何配置标准ACL协议

一、什么是标准ACL协议&#xff1f;有什么作用及配置方法&#xff1f; &#xff08;1&#xff09;标准ACL&#xff08;Access Control List&#xff09;协议是一种用于控制网络设备上数据流进出的协议。标准ACL基于源IP地址来过滤数据流&#xff0c;可以允许或拒绝特定IP地址范…...

蓝桥杯刷题(二)

参考大佬代码&#xff1a;&#xff08;区间合并二分&#xff09; import os import sysn, L map(int, input().split()) # 输入n,len arr [list(map(int, input().split())) for _ in range(n)] # 输入Li,Si def check(Ti, arr, L)->bool:sec [] # 存入已打开的阀门在…...

【Python】牛客网—软件开发-Python专项练习(day1)

1.&#xff08;单选&#xff09;下面哪个是Python中不可变的数据结构&#xff1f; A.set B.list C.tuple D.dict 可变数据类型&#xff1a;列表list[ ]、字典dict{ }、集合set{ }(能查询&#xff0c;也可更改)数据发生改变&#xff0c;但内存地址不变 不…...

P3405 [USACO16DEC] Cities and States S题解

题目 Farmer John有若干头奶牛。为了训练奶牛们的智力&#xff0c;Farmer John在谷仓的墙上放了一张美国地图。地图上表明了每个城市及其所在州的代码&#xff08;前两位大写字母&#xff09;。 由于奶牛在谷仓里花了很多时间看这张地图&#xff0c;他们开始注意到一些奇怪的…...

JavaScript原型和原型链

JavaScript每个对象拥有一个原型对象 需要注意的是&#xff0c;只有函数对象才有 prototype 属性 当试图访问一个对象的属性时&#xff0c;它不仅仅在该对象上搜寻&#xff0c;还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&#xff…...

PyTorch之完整的神经网络模型训练

简单的示例&#xff1a; 在PyTorch中&#xff0c;可以使用nn.Module类来定义神经网络模型。以下是一个示例的神经网络模型定义的代码&#xff1a; import torch import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()# 定义神经…...

基于神经网络的偏微分方程求解器再度取得突破,北大字节的研究成果入选Nature子刊

目录 一.引言:神经网络与偏微分方程 二.如何基于神经网络求解偏微分方程 1.简要概述 2.基于神经网络求解偏微分方程的三大方向 2.1数据驱动 基于CNN 基于其他网络 2.2物理约束 PINN 基于 PINN 可测量标签数据 2.3物理驱动(纯物理约束) 全连接神经网路(FC-NN) CN…...

Linux的基本权限

一、对shell的浅显认识 shell是操作系统下的一个外壳程序&#xff0c;无论是Linux操作系统&#xff0c;还是Windows操作系统&#xff0c;用户都不会直接对操作系统本身直接进行操作&#xff0c;需要通过一个外壳程序去间接的进行各种操作 在Linux的shell外壳就是命令行&#…...

指纹加密U盘/指纹KEY方案——采用金融级安全芯片 ACH512

方案概述 指纹加密U盘解决方案可实现指纹算法处理、数据安全加密、数据高速存取&#xff08;EMMC/TF卡/NandFlash&#xff09;&#xff0c;可有效保护用户数据安全。 方案特点 • 采用金融级安全芯片 ACH512 • 存储介质&#xff1a;EMMC、TF卡、NandFlash • 支持全系列国密…...

Cloud-Sleuth分布式链路追踪(服务跟踪)

简介 在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,每一个前端请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败 GitHub - spring-cloud/spring-cloud-sl…...

flink重温笔记(十四): flink 高级特性和新特性(3)——数据类型及 Avro 序列化

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第 14 天啦&#xff01;学习了 flink 高级特性和新特性之数据类型及 avro 序列化&#xff0c;主要是解决大数据领域数据规范化写入和规范化读取的问题&#xff0c;avro 数据结构可以节约存储空间&#xff0c;本文中结合企业真…...

python75-Python的函数参数,关键字(keyword)参数

在定义Python函数时可定义形参(形式参数的意思)这些形参的值要等到调用时才能确定下来&#xff0c;由函数的调用者负责为形参传入参数值。简单来说&#xff0c;就是谁调用函数&#xff0c;谁负责传入参数值。 关键字(keyword)参数 Python函数的参数名不是无意义的&#xff0c…...

Java宝典-抽象类和接口

目录 1. 抽象类1.1 抽象类的概念1.2 抽象类的语法1.3 抽象类的特点 2. 接口2.1 接口的概念2.2 接口的语法2.3 接口的特点2.4 实现多个接口2.5 接口的继承 3. 接口使用案例 铁汁们好,今天我们学习抽象类和接口~ 1. 抽象类 1.1 抽象类的概念 什么是抽象类?在面向对象中,如果一…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...