Dockerfile详解

概述

Dockerfile 是 Docker 中用于构建镜像的文本文件。它包含了一系列的指令和参数,用于定义镜像的基础操作、环境设置和应用程序配置等。通过 Dockerfile,可以自动化地构建、配置和部署 Docker 容器镜像,使得应用程序的部署过程更加可持续、可重复和自动化。

文件一般由四部分组成:

  • 基础镜像
  • 维护者信息
  • 镜像操作指令
  • 容器启动执行指令

文件说明

Docker 以从上到下的顺序运行 Dockerfile 指令,以 # 字符开头则被视为注释,可以在文件中使用 RUNCMDFROMEXPOSEENV 等指令。 以 SpringBoot 应用构建为例,一个基本的 Dockerfile 文件内容声明如下:

# Dockerfile with SpringBoot Application
FROM java:8
ARG JAR_FILE
ADD target/${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

指令详解

如下整理 Dockerfile 指令,点击左侧链接可快速跳转至详细说明,更多用法请参考:

指令 说明
FROM 指定基础镜像,用于后续的指令构建
LABEL 添加镜像的元数据,使用键值对的形式
MAINTAINER已弃用 维护者信息
RUN 在构建过程中在镜像中执行命令
CMD 指定容器创建时的默认命令
ENTRYPOINT 设置容器创建时的主要命令
EXPOSE 声明容器运行时监听的特定网络端口
ENV 在容器内部设置环境变量
ADD 将文件、目录或远程URL复制到镜像中
COPY 将文件或目录复制到镜像中
VOLUME 为容器创建挂载点或声明卷
WORKDIR 设置后续指令的工作目录
USER 指定后续指令的用户上下文
ARG 定义在构建过程中传递给构建器的变量,可使用 docker build 命令设置
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器
STOPSIGNAL 设置发送给容器以退出的系统调用信号
HEALTHCHECK 定义周期性检查容器健康状态的命令
SHELL 覆盖 Docker 中默认的 shell,用于 RUNCMDENTRYPOINT 指令

FROM 指令

FROM 指令用于指定基础镜像,用于后续的指令构建,所以尽可能使用官方镜像,来作为容器的基础环境,有效的 Dockerfile 必须以 FROM 指令开头(用于 FROMARG 除外)。

  • AS name (可选)可以通过添加到指令来为新的构建阶段指定名称,可以用于后续的 FROM 或者 `COPY --from``
  • tagdigest,如果省略,默认采用 latest 标签,如果构建找不到该 tag 值,则会返回错误。

用法:

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

基础示例:

镜像版本查找可通过:https://hub.docker.com/search

# 使用 centos 默认(latest)版本作为基础镜像
FROM centos
# 使用 centos 指定版本(7.9.2009)作为基础镜像
FROM centos:7.9.2009

指定镜像平台示例:

如果引用的是一个多平台镜像,需要交叉编译构建,可以通过 --platform 指定镜像平台,如:linux/amd64linux/arm64windows/amd64,如下:

# 使用 centos  默认(latest)版本作为基础镜像,并指定引用镜像平台为 linux/amd64
FROM --platform=linux/amd64 centos

多构建阶段示例:

可以在 Dockerfile 文件中使用多次 FROM ,以创建多个镜像或使用一个构建阶段作为另一个构建阶段的依赖项,每个 FROM 之前都会清除由先前指令创建的任何状态:

# 第一阶段构建,基于 Node 环境安装依赖打包应用
FROM node AS node1
LABEL maintainer="do@dodoo.co"
COPY ../../../env/linux/docker /app/
WORKDIR /app
RUN npm install
RUN npm build

# 第二阶段,基于 nginx 环境,将打包后静态资源 COPY 至 nginx 默认目录
FROM nginx
COPY --from=node1 /app/dist /usr/share/nginx/html

ARG 和 FROM 如何交互

FROM 指令支持调用由出现在第一个 FROM 之前的任何 ARG 指令声明的变量。

# 示例:使用 ARG 将变量指定基础镜像版本
ARG VERSION=latest
FROM nginx:${VERSION}
CMD /code/run-nginx

# 在 FROM 之前声明的 ARG 变量,不能在 FROM 之后的任何指令中使用
FROM php:${VERSION}
CMD /code/run-php

若要使用在第一个 FROM 之前声明的 ARG 默认值,需要在构建阶段内声明一次没有默认值的 ARG 指令,如下:

ARG VERSION=latest
FROM nginx:${VERSION}

# 再次声明没有默认值的 ARG 指令
ARG VERSION
RUN echo $VERSION

RUN 指令

建议: RUN 指令在构建时将会生成一个新的镜像层,并执行 RUN 指令后的内容,为避免创建多个镜像层,建议将多条 RUN 指令进行合并。

用法:

# shell 模式
RUN <command>
# exec 模式
RUN ["executable","param1","param2"]

shell 模式示例:

命令在 shell 中执行:

  • Linux 下默认使用:/bin/sh -c
  • Windows 下默认使用:cmd /S /C

可以将多个命令使用(&&)拼接,放在同一个 RUN 指令中,也可以使用反斜杠( \ )将复杂 RUN 命令换行,如下:

# 加 && 拼接多个命令,加 \ 将长命令进行换行
RUN /'source $HOME/.bashrc && \
echo $HOME'

# 替换为其他 shell ,可显示声明 shell ,以 /bin/bash 为例:
RUN /bin/bash -c echo hello

exec 模式示例:

exec 模式可以避免 shell 字符串修改,参数会被解析为 JSON 数组,因此参数必须使用双引号( "" )包裹,exec 不调用命令 shell,所以不会发生正常的 shell 处理,如下:

# 不会对变量进行替换
RUN ["echo", "$HOME"]

# 想要 shell 处理,则可以使用 shell 形式或直接执行 shell
RUN ["/bin/sh", "-c", "echo $HOME"]

如使用除 /bin/sh 之外的其他 shell,可做如下替换:

# 替换 /bin/sh 为 /bin/bash
RUN ["/bin/bash","-c","echo hello"]

RUN --mount 指令

允许创建可以访问的文件系统挂载,可以用于:

  • 创建主机文件系统或其他构建阶段的绑定挂载
  • 访问构建机密或 ssh-agent 套接字
  • 使用持久的包管理缓存来加快构建速度

用法:

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

支持类型:

更多细节及用法,请参考官方文档:RUN --mount

type 描述
bind 默认 绑定挂载上下文目录(只读)。
cache 挂载临时目录以及缓存编译器和包管理器的目录。
tmpfs 允许在构建容器中装载 tmpfs
secret 允许构建容器访问安全文件(如私钥),而无需将其放入到镜像中。
ssh 允许构建容器通过 SSH 代理访问 SSH 密钥,并支持密码短语。

RUN --network 指令

允许控制命令运行的网络环境。

用法:

RUN --network=<TYPE>

支持类型:

更多细节及用法,请参考官方文档:RUN --network

type 描述
default 默认 在默认网络中运行。
none 在没有网络访问的情况下运行。
host 在主机的网络环境中运行。

RUN --security 指令

暂未在稳定的 docker 版本中使用

--security=insecure

构建在不安全模式下运行没有沙箱的命令,即允许需要提升权限的流程,相当于执行
docker run --privileged

--security=sandbox

默认沙箱模式可以通过 --security=sandbox 激活,但这是无操作的。

CMD 指令

  • Dockerfile 只能有一个 CMD 指令生效,如果指定多个,则只有最后一个 CMD 生效。

  • CMD 主要目的是为执行容器提供默认值,可以包含可执行文件,也可以省略,省略时必须指定 ENTRYPOINT 值。

  • 如果使用 CMDENTRYPOINT 指令提供默认参数,则应使用 JSON 数组格式指定 CMDENTRYPOINT 指令。

用法:

# exec 模式(首选)
CMD ["executable","param1","param2"]
# 作为 ENTRYPOINT 的默认参数
CMD ["param1","param2"]
# shell 模式
CMD command param1 param2

示例:

# 使用 exec 模式
CMD ["/usr/bin/wc","--help"]

# 使用 shell 模式
CMD echo "this is a test." | wc -

LABEL 指令

将元数据添加到镜像中,镜像默认继承基础镜像的标签,如果标签已存在但具有不同的值,则最近应用的值将覆盖任何先前设置的值。

用法:

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

示例:

LABEL 值使用双引号("")包裹,一个镜像可以包含多个 LABEL,可以在一行指定多个 LABEL ,也可以通过反斜杠( \ )进行换行:

# 一行指定多个 LABEL
LABEL multi.label1="value1" multi.label2="value2" multi.label3="value3"
LABEL version="1.0.0"

# 使用 \ 进行换行
LABEL description="hello \
world! "

MAINTAINER 指令 已弃用

设置镜像的作者信息,已弃用。

MAINTAINER <name>

推荐使用 LABEL 指令,可以设置你需要的任何元数据。

LABEL org.opencontainers.image.authors="do@dodoo.co"

EXPOSE 指令

声明 Docker 容器在运行时监听指定的端口及协议,如果不指定协议,默认为 TCP。 提示 EXPOSE 指令实际上并未发布端口,仅指定容器提供服务需要用到的端口。

用法:

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

示例:

# 暴露 80 端口,udp 协议
EXPOSE 80/udp

# 如果同时暴露 tcp 和 udp 协议
EXPOSE 80/tcp
EXPOSE 80/udp

ENV 指令

设置环境变量,可用于后续所有指令中,与 LABEL 指令相同,允许设置多个变量。

子阶段会继承父阶段或任何祖先阶段的 ENV 设置的环境变量。

用法:

ENV <key>=<value> ...

示例:

# 设置单个变量
ENV CUSTOM_CODE=100

# 设置多个变量(引号:""、反斜杠:\、空格: 可用于变量值中)
ENV CUSTOM_KEY=key  CUSTOM_VALUE="value" CUSTOM_PREFIX=Hello\ World\ prefix

# 替代语法(后续版本可能会删除):可以省略等号,省略等号时,不允许一条指令中设置多个环境变量
ENV CUSTOM_KEY key

ADD 指令

从路径复制新文件、目录或远程文件URL <src> ,添加到镜像的文件系统中 <dest>

  • <src>:可以是 Dockerfile 所在目录的一个相对路径(文件或目录),也可以是一个 URL ,还可以是一个 tar 文件(自动解压为目录)
  • 可以指定多个 <src> 资源,如果是文件或目录,则路径被解析为相对于构建上下文的源
  • <dest>:可以是镜像内绝对路径,或者是工作目录( WORKDIR )的相对路径
  • 路径支持通配符,使用 Gofilepath.Match 来完成匹配规则
  • --chown:指定用户、组,仅适用于构建 Linux 容器的 Dockerfile 上,因为在 Windows 系统上没有用户、组的概念
  • --checksum:远程文件校验和,当前仅支持 http

ADD 和 COPY 的区别和使用场景

ADDCOPY 的区别和使用场景:

  • ADD 支持添加远程 URL 和自动提权压缩格式文件,COPY 只允许从本机中复制文件
  • COPY 支持从其他构建阶段中复制源文件(--from
  • 根据官方 Dockerfile 最佳实践,除非真的需要从远程 URL 添加文件或自动提取压缩文件采用 ADD,其他情况一律使用 COPY

注意:

  • ADD 从远程 URL 获取文件和复制的效果并不理想,因为该文件会增加 Docker Image 最终的大小
  • 应该使用 CURLWGET 来获取远程文件,然后在不需要时进行删除

用法:

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

# 包含空格的路径需要这种形式
ADD [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]

示例:

# 将以 home 开头的所有文件,添加到 customDir 路径下
ADD home* /customDir/

# 用 ? 替换单个字符,将以 home 开头的 txt 文件,添加到 customDir 路径下
ADD home?.txt /customDir/

# 使用相对路径,将 test.txt 添加到工作目录下的 relativeDir 下
ADD test.txt relativeDir/

# 使用绝对路径,将 test.txt 添加到目录 absoluteDir 下
ADD test.txt /absoluteDir/

# 添加包含特殊字符的文件或目录时,需要遵循 Golang 规则对路径进行转义,防止被解析为匹配模式
ADD arr[[]0].txt /customDir/

# 指定文件目录、组权限
ADD --chown=1 files* /customDir/
ADD --chown=bin files* /customDir/

ADD 遵循原则

<src> 路径必须在构建的上下文中

  • <src> 是一个 URL
    • <dest> 不以斜杠结尾,那么文件将从 URL 下载并复制到 <dest>
    • <dest> 以斜杠结尾,则从 URL 推断文件名并将文件下载到 <dest>/<filename>
    • URL 必须有一个重要的路径,以便在如上这种情况下可以找到文件名(http://example.com 将不起作用)
  • <src> 是目录
    • 则会复制目录的全部内容,包括文件系统元数据
    • 不会复制目录本身,只会复制其内容
  • <src> 是压缩格式的本地 tar 文件
    • 会将其自动解压为目录
    • 来自远程 URL 资源不会被解压缩
    • 当一个目录被复制或解压时,它的行为与 tar -x 相同
    • 文件是否被识别为可识别的压缩格式完全取决与文件的内容,而不是文件的名称
  • <src> 是任何其他类型的文件
    • 则将其与其元数据一起单独复制
    • <dest> 以斜杠 / 结尾,它将被视为一个目录,并且 <src> 的内容将写入 <dest>/base(<src>)
  • 指定了多个 <src> 资源,或使用了通配符,<dest> 必须是一个目录,并且必须以斜杠 / 结尾
  • <dest> 不以斜杠结尾,它将被视为常规文件,并将 <src> 内容写入 <dest>
  • <dest> 不存在,路径中所有缺失的目录都会自动创建
  • <src> 的内容发生变化,第一个遇到的 ADD 指令将使来自 Dockerfile 的所有后续指令的缓存无效,包括使 RUN 指令的缓存无效

COPY 指令

从容器的文件系统中复制新文件或目录将他们添加到路径中

用法:

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

# 包含空格的路径需要这种形式
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]

示例:

# 将以 home 开头的所有文件,复制到 customDir 路径下
COPY home* /customDir/

# 用 ? 替换单个字符,将以 home 开头的 txt 文件,复制到 customDir 路径下
COPY home?.txt /customDir/

# 使用相对路径,将 test.txt 复制到工作目录下的 relativeDir 下
COPY test.txt relativeDir/

# 使用绝对路径,将 test.txt 复制到目录 absoluteDir 下
COPY test.txt /absoluteDir/

# 复制包含特殊字符的文件或目录时,需要遵循 Golang 规则对路径进行转义,防止被解析为匹配模式
COPY arr[[]0].txt /customDir/

# 从指定构建阶段 base 寻找源文件 /tmp/example.txt 并复制到 /target/exmaple.txt
FROM ubuntu AS base
COPY --from=base /tmp/example.txt /target/example.txt

COPY 遵循规则

  • <src> 路径必须在构建的上下文中
  • <src> 是目录
    • 则复制目录的全部内容,包括文件系统元数据
    • 不会复制目录本身,只会复制其内容
  • <src> 是任何其他类型的文件
    • 则将其与元数据一起单独复制
    • <dest> 以斜杠 / 结尾,它将被视为一个目录,并且 <src> 的内容将写入 <dest>/base(<src>)
  • 指定了多个 <src> 资源,或者由于使用了通配符,则 <dest> 必须是一个目录,并且必须以斜杠 / 结尾
  • <dest> 不以斜杠结尾,将被视为常规文件,并且 <src> 的内容将写入 <dest>
  • <dest> 不存在,路径中所有缺失的目录都会自动创建
  • <src> 的内容发生变化,第一个遇到的 ADD 指令将使来自 Dockerfile 的所有后续指令的缓存无效,包括使 RUN 指令的缓存无效

ENTRYPOINT 指令

  • 指定镜像的默认入口命令,该入口命令会在容器启动时作为根命令执行,所有其他传入值作为该命令的参数
  • 可以通过 docker run -entrypoint 来覆盖
  • 只有 Dockerfile 中的最后一条 ENTRYPOINT 指令会起作用

用法: 当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令

提示 CMDENTRYPOINT 命令都定义了容器运行时的运行命令

  • Dockerfile 必须有一条 CMDENTRYPOINT 命令
  • 如果容器作为可执行程序运行,需要指定 ENTRYPOINT 命令
  • CMD 命令应该用作定义 ENTRYPOINT 命令的默认参数,或在容器启动中执行临时命令的方式
  • CMD 使用替代参数运行容器时将被覆盖

dockerfile

# exec 格式
ENTRYPOINT ["executable", "param1", "param2"]

# shell 格式
ENTRYPOINT command param1 param2

exec 格式示例:

# 替换 CMD 参数
ENTRYPOINT ["/bin/echo","Hello"]
CMD ["world"] # 表示默认参数,没提供参数,则使用此参数

docker run -it [image] # 输出 Hello world
docker run -it [image] "Docker" # 输出 Hello Docker, 不使用默认参数
docker run -it [image] "James" "Bond" # 输出 Hello James Bond, 使用多个参数

# ENTRYPOINT 设置默认命令参数,使用 CMD 设置可变动参数
ENTRYPOINT ["top","-b"]
CMD ["-c"]

docker run -it [image] -H # 实际执行 top -b -H

shell 格式示例:

ENTRYPOINT exec top -b

VOLUME 指令

创建一个匿名的数据挂载点,运行容器时,可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据等

用法:

VOLUME ["/data"]

示例:

# 用法中的 "/data" 可以是一个 JSON 数组
VOLUME ["/var/log/"]

# 也可以是一个或多个纯字符串
VOLUME /var/log
VOLUME /var/log /var/db

注意事项

  • 如果是以 Windows 系统为基础的容器,容器中的目标路径必须是以下两种之一:
    • 一个不存在的目录或者空目录
    • 只能是 C 盘之外的硬盘空间
  • Dockerfile 中更改 VOLUME:如果任何构建步骤在声明后更改了 VOLUME 内的数据,那么这些更改将被丢弃
  • 如果参数是 JSON 数组形式,必须使用双引号(""

主机目录(挂载点)在容器运行期间创建:主机目录(挂载点)本质上是与主机相关的,而我们无法保证给定的主机目录在所有主机上都可用,因此为了保持镜像的可移植性,我们不能从 Dockerfile 中挂载主机目录,所以 VOLUME 指令不支持指定 host-dir 参数,只能在创建或运行容器时指定挂载点

USER 指令

指定运行容器时的用户名或 UID ,当容器运行的服务不需要管理员权限时,可以先建立一个特定的用户和用户组,为它分配必要的权限,使用 USER 切换到这个用户

  • 使用 USER 指定可以设置用户名(或 UID )以及可选的用户组(或 GID
  • 使用 USER 指定用户后, Dockerfile 中后续的命令 RUNCMDENTRYPOINT 都将使用该用户

用法:

# 指定 用户名、组名
USER <user>[:<group>]

# 指定 用户ID、组ID
USER <UID>[:<GID>]

示例:

# 设置用户名 www
USER www

注意事项

  • Windows 上,如果用户不是内置账户,则必须创建该用户
  • 可以通过 DockerfileRUN net user 命令来完成,如下:
# 在容器创建新用户
RUN net user /add www

# 设置用户
USER wwww
  • 也可以使用 docker run -u 指定用户

    • 替代默认设置的用户
    • 可以使用 uid 来指定用户

    shell

    docker run -it -u 1001 busybox sh
    

WORKDIR 指令

  • 切换到镜像中的指定路径,设置工作目录
  • WORKDIR 中需要使用绝对路径,如果镜像中对应的路径不存在,会自动创建此目录
  • 一般用 WORKDIR 来替代 RUN cd <path> && <do something> 切换目录进行操作的命令
  • WORKDIR 指令为 Dockerfile 中跟随它的任何 RUNCMDENTRYPOINTCOPYADD 指令设置工作目录
  • 如果 WORKDIR 不存在,即使它没有在任何后续 Dockerfile 命令中使用,它也会被创建

用法:

WORKDIR /path/to/workdir

示例:

WORKDIR 指令可以在 Dockerfile 中多次使用,如果提供了相对路径,它将相对于前一个 WORKDIR 指令的路径,为了避免出错,推荐 WORKDIR 指令中只使用绝对路径

# 指定工作目录为 /tmp 
WORKDIR /tmp
COPY test.txt .

# WORKDIR 指令,可以使用 ENV 设置的环境变量
ENV DIRPATH=/path
WORKDIR DIRNAME
RUN pwd # /path/$DIRNAME

ARG 指令

用于定义一个变量,用户可以在构建 Docker 镜像时,使用 --build-arg 定义变量,如下:

新建一个 Dockerfile 文件,使用 ARG 指令定义参数 username,这里没有赋予默认值:

dockerfile

FROM ubuntu
ARG param
RUN echo $param

使用构建命令,并传入变量参数:

shell

docker build --build-arg param=helloworld -t myimage:1.0.0.beta .

警告

不建议在构建时使用 ARG 指令传递秘钥、用户凭证等信息,因为构建时的信息任何用户都可以通过 docker history 看到 !!!

用法:

ARG <name>[=<default value>]

示例:

# 如果在 FROM 指令之前指定,那么只能用于 FROM 指令中
ARG VERSION=latest
FROM ubuntu:${VERSION}

# 多阶段构建时,FROM 指令之前定义的 ARG 变量,每个 FROM 都能用
ARG VERSION=latest
FROM ubuntu:${VERSION}
RUN echo 'ubuntu...'

FROM node:${VERSION}
RUN npm -v

提示

ARGENV 的区别:

  • ARG 定义的变量只会存在于镜像的构建过程,启动容器后并不保留这些变量
  • ENV 定义的变量在启动容器后仍然保留

预定义ARG

Docker 中有一组预定义的变量,无需 Dockerfile 中的 ARG 指令指定,在运行容器时通过 --build-arg 参数指定即可,而且这些预定义变量不会在 docker history 中记录。

预定义变量如下:

  • HTTP_PROXY
  • http_proxy
  • HTTPS_PROXY
  • https_proxy
  • FTP_PROXY
  • ftp_proxy
  • NO_PROXY
  • no_proxy
  • ALL_PROXY
  • all_proxy

ONBUILD 指令

ONBUILD 是一个特殊的指令,它后面跟着的是其他指令,比如 RUNCOPY 等,而这些指令,在当前镜像构建时并不会被执行,只有当前镜像作为基础镜像,去构建下一级镜像的时候才会被执行。

Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的

ONBUILD 工作原理

  1. 当遇到 ONBUILD 指令时,构建器会向正在构建的镜像的元数据添加触发器。没有ONBUILD指令时,不会影响当前构建。
  2. 构建结束时,所有触发器的列表存储在镜像清单中的 .Container.OnBuild 键中。可以使用命令 docker inspect 检查它们。
  3. 使用 FROM 指令将镜像用作新构建的基础镜像时,作为处理 FROM 指令的一部分,下游构建器将查找 ONBUILD 触发器,并按照注册的顺序执行它们。如果任何一个触发器失败,那么 FROM 指令将被中止,从而导致构建失败。如果所有触发器都成功,则 FROM 指令将完成,构建将照常继续。
  4. 触发器在执行后从当次构建的镜像中清除,换句话说,它们不是由“孙子”构建继承的。 :::

用法:

ONBUILD <INSTRUCTION>

示例:

# 当被作为基础镜像进行构建时,触发器执行 RUN 指令自动创建 /app/src 目录
ONBUILD RUN mkdir /app/src

提示

  • 不允许使用 ONBUILD 指令链接 ONBUILD 指令
  • ONBUILD 指令不能令 FROMMAINTAINER 指令触发

STOPSIGNAL 指令

设置停止容器所要发送的系统调用信号,所使用的信号必须是内核系统调用表中的合法的值,如:9SIGKILL

用法:

默认停止信号是 SIGTERM ,在 docker stop 的时候会给容器内 PID1 的进程发送这个 signal,通过 --stop-signal 可以设置自己需要的 signal,主要目的是为了让容器内的应用程序在接收到 signal

之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,这个时间默认是 10s

STOPSIGNAL signal

HEALTHCHECK 指令

用于健康检查,通过 HEALTHCHECK 指令告诉 Docker 如何测试容器以检查它是否仍在工作,当镜像指定了 HEALTHCHECK 指令后,启动容器时,初始状态会为 starting , 检查通过后会变为 healthy ,如果连续失败一定次数后,则会变为 unhealthy

选项参数:

OPTIONS 描述
--interval=DURATION 运行检查间隔时间,默认:30s
--timeout=DURATION 超时时间,默认:30s
--start-period=DURATION 初始化时间,默认:0s
--start-interval=DURATION 两次检查时间间隔,默认:5s
--retries=N 最大重试次数,默认:3

用法:

HEALTHCHECK 返回值:

  • 0:成功 - 容器运行状况良好并可供使用
  • 1:不健康 - 容器无法正常工作
  • 2:保留 - 不使用此退出代码

dockerfile

# 通过容器内运行命令来检查容器运行状况
HEALTHCHECK [OPTIONS] CMD command

# 禁用从基础镜像继承的任何健康检查
HEALTHCHECK NONE

示例:

# 每隔 5min 检查一次,通过 curl 检查 Web 服务是否在正常工作
HEALTHCHECK --interval=5m --timeout=3s  CMD curl -f http://localhost/ || exit 1

SHELL 指令

用于设置执行命令所使用的默认 shell 类型

  • Linux 默认为 ["/bin/sh","-c"]
  • Windows 默认使用:["cmd","/S","/C"]

SHELL 指令必须在 Dockerfile 中以 JSON 格式编写,SHELL 指令可以出现多次,每条 SHELL 指令都会覆盖所有先前的 SHELL 指令,并影响所有后续指令。

用法:

SHELL ["executable","parameters"]

示例:

# Linux 下,指定 /bin/bash
SHELL ["/bin/bash","-c"]
RUN echo hello

# Windows 下,指定 Powershell
SHELL ["powershell","-command"]
RUN Write-Host hello

# Windows 下,指定 cmd 
SHELL ["cmd","/S","/C"]
RUN echo hello
updatedupdated2025-08-222025-08-22