Dockerfile 参考
Docker 可以通过读取 Dockerfile 文件。Dockerfile 是一个文本文档,其中包含 用户可以调用命令行来组装镜像。本页介绍了 您可以在 Dockerfile 中使用的命令。
概述
Dockerfile 支持以下说明:
| 指令 | 描述 |
|---|---|
ADD | 添加本地或远程文件和目录。 |
ARG | 使用构建时变量。 |
CMD | 指定 default 命令。 |
COPY | 复制文件和目录。 |
ENTRYPOINT | 指定默认可执行文件。 |
ENV | 设置环境变量。 |
EXPOSE | 描述您的应用程序正在侦听的端口。 |
FROM | 从基础镜像创建新的构建阶段。 |
HEALTHCHECK | 在启动时检查容器的运行状况。 |
LABEL | 将元数据添加到镜像中。 |
MAINTAINER | 指定镜像的作者。 |
ONBUILD | 指定何时在构建中使用镜像的说明。 |
RUN | 执行生成命令。 |
SHELL | 设置镜像的默认 shell。 |
STOPSIGNAL | 指定退出容器的系统调用信号。 |
USER | 设置用户和组 ID。 |
VOLUME | 创建卷挂载。 |
WORKDIR | 更改工作目录。 |
格式
以下是 Dockerfile 的格式:
# Comment
INSTRUCTION arguments该指令不区分大小写。然而,惯例是他们 是 UPPERCASE 以便更轻松地将它们与参数区分开来。
Docker 按顺序在 Dockerfile 中运行说明。一个 Dockerfile必须
以FROM指令.这可能是在解析器
指令、注释和全局范围的 ARG 中。这FROM指令指定基数
您来自的图片
建筑。FROM只能有一个或多个ARGinstructions,其中
声明在FROM行。
BuildKit 将 开头的行视为注释,除非该行是
有效的 parser 指令。随处可见的标记
else 被视为参数。这允许如下语句:##
# Comment
RUN echo 'we are running some # of cool things'在执行 Dockerfile 指令之前,将删除注释行。
以下示例中的注释在 shell 执行之前被删除
这echo命令。
RUN echo hello \
# comment
world以下示例是等效的。
RUN echo hello \
world注释不支持行继续符。
注意
关于空格的注意事项
为了向后兼容,在 comments () 和 指令(如
#RUN) 被忽略,但不建议这样做。前导空格 在这些情况下不会保留,因此以下示例是 等效:# this is a comment-line RUN echo hello RUN echo world# this is a comment-line RUN echo hello RUN echo world但是,指令参数中的空格不会被忽略。 以下示例打印
hello world指定前导空格:RUN echo "\ hello\ world"
解析器指令
解析器指令是可选的,并影响后续行的方式
在 Dockerfile 中。解析器指令不会向构建中添加层,
并且不会显示为 Build steps。解析器指令编写为
表单中的特殊类型的注释# directive=value.单个指令
只能使用一次。
支持以下解析器指令:
处理完评论、空行或构建器指令后,BuildKit 不再查找解析器指令。相反,它会处理任何格式化的内容 作为解析器指令作为注释,并且不会尝试验证它是否可能 be a parser 指令。因此,所有解析器指令都必须位于 top 的 Dockerfile 中。
解析器指令键,例如syntax或check不区分大小写,但
按照惯例,它们是小写的。指令的值区分大小写,并且
必须以指令的适当大小写编写。例如#check=skip=jsonargsrecommended无效,因为检查名称必须使用
帕斯卡大小写,而不是小写。通常包含空行
遵循任何 parser 指令。不支持换行符
in parser 指令。
由于这些规则,以下示例都是无效的:
由于换行而无效:
# direc \
tive=value由于出现两次而无效:
# directive=value1
# directive=value2
FROM ImageName被视为注释,因为它出现在 builder 指令之后:
FROM ImageName
# directive=value被视为注释,因为它出现在不是解析器的注释之后 命令:
# About my dockerfile
# directive=value
FROM ImageName以下内容unknowndirective被视为注释,因为它不是
认可。已知的syntax指令被视为注释,因为它
显示在不是解析器指令的 Comment 之后。
# unknowndirective=value
# syntax=valueparser 指令中允许使用非换行空格。因此, 以下行的处理方式相同:
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value语法
使用syntaxparser 指令将 Dockerfile 语法 version 声明为
用于构建。如果未指定,则 BuildKit 使用
Dockerfile 前端。声明语法 version 后,您可以自动使用
最新的 Dockerfile 版本,而无需升级 BuildKit 或 Docker Engine,
甚至使用自定义 Dockerfile 实现。
大多数用户希望将此解析器指令设置为docker/dockerfile:1,
这会导致 BuildKit 拉取 Dockerfile 的最新稳定版本
语法。
# syntax=docker/dockerfile:1有关 parser 指令工作原理的更多信息,请参阅自定义 Dockerfile 语法。
逃
# escape=\或
# escape=`这escape指令设置用于转义
Dockerfile 文件。如果未指定,则默认转义字符为 .\
转义字符既可用于转义行中的字符,也可用于
转义换行符。这允许 Dockerfile 指令
跨多行。请注意,无论escape解析 器
directive 包含在 Dockerfile 中,则不会在
一个RUN命令,但行尾除外。
将转义字符设置为 在`Windows,其中 是目录路径分隔符。 是一致的
使用 Windows PowerShell。\`
请考虑以下示例,该示例在
窗户。第二行末尾的第二个将被解释为
escape,而不是第一个 escape 的目标。
同样,第三行末尾的 the 也会,假设它实际上是
处理为指令,因此将其视为 line continuation。结果
的 Dockerfile 是第二行和第三行被视为单个
指令:\\\
FROM microsoft/nanoserver
COPY testfile.txt c:\\
RUN dir c:\结果:
PS E:\myproject> docker build -t cmd .
Sending build context to Docker daemon 3.072 kB
Step 1/2 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/2 : COPY testfile.txt c:\RUN dir c:
GetFileAttributesEx c:RUN: The system cannot find the file specified.
PS E:\myproject>
上述方法的一种解决方案是将/COPYinstruction,以及dir.然而,这种语法充其量只是令人困惑,因为它并非如此
对于 Windows 上的路径来说,这是自然的,最坏的情况是,由于并非所有命令都打开,因此容易出错
Windows 支持作为路径分隔符。/
通过添加escapeparser 指令,以下 Dockerfile 成功为
预期在 Windows 上对文件路径使用自然平台语义时:
# escape=`
FROM microsoft/nanoserver
COPY testfile.txt c:\
RUN dir c:\结果:
PS E:\myproject> docker build -t succeeds --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1/3 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/3 : COPY testfile.txt c:\
---> 96655de338de
Removing intermediate container 4db9acbb1682
Step 3/3 : RUN dir c:\
---> Running in a2c157f842f5
Volume in drive C has no label.
Volume Serial Number is 7E6D-E0F7
Directory of c:\
10/05/2016 05:04 PM 1,894 License.txt
10/05/2016 02:22 PM <DIR> Program Files
10/05/2016 02:14 PM <DIR> Program Files (x86)
10/28/2016 11:18 AM 62 testfile.txt
10/28/2016 11:20 AM <DIR> Users
10/28/2016 11:20 AM <DIR> Windows
2 File(s) 1,956 bytes
4 Dir(s) 21,259,096,064 bytes free
---> 01c7f3bef04f
Removing intermediate container a2c157f842f5
Successfully built 01c7f3bef04f
PS E:\myproject>
检查
# check=skip=<checks|all>
# check=error=<boolean>这check指令用于配置构建检查的评估方式。默认情况下,将运行所有检查,并将失败视为
警告。
您可以使用#check=skip=<check-name>.要指定
要跳过多个检查,请用逗号分隔它们:
# check=skip=JSONArgsRecommended,StageNameCasing要禁用所有检查,请使用#check=skip=all.
默认情况下,生成检查失败的生成以零状态代码退出
尽管有警告。要使构建在出现警告时失败,请将#check=error=true.
# check=error=true注意
使用
check指令,使用error=true选项,建议 将 Dockerfile 语法固定到特定版本。否则,您的 build 可能会 在将来的版本中添加新的检查时开始失败。
要将skip和error选项中,使用分号分隔
他们:
# check=skip=JSONArgsRecommended;error=true要查看所有可用的检查,请参阅 构建检查参考.
请注意,可用的检查取决于 Dockerfile 语法版本。要使
确保您获得的是最新的检查,请使用syntax指令将 Dockerfile 语法版本指定为最新的稳定版
版本。
环境替换
环境变量(使用这ENV陈述) 也可以是
在某些指令中用作变量,由
Dockerfile 文件。还处理转义以包含类似变量的语法
转换为语句。
环境变量在 Dockerfile 中用$variable_name或${variable_name}.它们被等效地处理,并且
大括号语法通常用于解决变量名称中没有
空格,例如${foo}_bar.
这${variable_name}语法还支持一些标准的bash修饰符,如下所示:
${variable:-word}表示如果variable设置,则结果 将是该值。如果variable未设置,则word将是结果。${variable:+word}表示如果variable则word将是 result,否则结果为空字符串。
的预发布版本支持以下变量替换
Dockerfile 语法,当使用# syntax=docker/dockerfile-upstream:master语法
指令中:
${variable#pattern}删除pattern从variable, 从字符串的开头开始查找。str=foobarbaz echo ${str#f*b} # arbaz${variable##pattern}删除pattern从variable, 从字符串的开头开始查找。str=foobarbaz echo ${str##f*b} # az${variable%pattern}删除pattern从variable, 从字符串的末尾向后查找。string=foobarbaz echo ${string%b*} # foobar${variable%%pattern}删除pattern从variable, 从字符串的末尾向后查找。string=foobarbaz echo ${string%%b*} # foo${variable/pattern/replacement}替换pattern在variable跟replacementstring=foobarbaz echo ${string/ba/fo} # fooforbaz${variable//pattern/replacement}替换所有出现的pattern在variable跟replacementstring=foobarbaz echo ${string//ba/fo} # fooforfoz
在所有情况下,word可以是任何字符串,包括其他环境
变量。
pattern是一个 glob 模式,其中?匹配任何单个字符
和任意数量的字符(包括零)。匹配 Literal*?和
使用反斜杠转义:*\?和。\*
您可以通过在变量前添加 a 来转义整个变量名称:\\$foo或\${foo},
例如,将转换为$foo和${foo}literals 分别。
示例(解析的表示显示在 之后):#
FROM busybox
ENV FOO=/bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux环境变量由以下说明列表支持 Dockerfile 中:
ADDCOPYENVEXPOSEFROMLABELSTOPSIGNALUSERVOLUMEWORKDIRONBUILD(与上述支持的说明之一结合使用时)
您还可以将环境变量与RUN,CMD和ENTRYPOINT指令,但在这些情况下,变量替换由
命令 shell,而不是构建器。请注意,使用 exec 表单的说明
不要自动调用命令 shell。查看变量
替换。
环境变量替换对每个变量使用相同的值 贯穿整个教学过程。更改变量的值只需要 effect 的 intent 的 intent请考虑以下示例:
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc- 的值
def成为hello - 的值
ghi成为bye
.dockerignore 文件
您可以使用.dockerignorefile 从
构建上下文。有关更多信息,请参阅 .dockerignore 文件。
Shell 和 exec 表单
这RUN,CMD和ENTRYPOINT指令都有两种可能的形式:
INSTRUCTION ["executable","param1","param2"](执行表单)INSTRUCTION command param1 param2(壳体形式)
exec 表单可以避免 shell 字符串修改,并在 命令,或任何其他可执行文件。它使用 JSON 数组语法,其中数组中的每个元素都是一个命令、标志或 论点。
壳体形式更加宽松,强调易用性、灵活性和 可读性。shell 表单自动使用命令 shell,而 exec 表单中没有。
执行表单
exec 表单被解析为 JSON 数组,这意味着 您必须在单词周围使用双引号 (“”),而不是单引号 (')。
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]exec 表单最适合用于指定ENTRYPOINT指令, 组合
跟CMD用于设置可在运行时覆盖的默认参数。为
有关更多信息,请参阅 ENTRYPOINT。
变量替换
使用 exec 表单不会自动调用命令 shell。这意味着
正常的 shell 处理(例如变量替换)不会发生。
例如RUN [ "echo", "$HOME" ]不会处理 的变量替换$HOME.
如果您想要 shell 处理,请使用 shell 形式或执行 shell
直接使用 exec 表单,例如:RUN [ "sh", "-c", "echo $HOME" ].
当使用 exec 表单并直接执行 shell 时,就像
shell 形式,则是执行环境变量替换的 shell,
不是建筑商。
反 斜线
在 exec 形式中,您必须转义反斜杠。这在 其中反斜杠是路径分隔符的 Windows。以下行将 否则,由于不是有效的 JSON,因此被视为 shell 形式,并在 意想不到的方式:
RUN ["c:\windows\system32\tasklist.exe"]此示例的正确语法为:
RUN ["c:\\windows\\system32\\tasklist.exe"]壳型
与 exec 表单不同,使用 shell 表单的指令始终使用命令 壳。shell 形式不使用 JSON 数组格式,而是常规的 字符串。shell 形式字符串允许您使用 escape 字符(默认为反斜杠)以继续执行单个指令 到下一行。这使得它更容易与较长的命令一起使用,因为 它允许您将它们分成多行。例如,考虑这两个 线:
RUN source $HOME/.bashrc && \
echo $HOME它们相当于以下行:
RUN source $HOME/.bashrc && echo $HOME你也可以将 heredocs 与 shell 形式一起使用来分解支持的命令。
RUN <<EOF
source $HOME/.bashrc && \
echo $HOME
EOF有关 heredocs 的更多信息,请参阅 Here-documents。
使用不同的 shell
您可以使用SHELL命令。例如:
SHELL ["/bin/bash", "-c"]
RUN echo hello有关更多信息,请参阅 SHELL。
从
FROM [--platform=<platform>] <image> [AS <name>]或
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]或
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]这FROM指令初始化一个新的构建阶段,并为后续
指示。因此,有效的 Dockerfile 必须以FROM指令。
镜像可以是任何有效的镜像。
ARG是唯一可能位于FROM在 Dockerfile 中。 请参阅了解 ARG 和 FROM 如何交互。FROM可以在单个 Dockerfile 中多次出现,以 创建多个镜像或将一个构建阶段用作另一个构建阶段的依赖项。 只需记下提交在每个新FROM指令。每FROM指令清除 previous 创建的任何状态 指示。- (可选)可以通过添加
AS name到FROM指令。该名称可用于后续FROM <name>,COPY --from=<name>, 和RUN --mount=type=bind,from=<name>指示 引用此阶段构建的镜像。 - 这
tag或digest值是可选的。如果省略其中任何一个,则 builder 假定latest标签。如果 Builder 出现 找不到tag价值。
可选的--platformflag 可用于指定镜像的平台
倘FROM引用多平台镜像。例如linux/amd64,linux/arm64或windows/amd64.默认情况下,生成的目标平台
request 的 API 请求。全局构建参数可以在此标志的值中使用,
例如,自动平台 ARG 允许您强制将阶段转换为本机构建平台 (--platform=$BUILDPLATFORM),
并使用它交叉编译到 stage 内的目标平台。
了解 ARG 和 FROM 如何交互
FROMinstructions 支持由任何ARG指令出现在第一个FROM.
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras一ARG在FROM位于 build 阶段之外,因此
不能在FROM.要使用默认值
一ARG在第一个FROM使用ARG指令 无
构建阶段中的值:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version跑
这RUN指令将执行任何命令以在
当前镜像。添加的层将在 Dockerfile 的下一步中使用。RUN有两种形式:
# Shell form:
RUN [OPTIONS] <command> ...
# Exec form:
RUN [OPTIONS] [ "<command>", ... ]有关这两种表单之间差异的更多信息,请参阅 shell 或 exec 表单。
shell 形式是最常用的,可以让您分解更长时间 指令转换为多行,使用换行转义,或者 使用 heredocs:
RUN <<EOF
apt-get update
apt-get install -y curl
EOF可用的[OPTIONS]对于RUN指令是:
| 选择 | 最低 Dockerfile 版本 |
|---|---|
--mount | 1.2 |
--network | 1.3 |
--security | 1.1.2-实验室 |
RUN 指令的缓存失效
的缓存RUN说明不会在
下一个版本。像RUN apt-get dist-upgrade -y将在下次构建期间重复使用。这
cache 的RUN可以使用--no-cacheflag 的docker build --no-cache.
请参阅 Dockerfile 最佳实践 指南了解更多信息。
运行 --mount
RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]RUN --mount允许您创建构建可以访问的文件系统挂载。
这可用于:
- 创建绑定挂载到主机文件系统或其他构建阶段
- 访问构建密钥或 ssh-agent 套接字
- 使用持久性包管理缓存加快构建速度
支持的挂载类型包括:
| 类型 | 描述 |
|---|---|
bind(默认) | 绑定挂载上下文目录(只读)。 |
cache | 挂载临时目录以缓存编译器和包管理器的目录。 |
tmpfs | 挂载tmpfs在 Build Container 中。 |
secret | 允许构建容器访问私钥等安全文件,而无需将其烘焙到镜像或构建缓存中。 |
ssh | 允许构建容器通过 SSH 代理访问 SSH 密钥,并支持密码。 |
运行 --mount=type=bind
此挂载类型允许将文件或目录绑定到构建容器。一个 默认情况下,bind mount 是只读的。
| 选择 | 描述 |
|---|---|
target,dst,destination1 | 挂载路径。 |
source | 源路径from.默认为from. |
from | 为源的根生成阶段、上下文或镜像名称。默认为 build 上下文。 |
rw,readwrite | 允许在挂载上写入。写入的数据将被丢弃。 |
运行 --mount=type=cache
此挂载类型允许构建容器缓存编译器的目录 和包管理器。
| 选择 | 描述 |
|---|---|
id | 用于标识单独/不同缓存的可选 ID。默认为target. |
target,dst,destination1 | 挂载路径。 |
ro,readonly | 如果设置,则为 Read-only。 |
sharing | 其中之一shared,private或locked.默认为shared.一个sharedcache mount 可以被多个写入器同时使用。private如果有多个写入器,则创建一个新的挂载。locked暂停第二个写入器,直到第一个写入器释放挂载。 |
from | 构建阶段、上下文或镜像名称,以用作缓存挂载的基础。默认为空目录。 |
source | Subpath 中的from进行挂载。默认为from. |
mode | 八进制中新缓存目录的文件模式。违约0755. |
uid | 新缓存目录的用户 ID。违约0. |
gid | 新缓存目录的组 ID。违约0. |
缓存目录的内容在生成器调用之间仍然存在,没有 使指令缓存失效。缓存挂载应该仅用于更好的 性能。您的构建版本应与缓存目录的任何内容一起使用,如 如果存储空间增加,另一个构建可能会覆盖文件,或者 GC 可能会清理文件 是必需的。
示例:缓存 Go 包
# syntax=docker/dockerfile:1
FROM golang
RUN --mount=type=cache,target=/root/.cache/go-build \
go build ...示例:缓存 apt 软件包
# syntax=docker/dockerfile:1
FROM ubuntu
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && apt-get --no-install-recommends install -y gccApt 需要对其数据进行独占访问,因此缓存使用sharing=locked,这将确保使用
相同的缓存挂载将相互等待,而不是访问相同的
cache 文件。您还可以使用sharing=private如果
您更喜欢让每个构建在此
箱。
运行 --mount=type=tmpfs
这种安装类型允许安装tmpfs在 Build Container 中。
| 选择 | 描述 |
|---|---|
target,dst,destination1 | 挂载路径。 |
size | 指定文件系统大小的上限。 |
运行 --mount=type=secret
此挂载类型允许构建容器访问 secret 值,例如 令牌或私钥,而无需将它们烘焙到镜像中。
默认情况下,密钥作为文件挂载。您还可以将 secret 挂载为
环境变量,方法是将env选择。
| 选择 | 描述 |
|---|---|
id | 密钥的 ID。默认为目标路径的 basename 。 |
target,dst,destination | 将密钥挂载到指定路径。默认为/run/secrets/ + id如果未设置且env也未设置。 |
env | 将密钥挂载到环境变量而不是文件,或同时挂载到两者。(自 Dockerfile v1.10.0 起) |
required | 如果设置为true,则当 secret 不可用时,指令会出错。默认为false. |
mode | 八进制中 secret 文件的文件模式。违约0400. |
uid | secret 文件的用户 ID。违约0. |
gid | 密钥文件的组 ID。违约0. |
示例:访问 S3
# syntax=docker/dockerfile:1
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
aws s3 cp s3://... ...$ docker buildx build --secret id=aws,src=$HOME/.aws/credentials .
示例:作为环境变量挂载
以下示例采用 secretAPI_KEY并将其挂载为
环境变量。
# syntax=docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=API_KEY,env=API_KEY \
some-command --token-from-env $API_KEY假设API_KEY环境变量
环境中,您可以使用以下命令构建此 API:
$ docker buildx build --secret id=API_KEY .
运行 --mount=type=ssh
此挂载类型允许构建容器通过 SSH 代理访问 SSH 密钥。 支持密码。
| 选择 | 描述 |
|---|---|
id | SSH 代理套接字或密钥的 ID。默认为 “default”。 |
target,dst,destination | SSH 代理套接字路径。默认为/run/buildkit/ssh_agent.${N}. |
required | 如果设置为true,则当密钥不可用时,指令会出错。默认为false. |
mode | 八进制套接字的文件模式。违约0600. |
uid | 套接字的用户 ID。违约0. |
gid | 套接字的组 ID。违约0. |
示例:访问 GitLab
# syntax=docker/dockerfile:1
FROM alpine
RUN apk add --no-cache openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh \
ssh -q -T git@gitlab.com 2>&1 | tee /hello
# "Welcome to GitLab, @GITLAB_USERNAME_ASSOCIATED_WITH_SSHKEY" should be printed here
# with the type of build progress is defined as `plain`.$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ docker buildx build --ssh default=$SSH_AUTH_SOCK .
您还可以指定*.pem文件直接放在主机上,而不是$SSH_AUTH_SOCK.
但是,不支持带有密码的 pem 文件。
运行 --network
RUN --network=<TYPE>RUN --network允许控制命令的联网环境
被磨合。
支持的网络类型包括:
运行 --network=default
相当于根本不提供标志,该命令在默认的 network 进行构建。
运行 --network=none
命令在没有网络访问权限 (lo仍然可用,但
isolate to this process (隔离到此过程)
示例:隔离外部效果
# syntax=docker/dockerfile:1
FROM python:3.6
ADD mypackage.tgz wheels/
RUN --network=none pip install --find-links wheels mypackagepip将只能安装 tarfile 中提供的软件包,该软件包
可以由早期构建阶段控制。
运行 --network=host
该命令在主机的网络环境中运行(类似于docker build --network=host,但基于每条指令)
警告
的使用
--network=host受network.host权利 在使用--allow-insecure-entitlement network.hostflag 或 buildkitd 配置中, 对于具有--allow network.host旗.
运行 --security
注意
目前尚不支持稳定的语法,请使用
docker/dockerfile:1-labs版本。
RUN --security=<sandbox|insecure>默认安全模式为sandbox.
跟--security=insecure,构建器在 insecure 中运行不带 sandbox 的命令
模式,允许运行需要提升权限的流(例如 containerd)。
这相当于运行docker run --privileged.
警告
要访问此功能,权利
security.insecure应该是 在使用--allow-insecure-entitlement security.insecureflag 或 buildkitd 配置中, 对于具有--allow security.insecure旗.
默认沙盒模式可以通过以下方式激活--security=sandbox,但这是无作。
示例:检查权利
# syntax=docker/dockerfile:1-labs
FROM ubuntu
RUN --security=insecure cat /proc/self/status | grep CapEff#84 0.093 CapEff: 0000003fffffffffCMD
这CMDinstruction 设置运行容器时要执行的命令
从镜像中。
您可以指定CMD使用 shell 或 exec 表单的说明:
CMD ["executable","param1","param2"](执行表单)CMD ["param1","param2"](exec 表单,作为ENTRYPOINT)CMD command param1 param2(壳体形式)
只能有一个CMD指令。如果您列出的超过
一CMD,只有最后一个生效。
目的CMD是为正在执行的容器提供默认值。这些
defaults 可以包含可执行文件,也可以省略可执行文件,其中
case 中,您必须指定ENTRYPOINT指令也是如此。
如果您希望容器每次都运行相同的可执行文件,则
您应该考虑使用ENTRYPOINT与CMD.看ENTRYPOINT.如果用户将参数指定为docker run然后,它们将覆盖CMD,但仍使用
违约ENTRYPOINT.
如果CMD用于为ENTRYPOINT指令
这两个CMD和ENTRYPOINT应在 exec 表单中指定说明。
注意
不要混淆
RUN跟CMD.RUN实际运行命令并提交 结果;CMD在构建时不执行任何内容,但指定 镜像的预期命令。
标签
LABEL <key>=<value> [<key>=<value>...]这LABEL指令将元数据添加到镜像中。一个LABEL是一个
键值对。要在LABELvalue、use quotes 和
反斜杠,就像在命令行解析中所做的那样。一些使用示例:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."一个镜像可以有多个标签。您可以在 单行。在 Docker 1.10 之前,这减小了最终镜像的大小, 但现在情况已不再如此。您仍然可以选择指定多个标签 在单个指令中,通过以下两种方式之一:
LABEL multi.label1="value1" multi.label2="value2" other="value3"LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"注意
请务必使用双引号,而不是单引号。特别是当您 使用字符串插值(例如
LABEL example="foo-$ENV_VAR")、单 quotes 将按原样获取字符串,而无需解压缩变量的值。
基础镜像中包含的标签(FROM行)由
您的镜像。如果标签已存在但具有不同的值,则
最近应用的值将覆盖任何以前设置的值。
要查看镜像的标签,请使用docker image inspect命令。您可以使用
这--format选项仅显示标签;
$ docker image inspect --format='{{json .Config.Labels}}' myimage
{
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
}MAINTAINER(已弃用)
MAINTAINER <name>这MAINTAINER指令设置生成镜像的 Author 字段。
这LABELinstruction 是其更灵活的版本,您应该使用
相反,因为它可以设置您需要的任何元数据,并且可以查看
轻松,例如使用docker inspect.要设置与MAINTAINER字段:
LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"然后,这将从docker inspect与其他标签一起使用。
暴露
EXPOSE <port> [<port>/<protocol>...]这EXPOSE指令通知 Docker 容器监听
在运行时指定网络端口。您可以指定端口是否侦听
TCP 或 UDP,如果您未指定协议,则默认为 TCP。
这EXPOSE指令实际上并不发布端口。它的功能是
构建镜像的人员与构建镜像的人员之间的文档类型
运行容器,了解要发布的端口。自
publish 端口,请使用-p标记docker run发布和映射一个或多个端口,或者选择-Pflag 发布所有公开的
ports 并将它们映射到高阶 ports。
默认情况下,EXPOSE假设 TCP。您还可以指定 UDP:
EXPOSE 80/udp要在 TCP 和 UDP 上公开,请包含两行代码:
EXPOSE 80/tcp
EXPOSE 80/udp在这种情况下,如果您使用-P跟docker run,则端口将暴露一次
用于 TCP,一次用于 UDP。请记住-P使用短暂的高序主机
端口,因此 TCP 和 UDP 不会使用相同的端口。
无论EXPOSE设置中,您可以在运行时使用
这-p旗。例如
$ docker run -p 80:80/tcp -p 80:80/udp ...
要在主机系统上设置端口重定向,请参阅使用 -P 标志。
这docker network命令支持创建用于通信的网络
容器,而无需公开或发布特定端口,因为
连接到网络的容器可以通过任何
港口。有关详细信息,请参阅此功能概述。
环境
ENV <key>=<value> [<key>=<value>...]这ENV指令设置环境变量<key>到值<value>.此值将位于所有后续指令的环境中
在构建阶段,并且可以在
也有很多。该值将针对其他环境变量进行解释,因此
如果未转义引号字符,则引号字符将被删除。与命令行解析一样,
引号和反斜杠可用于在值中包含空格。
例:
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy这ENV指令允许多个<key>=<value> ...要设置的变量
一次,下面的示例将在最终
镜像:
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy使用ENV将在容器运行时保留
从生成的镜像中。您可以使用docker inspect和
使用docker run --env <key>=<value>.
阶段继承使用ENV通过其
父阶段或任何祖先。有关更多信息,请参阅手册中的多阶段构建部分。
环境变量持久性可能会导致意外的副作用。例如
设置ENV DEBIAN_FRONTEND=noninteractive更改apt-get,
,并且可能会使镜像的用户感到困惑。
如果仅在构建期间需要环境变量,而不需要在最终的 image 中,请考虑为单个命令设置一个值:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...或使用ARG,它不会保留在最终镜像中:
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y ...注意
替代语法
这
ENV指令还允许使用替代语法ENV <key> <value>, 省略 .例如:=ENV MY_VAR my-value此语法不允许在 单
ENV指令,并且可能会令人困惑。例如,以下 设置单个环境变量 (ONE) 的"TWO= THREE=world":ENV ONE TWO= THREE=world为了向后兼容,支持替代语法,但不建议使用 出于上述原因,可能会在将来的发行版中删除。
加
ADD 有两种形式。 对于包含空格的路径,后一种形式是必需的。
ADD [OPTIONS] <src> ... <dest>
ADD [OPTIONS] ["<src>", ... "<dest>"]可用的[OPTIONS]是:
| 选择 | 最低 Dockerfile 版本 |
|---|---|
--keep-git-dir | 1.1 |
--checksum | 1.6 |
--chown | |
--chmod | 1.2 |
--link | 1.4 |
--exclude | 1.7 实验室 |
这ADD指令从<src>并添加了
它们到路径中镜像的文件系统<dest>.文件和目录
可以从构建上下文、远程 URL 或 Git 仓库中复制。
这ADD和COPY指令在功能上相似,但用途略有不同。
详细了解差异ADD和COPY.
源
您可以使用ADD.最后
argument 必须始终是 destination 。例如,要添加两个文件,file1.txt和file2.txt,从 build 上下文到/usr/src/things/在
生成容器:
ADD file1.txt file2.txt /usr/src/things/如果直接或使用通配符指定多个源文件,则
destination 必须是 directory (必须以 slash 结尾)。/
要从远程位置添加文件,您可以指定 URL 或 Git 仓库作为源。例如:
ADD https://example.com/archive.zip /usr/src/things/
ADD git@github.com:user/repo.git /usr/src/things/BuildKit 检测<src>并相应地对其进行处理。
- 如果
<src>是本地文件或目录,则目录的内容为 复制到指定的接收方。请参阅从构建上下文添加文件。 - 如果
<src>是本地 tar 存档,它会被解压缩并提取到 指定的目标。请参阅添加本地 tar 存档。 - 如果
<src>是一个 URL,则 URL 的内容将被下载并放置在 指定的目标。请参阅从 URL 添加文件。 - 如果
<src>是 Git 仓库,则仓库将克隆到指定的 目的地。请参阅从 Git 仓库添加文件。
从构建上下文添加文件
任何不以http://,https://或git@protocol prefix 被视为本地文件路径。本地文件路径为
相对于 build 上下文。例如,如果构建上下文是当前的
目录ADD file.txt /将文件添加到./file.txt到
filesystem 中。
从构建上下文添加源文件时,它们的路径被解释为
相对于上下文的根。如果指定相对路径前导
在 build 上下文之外,例如ADD ../something /something父母
目录路径会自动剥离。中的 有效源路径
此示例变为ADD something /something.
如果源是目录,则复制该目录的内容, 包括 Filesystem 元数据。目录本身不会被复制,只会复制它的 内容。如果它包含子目录,则也会复制这些子目录,并与 目标上的任何现有目录。任何冲突都在 支持逐个文件添加的内容,除非您是 尝试将目录复制到现有文件上,在这种情况下,错误为 提出。
如果源是文件,则文件及其元数据将复制到 目的地。保留文件权限。如果源是文件且 目录,则会引发错误。
如果您通过 stdin 将 Dockerfile 传递给构建 (docker build - < Dockerfile),则没有构建上下文。在这种情况下,您只能使用ADD复制远程文件的说明。您还可以通过
标准输入: (docker build - < archive.tar),则
archive 和存档的其余部分将用作构建的上下文。
模式匹配
对于本地文件,每个<src>可能包含通配符,并且将进行匹配
使用 Go 的 filepath 。匹配规则。
例如,要在构建上下文的根目录中添加所有文件和目录
结尾为.png:
ADD *.png /dest/在以下示例中,?是单字符通配符,匹配例如index.js和index.ts.
ADD index.?s /dest/当添加包含特殊字符(如 和 )的文件或目录时,你需要按照 Golang 规则对这些路径进行转义,以防止
它们不再被视为匹配模式。例如,要添加文件
叫[]arr[0].txt,请使用以下内容;
ADD arr[[]0].txt /dest/添加本地 tar 存档
当使用本地 tar 存档作为ADD,并且存档位于
识别的压缩格式 (gzip,bzip2或xz或未压缩的 URL 中),则
archive 将解压缩并提取到指定的目标中。只
提取本地 tar 档案。如果 tar 存档是远程 URL,则
存档不会提取,而是下载并放置在目标位置。
提取目录时,它与tar -x.
结果是以下各项的并集:
- 目标路径中存在的任何内容,以及
- 源代码树的内容,冲突得到解决,有利于 逐个文件添加的内容。
注意
文件是否被识别为可识别的压缩格式是 仅根据文件的内容(而不是文件名)完成。为 示例,如果空文件恰好以
.tar.gz无法识别 作为压缩文件,并且不会生成任何类型的解压缩错误 消息,而是简单地将文件复制到目标。
从 URL 添加文件
如果 source 是远程文件 URL,则目标将具有
权限为 600。如果 HTTP 响应包含Last-Modified标头、
timestamp 将用于设置mtime在目的地
文件。但是,与在ADD,mtime不是
包含在确定文件是否已更改以及
cache 应该更新。
如果目标以尾部斜杠结尾,则推断文件名
从 URL 路径。例如ADD http://example.com/foobar /将创建
文件/foobar.URL 必须具有重要的路径,以便适当的
filename 可以被发现 (http://example.com不起作用)。
如果目标不以尾部斜杠结尾,则目标路径
将成为从 URL 下载的文件的文件名。例如ADD http://example.com/foo /bar创建文件/bar.
如果您的 URL 文件使用身份验证进行保护,则需要使用RUN wget,RUN curl或使用容器中的其他工具作为ADD指令
不支持身份验证。
从 Git 仓库添加文件
使用 Git 仓库作为ADD中,您可以引用
仓库的 HTTP 或 SSH 地址作为源。仓库将克隆到
指定的 destination 在镜像中。
ADD https://github.com/user/repo.git /mydir/您可以使用 URL 片段指定特定的分支、标签、提交或
子目录。例如,要添加docs目录下的v0.14.1标记的
这buildkit仓库:
ADD git@github.com:moby/buildkit.git#v0.14.1:docs /buildkit-docs有关 Git URL 片段的更多信息, 请参阅 URL 片段。
从 Git 仓库添加时,文件的权限位 是 644 人。如果仓库中的文件设置了可执行位,则它将具有 权限设置为 755。目录的权限设置为 755。
使用 Git 仓库作为源时,仓库必须可访问 从 Build 上下文。要通过 SSH 添加仓库,无论是公共还是私有, 您必须传递 SSH 密钥进行身份验证。例如,给定以下内容 Dockerfile 文件:
# syntax=docker/dockerfile:1
FROM alpine
ADD git@git.example.com:foo/bar.git /bar要构建此 Dockerfile,请将--sshflag 添加到docker build挂载
构建的 SSH 代理套接字。例如:
$ docker build --ssh default .
有关使用 Secret 进行构建的更多信息, 请参阅 构建密钥。
目的地
如果目标路径以正斜杠开头,则将其解释为 absolute path 的 Absolute Path 中,源文件将复制到指定的目标 相对于当前构建阶段的根。
# create /abs/test.txt
ADD test.txt /abs/尾部斜杠很重要。例如ADD test.txt /abs创建一个
文件位于/abs而ADD test.txt /abs/创建/abs/test.txt.
如果目标路径不以前导斜杠开头,则会将其解释为 相对于构建容器的工作目录。
WORKDIR /usr/src/app
# create /usr/src/app/rel/test.txt
ADD test.txt rel/如果 destination 不存在,则会创建该 destination 以及所有缺失的目录 在它的路径上。
如果源是文件,并且目标不以尾部斜杠结尾,则 源文件将作为文件写入目标路径。
添加 --keep-git-dir
ADD [--keep-git-dir=<boolean>] <src> ... <dir>什么时候<src>是远程 Git 仓库的 HTTP 或 SSH 地址,
BuildKit 将 Git 仓库的内容添加到镜像中
不包括.git目录中。
这--keep-git-dir=trueflag 允许您保留.git目录。
# syntax=docker/dockerfile:1
FROM alpine
ADD --keep-git-dir=true https://github.com/moby/buildkit.git#v0.10.1 /buildkit添加 --校验和
ADD [--checksum=<hash>] <src> ... <dir>这--checksumflag 允许您验证远程资源的校验和。这
校验和的格式为<algorithm>:<hash>.支持的算法包括sha256,sha384和sha512.
ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz /这--checksum标志仅支持 HTTP(S) 源。
添加 --chown --chmod
添加 --link
添加 --exclude
复制
COPY 有两种形式。 对于包含空格的路径,后一种形式是必需的。
COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]可用的[OPTIONS]是:
这COPY指令从<src>并添加了
它们到路径中镜像的文件系统<dest>.文件和目录
可以从 Build Context、Build Stage、named context 或镜像中复制。
这ADD和COPY指令在功能上相似,但用途略有不同。
详细了解差异ADD和COPY.
源
您可以使用COPY.最后
argument 必须始终是 destination 。例如,要复制两个文件,file1.txt和file2.txt,从 build 上下文到/usr/src/things/在
生成容器:
COPY file1.txt file2.txt /usr/src/things/如果直接或使用通配符指定多个源文件,则
destination 必须是 directory (必须以 slash 结尾)。/
COPY接受标志--from=<name>,用于指定源位置
设置为构建阶段、上下文或镜像。以下示例从
一个名为build:
FROM golang AS build
WORKDIR /app
RUN --mount=type=bind,target=. go build -o /myapp ./cmd
COPY --from=build /myapp /usr/bin/有关从指定源复制的更多信息,请参阅--from旗.
从构建上下文复制
从构建上下文复制源文件时,它们的路径被解释为
相对于上下文的根。如果指定相对路径前导
在 build 上下文之外,例如COPY ../something /something父母
目录路径会自动剥离。中的 有效源路径
此示例变为COPY something /something.
如果源是目录,则复制该目录的内容, 包括 Filesystem 元数据。目录本身不会被复制,只会复制它的 内容。如果它包含子目录,则也会复制这些子目录,并与 目标上的任何现有目录。任何冲突都在 支持逐个文件添加的内容,除非您是 尝试将目录复制到现有文件上,在这种情况下,错误为 提出。
如果源是文件,则文件及其元数据将复制到 目的地。保留文件权限。如果源是文件且 目录,则会引发错误。
如果您通过 stdin 将 Dockerfile 传递给构建 (docker build - < Dockerfile),则没有构建上下文。在这种情况下,您只能使用COPY从其他阶段、命名上下文或镜像复制文件的指令,
使用--from旗.您还可以传递 tar 存档
通过 stdin: (docker build - < archive.tar)、位于
存档和存档的其余部分将用作
建。
当使用 Git 仓库作为构建上下文时,权限位 复制的文件为 644。如果仓库中的文件设置了可执行位,则 它将将 permissions 设置为 755。目录的权限设置为 755。
模式匹配
对于本地文件,每个<src>可能包含通配符,并且将进行匹配
使用 Go 的 filepath 。匹配规则。
例如,要在构建上下文的根目录中添加所有文件和目录
结尾为.png:
COPY *.png /dest/在以下示例中,?是单字符通配符,匹配例如index.js和index.ts.
COPY index.?s /dest/当添加包含特殊字符(如 和 )的文件或目录时,你需要按照 Golang 规则对这些路径进行转义,以防止
它们不再被视为匹配模式。例如,要添加文件
叫[]arr[0].txt,请使用以下内容;
COPY arr[[]0].txt /dest/目的地
如果目标路径以正斜杠开头,则将其解释为 absolute path 的 Absolute Path 中,源文件将复制到指定的目标 相对于当前构建阶段的根。
# create /abs/test.txt
COPY test.txt /abs/尾部斜杠很重要。例如COPY test.txt /abs创建一个
文件位于/abs而COPY test.txt /abs/创建/abs/test.txt.
如果目标路径不以前导斜杠开头,则会将其解释为 相对于构建容器的工作目录。
WORKDIR /usr/src/app
# create /usr/src/app/rel/test.txt
COPY test.txt rel/如果 destination 不存在,则会创建该 destination 以及所有缺失的目录 在它的路径上。
如果源是文件,并且目标不以尾部斜杠结尾,则 源文件将作为文件写入目标路径。
复制 --from
默认情况下,COPY指令从 build 上下文中复制文件。这COPY --fromflag 允许您从镜像、构建阶段、
或命名上下文。
COPY [--from=<image|stage|context>] <src> ... <dest>要从多阶段构建的构建阶段复制,
指定要从中复制的阶段的名称。您指定阶段名称
使用AS关键字替换为FROM指令。
# syntax=docker/dockerfile:1
FROM alpine AS build
COPY . .
RUN apk add clang
RUN clang -o /hello hello.c
FROM scratch
COPY --from=build /hello /也可以直接从命名上下文 (使用--build-context <name>=<source>) 或镜像。以下示例将nginx.conf文件。
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf的源路径COPY --from始终从
Image 或 stage 中指定的 IMAGE 或 STAGE。
复制 --chown --chmod
注意
目前仅支持八进制表示法。非八进制支持在 moby/buildkit#1951 中跟踪。
COPY [--chown=<user>:<group>] [--chmod=<perms> ...] <src> ... <dest>这--chown和--chmod功能仅支持用于构建 Linux 容器的 Dockerfile、
并且不适用于 Windows 容器。由于用户和组所有权概念确实如此
不在 Linux 和 Windows 之间进行翻译,使用/etc/passwd和/etc/group为
将用户和组名称转换为 ID 会将此功能限制为仅适用于
基于 Linux作系统的容器。
从构建上下文复制的所有文件和目录都是使用 UID 和 GID 创建的0除非
自选--chownflag 指定给定的用户名、组名或 UID/GID
组合以请求对复制内容的特定所有权。这
格式--chownflag 允许使用 username 和 groupname 字符串
或直接整数 UID 和 GID 的任意组合。提供用户名,但不提供
groupname 或不带 GID 的 UID 将使用与 GID 相同的数字 UID。如果
username 或 groupname 时,容器的根文件系统/etc/passwd和/etc/group文件将用于执行翻译
从 name 分别转换为整数 UID 或 GID。以下示例显示
的有效定义--chown旗:
COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/
COPY --chown=myuser:mygroup --chmod=644 files* /somedir/如果容器根文件系统不包含/etc/passwd或/etc/groupfiles 和用户名或组名称用于--chown标志,则构建将在COPY操作。使用数字 ID 需要
无需查找,并且不依赖于容器根文件系统内容。
使用 Dockerfile 语法版本 1.10.0 及更高版本时,
这--chmodflag 支持变量插值,
这允许您使用 build 参数定义权限位:
# syntax=docker/dockerfile:1.10
FROM alpine
WORKDIR /src
ARG MODE=440
COPY --chmod=$MODE . .复制 --link
COPY [--link[=<boolean>]] <src> ... <dest>在COPY或ADD命令允许您复制文件
增强的语义,其中文件在其自己的层上保持独立,并且
当先前层上的命令发生更改时,不会失效。
什么时候--link,则源文件将复制到空目标中
目录。该目录将转换为一个层,该层链接到
previous 状态。
# syntax=docker/dockerfile:1
FROM alpine
COPY --link /foo /bar相当于执行两个构建:
FROM alpine和
FROM scratch
COPY /foo /bar并将两个镜像的所有图层合并在一起。
使用--link
用--link要在后续构建中重用已构建的层,请使用--cache-from即使之前的图层已更改。这一点尤其
对于多阶段构建非常重要,其中COPY --fromstatement 将
如果同一阶段中的任何先前命令发生更改,则 previously 将失效,
导致需要再次重建中间阶段。跟--link这
层被重用并合并到新的
层。这也意味着您可以在使用基础镜像时轻松变基镜像
接收更新,而无需再次执行整个构建。在后端
支持它,BuildKit 可以执行这个 rebase作,而无需推送或
拉取客户端和注册表之间的任何层。BuildKit 将检测到这一点
case 创建,并且仅创建包含新层和旧层的新镜像清单
图层。
BuildKit 可以避免下拉基础镜像的相同行为也可以
使用--link并且没有其他需要访问
基础镜像中的文件。在这种情况下,BuildKit 将仅构建层
对于COPY命令,并将它们直接推送到注册表中的
图层。
不兼容--link=false
使用--link这COPY/ADD不允许 commands 读取任何文件
从上一个状态。这意味着,如果在先前的状态下,目标
directory 是包含符号链接的路径,COPY/ADD无法遵循它。
在最终镜像中,使用--link将始终是一个
path 中仅包含目录。
如果您不依赖目标中以下符号链接的行为
path, 使用--link始终推荐。的性能--link是
等同或优于默认行为,并且,它创建的
缓存重用的条件。
复制 --parents
注意
目前尚不支持稳定的语法,请使用
docker/dockerfile:1.7-labs版本。
COPY [--parents[=<boolean>]] <src> ... <dest>这--parentsflag 保留父目录src条目。此标志默认为false.
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY ./x/a.txt ./y/a.txt /no_parents/
COPY --parents ./x/a.txt ./y/a.txt /parents/
# /no_parents/a.txt
# /parents/x/a.txt
# /parents/y/a.txt此行为类似于Linux的cp实用程序的
--parents或rsync --relative旗。
与 Rsync 一样,可以限制哪些父目录由
插入点和斜杠 (./) 添加到源路径中。如果存在此类点,则只有 parent
目录。这可能是阶段之间特别有用的副本
跟--from其中源路径必须是绝对的。
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY --parents ./x/./y/*.txt /parents/
# Build context:
# ./x/y/a.txt
# ./x/y/b.txt
#
# Output:
# /parents/y/a.txt
# /parents/y/b.txt请注意,如果没有--parentsflag 指定,则任何文件名冲突都将
使 Linux 失败cp带有明确错误消息的作
(cp: will not overwrite just-created './x/a.txt' with './y/a.txt'),其中
Buildkit 将静默覆盖目标处的目标文件。
虽然可以保留COPY指令仅包含一个srcentry,通常更有利
以使结果镜像中的图层计数尽可能低。因此
使用--parents标志,则 Buildkit 能够打包多个COPY说明中,保持目录结构不变。
复制 --exclude
注意
目前尚不支持稳定的语法,请使用
docker/dockerfile:1.7-labs版本。
COPY [--exclude=<path> ...] <src> ... <dest>这--excludeflag 允许您指定要排除的文件的路径表达式。
path 表达式遵循与<src>,
支持通配符和使用 Go 的 filepath 进行匹配。匹配规则。
例如,要添加所有以 “hom” 开头的文件,不包括.txt外延:
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY --exclude=*.txt hom* /mydir/您可以指定--exclude选项的多次COPY指令。
倍数--excludes是与其模式匹配的文件,不会被复制,
即使文件路径与<src>.
添加所有以 “hom” 开头的文件,不包括.txt或.md扩展:
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY --exclude=*.txt --exclude=*.md hom* /mydir/入口点
一ENTRYPOINT允许您配置将作为可执行文件运行的容器。
ENTRYPOINT有两种可能的形式:
exec 表单,这是首选表单:
ENTRYPOINT ["executable", "param1", "param2"]壳体形式:
ENTRYPOINT command param1 param2
有关不同表单的更多信息,请参阅 Shell 和 exec 表单。
以下命令从nginx替换为其默认值
内容, 侦听端口 80:
$ docker run -i -t --rm -p 80:80 nginx
命令行参数设置为docker run <image>将附加在
Exec 表单中的元素ENTRYPOINT,并将覆盖所有指定的元素
用CMD.
这允许将参数传递给入口点,即docker run <image> -d将传递-d参数添加到入口点。您可以覆盖
这ENTRYPOINT指令中使用docker run --entrypoint旗。
的 shell 形式ENTRYPOINT防止任何CMD命令行参数
被利用。它还会启动ENTRYPOINT作为/bin/sh -c,
它不传递信号。这意味着可执行文件不会是
容器的PID 1,并且不会接收 Unix 信号。在这种情况下,您的
可执行文件不会收到SIGTERM从docker stop <container>.
只有最后一个ENTRYPOINT指令将产生影响。
Exec 表单 ENTRYPOINT 示例
您可以使用 exec 形式的ENTRYPOINT设置相当稳定的默认命令
和参数,然后使用CMD要设置其他默认值,则
更有可能被更改。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]当您运行容器时,您可以看到top是唯一的进程:
$ docker run -it --rm --name test top -H
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
要进一步检查结果,您可以使用docker exec:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
您可以优雅地请求top使用docker stop test.
以下 Dockerfile 显示了如何使用ENTRYPOINT要在
foreground (即 asPID 1):
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]如果需要为单个可执行文件编写启动脚本,则可以确保
最终的可执行文件通过使用exec和gosu命令:
#!/usr/bin/env bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"最后,如果您需要进行一些额外的清理(或与其他容器通信)
在关闭时,或者正在协调多个可执行文件时,您可能需要确保
该ENTRYPOINTscript 接收 Unix 信号,传递它们,然后
执行更多工作:
#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too
# USE the trap if you need to also do manual cleanup after the service is stopped,
# or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM
# start service in background here
/usr/sbin/apachectl start
echo "[hit enter key to exit] or run 'docker stop <container>'"
read
# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop
echo "exited $0"如果您使用docker run -it --rm -p 80:80 --name test apache,
然后,您可以使用docker exec或docker top,
然后要求脚本停止 Apache:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
$ docker top test
PID USER COMMAND
10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2
10054 root /usr/sbin/apache2 -k start
10055 33 /usr/sbin/apache2 -k start
10056 33 /usr/sbin/apache2 -k start
$ /usr/bin/time docker stop test
test
real 0m 0.27s
user 0m 0.03s
sys 0m 0.03s
注意
您可以覆盖
ENTRYPOINT设置 using--entrypoint, 但这只能将Binaries设置为 exec (否sh -c将被使用)。
Shell 表单 ENTRYPOINT 示例
您可以为ENTRYPOINT它将在/bin/sh -c.
此表单将使用 shell 处理来替换 shell 环境变量,
,并将忽略任何CMD或docker run命令行参数。
要确保docker stop将向任何长时间运行的ENTRYPOINT可执行
正确地,您需要记住以exec:
FROM ubuntu
ENTRYPOINT exec top -b运行此镜像时,您将看到单个PID 1过程:
$ docker run -it --rm --name test top
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
Load average: 0.08 0.03 0.05 2/98 6
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root R 3164 0% 0% top -b
它干净地退出docker stop:
$ /usr/bin/time docker stop test
test
real 0m 0.20s
user 0m 0.02s
sys 0m 0.04s
如果您忘记添加exec拖动到ENTRYPOINT:
FROM ubuntu
ENTRYPOINT top -b
CMD -- --ignored-param1然后,您可以运行它(为下一步命名):
$ docker run -it --name test top --ignored-param2
top - 13:58:24 up 17 min, 0 users, load average: 0.00, 0.00, 0.00
Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 16.7 us, 33.3 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1990.8 total, 1354.6 free, 231.4 used, 404.7 buff/cache
MiB Swap: 1024.0 total, 1024.0 free, 0.0 used. 1639.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 2612 604 536 S 0.0 0.0 0:00.02 sh
6 root 20 0 5956 3188 2768 R 0.0 0.2 0:00.00 top
您可以从top指定的ENTRYPOINT莫PID 1.
如果随后运行docker stop test,容器将无法干净地退出 - 该stop命令将被迫发送SIGKILL超时后:
$ docker exec -it test ps waux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.4 0.0 2612 604 pts/0 Ss+ 13:58 0:00 /bin/sh -c top -b --ignored-param2
root 6 0.0 0.1 5956 3188 pts/0 S+ 13:58 0:00 top -b
root 7 0.0 0.1 5884 2816 pts/1 Rs+ 13:58 0:00 ps waux
$ /usr/bin/time docker stop test
test
real 0m 10.19s
user 0m 0.04s
sys 0m 0.03s
了解 CMD 和 ENTRYPOINT 如何交互
双CMD和ENTRYPOINT指令定义在运行容器时执行什么命令。
很少有规则可以描述他们的合作。
Dockerfile 应至少指定
CMD或ENTRYPOINT命令。ENTRYPOINT在将容器用作可执行文件时,应定义该容器。CMD应该用作定义ENTRYPOINT命令 或用于在容器中执行临时命令。CMD将在使用替代参数运行容器时被覆盖。
下表显示了针对不同的ENTRYPOINT / CMD组合:
| 无 ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | 入口点 [“exec_entry”, “p1_entry”] | |
|---|---|---|---|
| 无 CMD | 错误,不允许 | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
| CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_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_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
注意
如果
CMD从基础镜像定义,则设置ENTRYPOINT将 重置CMD设置为空值。在此方案中,CMD必须在 current image 的值。
卷
VOLUME ["/data"]这VOLUME指令会创建一个具有指定名称的挂载点
并将其标记为保存来自本机主机或其他
器皿。该值可以是 JSON 数组,VOLUME ["/var/log/"]或普通
string 中具有多个参数,例如VOLUME /var/log或VOLUME /var/log /var/db.有关更多信息/示例和安装说明,请通过
Docker 客户端,请参阅通过 Volumes 共享目录文档。
这docker run命令使用任何数据初始化新创建的卷
位于基础镜像中的指定位置。例如
请考虑以下 Dockerfile 代码段:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol此 Dockerfile 会生成一个镜像,该镜像会导致docker run自
在 以下位置创建新的挂载点/myvol并复制greeting文件
到新创建的卷中。
有关指定卷的注意事项
请记住以下有关 Dockerfile 中的卷的事项。
基于 Windows 的容器上的卷:使用基于 Windows 的容器时, 容器内卷的目的地必须是以下之一:
- 不存在或空的目录
- 除
C:
从 Dockerfile 中更改卷:如果任何构建步骤更改了 data 后,这些更改将被丢弃 使用旧版构建器时。使用 Buildkit 时,将保留更改。
JSON 格式:列表解析为 JSON 数组。 您必须用双引号 () 而不是单引号 () 将单词括起来。
"'主机目录在容器运行时声明:主机目录 (挂载点) 本质上依赖于主机。这是为了保留镜像 可移植性,因为无法保证给定的主机目录可用 在所有主机上。因此,您无法从 在 Dockerfile 中。这
VOLUME指令不支持指定host-dir参数。您必须在创建或运行容器时指定挂载点。
用户
USER <user>[:<group>]或
USER <UID>[:<GID>]这USER指令设置用户名(或 UID)和用户(可选)
group(或 GID)作为
当前阶段。指定的用户用于RUNinstructions 和 at
runtime 运行相关的ENTRYPOINT和CMD命令。
请注意,在为用户指定组时,用户将只有 指定的组成员身份。任何其他已配置的组成员资格都将被忽略。
警告
当用户没有主组时,镜像(或下一个 说明)将与
root群。在 Windows 上,如果用户不是内置帐户,则必须先创建用户。 这可以通过
net user命令作为 Dockerfile 的一部分调用。
FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrickWORKDIR (工作目录)
WORKDIR /path/to/workdir这WORKDIR指令为任何RUN,CMD,ENTRYPOINT,COPY和ADD说明。
如果WORKDIR不存在,则即使它未在任何
后续的 Dockerfile 指令。
这WORKDIR指令可以在 Dockerfile 中多次使用。如果
relative path 时,它将相对于上一个WORKDIR指令。例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd最终pwdcommand 将是/a/b/c.
这WORKDIR指令可以解析先前使用ENV.您只能使用在 Dockerfile 中显式设置的环境变量。
例如:
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd最终pwdcommand 将是/path/$DIRNAME
如果未指定,则默认工作目录为 。在实践中,如果您不是从头开始构建 Dockerfile (/FROM scratch),
这WORKDIR可能由您正在使用的基本镜像设置。
因此,为避免在未知目录中执行意外作,最佳实践是将WORKDIR明确地。
精 氨 酸
ARG <name>[=<default value>] [<name>[=<default value>]...]这ARGinstruction 定义了一个变量,用户可以在构建时传递给该变量
具有docker build命令使用--build-arg <varname>=<value>旗。
警告
不建议使用构建参数来传递密钥,例如 用户凭证、API 令牌等。Build 参数在
docker history命令和max模式出处证明, 如果您使用 Buildx GitHub Actions,则默认附加到镜像 并且您的 GitHub 仓库是公共的。请参阅
RUN --mount=type=secret部分设置为 了解在构建镜像时使用密钥的安全方法。
一个 Dockerfile 可以包含一个或多个ARG指示。例如
以下是有效的 Dockerfile:
FROM busybox
ARG user1
ARG buildno
# ...默认值
一ARGinstruction 可以选择包含默认值:
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...如果ARGinstruction 具有默认值,如果未传递值
在构建时,构建器使用默认值。
范围
一ARGvariable 从声明它的行开始生效
Dockerfile 中。例如,请考虑以下 Dockerfile:
FROM busybox
USER ${username:-some_user}
ARG username
USER $username
# ...用户通过调用来构建此文件:
$ docker build --build-arg username=what_user .
- 这
USER指令的计算结果为some_user后备 因为usernamevariable 尚未声明。 - 这
usernamevariable 在第 3 行声明,并可在 Dockerfile 指令。 - 这
USER第 4 行的 instruction 的计算结果为what_user,因为在那时 将username参数的值为what_user这被传递了 命令行。在它由ARGinstruction、任何对 变量会导致空字符串。
一ARG在构建阶段中声明的变量会自动由
其他阶段基于该阶段。不相关的构建阶段无权访问
变量。要在多个不同的阶段中使用参数,每个阶段都必须
包括ARG指令,或者它们都必须基于共享基础
阶段。
有关更多信息,请参阅 变量范围.
使用 ARG 变量
您可以使用ARG或ENV指令来指定
available to 的RUN指令。使用ENV指令始终覆盖ARG同名指令。考虑
这个 Dockerfile 带有一个ENV和ARG指令。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER然后,假设此镜像是使用以下命令构建的:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .
在这种情况下,RUN指令用途v1.0.0而不是ARG设置
由用户传递:v2.0.1此行为类似于 shell
脚本,其中本地范围的变量会覆盖作为
参数或从 environment 继承,从其定义点。
使用上面的示例,但使用不同的ENV您可以创建更多
之间的有用交互ARG和ENV指示:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER与ARG指令ENV值始终保留在构建的
镜像。考虑一个没有--build-arg旗:
$ docker build .
使用此 Dockerfile 示例,CONT_IMG_VER仍保留在镜像中,但
其值为v1.0.0因为它是第 3 行中由ENV指令。
此示例中的变量扩展技术允许您传递参数
并从命令行中将它们持久化在最终镜像中,方法是利用ENV指令。仅一组有限的
Dockerfile 说明。
预定义的 ARG
Docker 有一组预定义的ARG变量,您可以在没有
相应ARG指令。
HTTP_PROXYhttp_proxyHTTPS_PROXYhttps_proxyFTP_PROXYftp_proxyNO_PROXYno_proxyALL_PROXYall_proxy
要使用这些,请在命令行中使用--build-argflag, 用于
例:
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
默认情况下,这些预定义变量从docker history.排除它们可降低意外泄漏的风险
敏感身份验证信息在HTTP_PROXY变量。
例如,考虑使用--build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com
FROM ubuntu
RUN echo "Hello World"在这种情况下,HTTP_PROXY变量在docker history,并且不会缓存。如果您要更改位置,并且您的
代理服务器已更改为http://user:pass@proxy.sfo.example.com,则后续的
build 不会导致缓存未命中。
如果您需要覆盖此行为,则可以通过在ARG语句,如下所示:
FROM ubuntu
ARG HTTP_PROXY
RUN echo "Hello World"在构建此 Dockerfile 时,HTTP_PROXY保留在docker history,更改其值会使构建缓存失效。
全球范围内的自动平台 ARG
此功能仅在使用 BuildKit 后端时可用。
BuildKit 支持一组预定义的ARG变量,其平台上的信息为
执行构建的节点 (Build Platform) 和
生成的镜像 (Target Platform)。目标平台可以使用
这--platform标记docker build.
以下内容ARG变量是自动设置的:
TARGETPLATFORM- 构建结果的平台。例如linux/amd64,linux/arm/v7,windows/amd64.TARGETOS- TARGETPLATFORM 的 OS 组件TARGETARCH- TARGETPLATFORM 的架构组件TARGETVARIANT- TARGETPLATFORM 的 variant 组件BUILDPLATFORM- platform 执行构建的节点。BUILDOS- BUILDPLATFORM 的 OS 组件BUILDARCH- BUILDPLATFORM 的架构组件BUILDVARIANT- BUILDPLATFORM 的 variant 组件
这些参数是在全局范围内定义的,因此不会自动
可在构建阶段内使用,或用于您的RUN命令。要公开其中之一
构建阶段中的这些参数重新定义了它,但没有价值。
例如:
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"BuildKit 内置构建参数
| 精 氨 酸 | 类型 | 描述 |
|---|---|---|
BUILDKIT_CACHE_MOUNT_NS | 字符串 | 设置可选的缓存 ID 命名空间。 |
BUILDKIT_CONTEXT_KEEP_GIT_DIR | 布尔 | 触发 Git 上下文以保留.git目录。 |
BUILDKIT_INLINE_CACHE2 | 布尔 | 是否将缓存元数据内联到镜像配置。 |
BUILDKIT_MULTI_PLATFORM | 布尔 | 选择确定性输出,无论是否多平台输出。 |
BUILDKIT_SANDBOX_HOSTNAME | 字符串 | 设置主机名(默认buildkitsandbox) |
BUILDKIT_SYNTAX | 字符串 | 设置前端镜像 |
SOURCE_DATE_EPOCH | Int (整数) | 为创建的镜像和图层设置 Unix 时间戳。来自 Reroducible Builds 的更多信息。从 Dockerfile 1.5、BuildKit 0.11 开始支持 |
示例:keep.git迪尔
使用 Git 上下文时,.gitdir 不会保留在检出中。可以是
如果您想在
您的版本:
# syntax=docker/dockerfile:1
FROM alpine
WORKDIR /src
RUN --mount=target=. \
make REVISION=$(git rev-parse HEAD) build$ docker build --build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 https://github.com/user/repo.git#main
对构建缓存的影响
ARG变量不会作为ENV变量是。
然而ARG变量确实以类似的方式影响构建缓存。如果
Dockerfile 定义了一个ARG值与上一个
build 的 build 中,则 “cache miss” 发生在它第一次使用时,而不是它的定义上。在
particular、allRUN说明ARG指令使用ARG变量(作为环境变量),因此可能会导致缓存未命中。
全部预定义ARG变量免于缓存,除非存在
匹配ARG语句。
例如,考虑以下两个 Dockerfile:
FROM ubuntu
ARG CONT_IMG_VER
RUN echo $CONT_IMG_VERFROM ubuntu
ARG CONT_IMG_VER
RUN echo hello如果指定--build-arg CONT_IMG_VER=<value>在命令行中,在
的情况下,第 2 行的规范不会导致缓存未命中;3 号线
导致缓存未命中。ARG CONT_IMG_VER导致RUN待识别的线路
与运行CONT_IMG_VER=<value> echo hello,因此如果<value>changes,则会收到缓存未命中。
考虑同一命令行下的另一个示例:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=$CONT_IMG_VER
RUN echo $CONT_IMG_VER在此示例中,缓存未命中发生在第 3 行。发生错过是因为
变量在ENV引用ARG变量,并且
变量通过命令行进行更改。在此示例中,ENV命令使镜像包含该值。
如果ENV指令会覆盖ARG指令,如
这个 Dockerfile:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=hello
RUN echo $CONT_IMG_VER第 3 行不会导致缓存未命中,因为CONT_IMG_VER是一个
常数 (hello).因此,在
这RUN(第 4 行)在 build 之间不会更改。
构建
ONBUILD <INSTRUCTION>这ONBUILD指令向镜像添加一个触发指令
在以后执行,当镜像用作
另一个版本。触发器将在
downstream build 的 API API 的 API API 的 API 中,就好像它是在FROM指令。
如果您正在构建将用作基础的镜像,这将非常有用 要构建其他镜像,例如应用程序构建环境或 守护进程,该守护进程可以使用用户特定的配置进行自定义。
例如,如果您的镜像是可重用的 Python 应用程序构建器,则
将要求将应用程序源代码添加到特定的
目录中,并且可能需要在
那。你不能只打电话ADD和RUN现在,因为你还没有
可以访问应用程序源代码,并且
每个应用程序构建。您可以简单地为应用程序开发人员提供
使用样板 Dockerfile 复制粘贴到他们的应用程序中,但
这效率低下、容易出错且难以更新,因为它
与特定于应用程序的代码混合。
解决方案是使用ONBUILD将预先指示登记到
稍后在下一个构建阶段运行。
以下是它的工作原理:
- 当它遇到
ONBUILD指令中,构建器会添加一个 trigger 添加到正在构建的镜像的元数据中。指令 不会影响当前版本。 - 在构建结束时,所有触发器的列表都存储在
image manifest 中,在 key
OnBuild.它们可以使用 这docker inspect命令。 - 稍后,该镜像可以用作新版本的基础,使用
FROM指令。作为处理FROM指令 下游生成器查找ONBUILD触发器并执行 他们按照他们注册的顺序。如果任何触发器 fail 时,该FROM指令中止,这反过来又会导致 构建失败。如果所有触发器都成功,则FROM指令 完成,构建会照常继续。 - 触发器在执行后会从最终镜像中清除。在 换句话说,它们不会被 “grand-children” 构建继承。
例如,您可以添加如下内容:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src从舞台、镜像或上下文复制或装载
从 Dockerfile 语法 1.11 开始,您可以使用ONBUILD带有复制的指示
或者从其他阶段、镜像或构建上下文中挂载文件。例如:
# syntax=docker/dockerfile:1.11
FROM alpine AS baseimage
ONBUILD COPY --from=build /usr/bin/app /app
ONBUILD RUN --mount=from=config,target=/opt/appconfig ...如果from是构建阶段,则必须在
Dockerfile,其中ONBUILD触发。如果它是一个命名上下文,则
context 必须传递给下游构建。
ONBUILD 限制
- 链接
ONBUILD使用ONBUILD ONBUILD不允许。 - 这
ONBUILD指令可能无法触发FROM或MAINTAINER指示。
停止信号
STOPSIGNAL signal这STOPSIGNAL指令设置将发送到
容器退出。此信号可以是格式为SIG<NAME>,
例如SIGKILL或与
内核的 syscall 表,例如9.默认值为SIGTERM如果不是
定义。
可以使用--stop-signal标记docker run和docker create.
健康检查
这HEALTHCHECK指令有两种形式:
HEALTHCHECK [OPTIONS] CMD command(通过在容器内运行命令来检查容器运行状况)HEALTHCHECK NONE(禁用从基础镜像继承的任何运行状况检查)
这HEALTHCHECK指令告诉 Docker 如何测试容器以检查
它仍然有效。这可以检测 Web 服务器卡在
无限循环,并且无法处理新连接,即使服务器
进程仍在运行。
当容器指定了 healthcheck 时,它的 health status 为
添加到其正常状态中。此状态最初为starting.每当
运行状况检查通过,它将变为healthy(无论它以前处于什么状态)。
在一定数量的连续失败后,它变为unhealthy.
之前可以显示的选项CMD是:
--interval=DURATION(默认:30s)--timeout=DURATION(默认:30s)--start-period=DURATION(默认:0s)--start-interval=DURATION(默认:5s)--retries=N(默认:3)
运行状况检查将在容器 started,然后在前面的每个检查完成后再次间隔秒。
如果单次运行检查的时间超过超时秒数,则检查 被视为失败。
它需要重试容器的运行状况检查的连续失败
待考虑unhealthy.
Start Period 为需要时间引导的容器提供初始化时间。 在此期间的探测失败将不计入最大重试次数。 但是,如果在启动期间运行状况检查成功,则会考虑该容器 started 和所有连续失败都将计入最大重试次数。
Start interval (启动间隔) 是启动期间运行状况检查之间的时间。 此选项需要 Docker Engine 版本 25.0 或更高版本。
只能有一个HEALTHCHECK指令。如果您列出
多于一个,然后只使用最后一个HEALTHCHECK将生效。
命令位于CMDkeyword 可以是 shell 命令(例如HEALTHCHECK CMD /bin/check-running) 或 exec 数组(与其他 Dockerfile 命令一样;
参见 e.g.ENTRYPOINT了解详情)。
命令的 exit status 指示容器的运行状况。 可能的值为:
- 0:成功 - 容器运行状况良好,可供使用
- 1:运行状况不佳 - 容器无法正常工作
- 2:保留 - 不要使用此退出代码
例如,每隔 5 分钟左右检查一次 Web 服务器是否能够 在 3 秒内提供网站的主页:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1为了帮助调试失败的探测器,命令写入的任何输出文本(UTF-8 编码)
on stdout 或 stderr 将存储在 health 状态中,并且可以使用docker inspect.此类输出应保持简短(仅前 4096 字节
当前存储)。
当容器的运行状况发生变化时,会有一个health_statusevent 为
以新状态生成。
壳
SHELL ["executable", "parameters"]这SHELL指令允许用于 shell 形式的默认 shell
命令。Linux 上的默认 shell 是["/bin/sh", "-c"],然后打开
Windows 是["cmd", "/S", "/C"].这SHELL指令必须以 JSON 编写
表单。
这SHELL指令在 Windows 上特别有用,因为
两种常用且完全不同的原生 shell:cmd和powershell如
以及可用的替代外壳,包括sh.
这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指令时,
它们的 shell 形式用于 Dockerfile:RUN,CMD和ENTRYPOINT.
以下示例是在 Windows 上找到的常见模式,它可以是
使用SHELL指令:
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"构建器调用的命令将是:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"这效率低下,原因有两个。首先,有一个不必要的cmd.exe正在调用的命令处理器(又名 shell)。二、RUN指令
shell 表单需要一个额外的powershell -command前缀命令。
为了提高这一效率,可以采用两种机制之一。一是
使用 JSON 格式的RUN命令,例如:
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]虽然 JSON 表单是明确的,并且不使用不必要的cmd.exe,
它确实需要通过双引号和转义来更加冗长。替代
机制是使用SHELL指令和 shell 形式,
为 Windows 用户提供更自然的语法,尤其是与
这escapeparser 指令:
# escape=`
FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'结果:
PS E:\myproject> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
---> Running in 6fcdb6855ae2
---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
---> Running in d0eef8386e97
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/28/2016 11:26 AM Example
---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
---> Running in be6d8e63fe75
hello world
---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\myproject>
这SHELL指令也可以用于修改
shell 运行。例如,使用SHELL cmd /S /C /V:ON|OFF在 Windows 上,延迟
环境变量扩展语义可以修改。
这SHELL指令也可以在 Linux 上使用,如果备用 shell 是
必需,例如zsh,csh,tcsh和其他。
Here-文档
Here-documents 允许将后续 Dockerfile 行重定向到RUN或COPY命令。如果此类命令包含 here-document,则 Dockerfile 会考虑下一行,直到该行仅包含
here-doc 分隔符作为同一命令的一部分。
示例:运行多行脚本
# syntax=docker/dockerfile:1
FROM debian
RUN <<EOT bash
set -ex
apt-get update
apt-get install -y vim
EOT如果命令仅包含 here-document,则其内容将使用 默认 shell。
# syntax=docker/dockerfile:1
FROM debian
RUN <<EOT
mkdir -p foo/bar
EOT或者,shebang 标头可用于定义解释器。
# syntax=docker/dockerfile:1
FROM python:3.6
RUN <<EOT
#!/usr/bin/env python
print("hello world")
EOT更复杂的示例可能会使用多个 here-documents。
# syntax=docker/dockerfile:1
FROM alpine
RUN <<FILE1 cat > file1 && <<FILE2 cat > file2
I am
first
FILE1
I am
second
FILE2示例:创建内嵌文件
跟COPY说明,您可以将 source 参数替换为 here-doc
指示符将 here-document 的内容直接写入文件。这
以下示例创建一个greeting.txt包含hello world用
一个COPY指令。
# syntax=docker/dockerfile:1
FROM alpine
COPY <<EOF greeting.txt
hello world
EOF常规的 here-doc 变量扩展和 Tab 键剥离规则适用。
以下示例显示了一个小型 Dockerfile,它创建了一个hello.sh脚本
文件使用COPY带有 here 文档的 instructions 来执行。
# syntax=docker/dockerfile:1
FROM alpine
ARG FOO=bar
COPY <<-EOT /script.sh
echo "hello ${FOO}"
EOT
ENTRYPOINT ash /script.sh在这种情况下,文件脚本会打印 “hello bar”,因为变量已展开
当COPY指令被执行。
$ docker build -t heredoc .
$ docker run heredoc
hello bar
如果你要引用 here-document 单词的任何部分EOT这
变量在构建时不会展开。
# syntax=docker/dockerfile:1
FROM alpine
ARG FOO=bar
COPY <<-"EOT" /script.sh
echo "hello ${FOO}"
EOT
ENTRYPOINT ash /script.sh请注意,ARG FOO=bar在这里是多余的,可以删除。变量
在运行时调用脚本时进行解释:
$ docker build -t heredoc .
$ docker run -e FOO=world heredoc
hello world
Dockerfile 示例
有关 Dockerfile 的示例,请参阅: