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 中。该指令指定 base
您来自的图片
建筑。 只能有一个或多个指令,这些指令
声明在 Dockerfile 中的行中使用的参数。FROM
FROM
ARG
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 中。
解析器指令键(例如 or )不区分大小写,但
按照惯例,它们是小写的。指令的值区分大小写,并且
必须以指令的适当大小写编写。例如,是无效的,因为校验名称必须使用
帕斯卡大小写,而不是小写。通常包含空行
遵循任何 parser 指令。不支持换行符
in parser 指令。syntax
check
#check=skip=jsonargsrecommended
由于这些规则,以下示例都是无效的:
由于换行而无效:
# direc \
tive=value
由于出现两次而无效:
# directive=value1
# directive=value2
FROM ImageName
被视为注释,因为它出现在 builder 指令之后:
FROM ImageName
# directive=value
被视为注释,因为它出现在不是解析器的注释之后 命令:
# About my dockerfile
# directive=value
FROM ImageName
以下内容被视为注释,因为它不是
认可。已知指令被视为注释,因为它
显示在不是解析器指令的 Comment 之后。unknowndirective
syntax
# unknowndirective=value
# syntax=value
parser 指令中允许使用非换行空格。因此, 以下行的处理方式相同:
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
语法
使用 parser 指令将 Dockerfile 语法 version 声明为
用于构建。如果未指定,则 BuildKit 使用
Dockerfile 前端。声明语法 version 后,您可以自动使用
最新的 Dockerfile 版本,而无需升级 BuildKit 或 Docker Engine,
甚至使用自定义 Dockerfile 实现。syntax
大多数用户希望将此解析器指令设置为 ,
这会导致 BuildKit 拉取 Dockerfile 的最新稳定版本
语法。docker/dockerfile:1
# syntax=docker/dockerfile:1
有关 parser 指令工作原理的更多信息,请参阅自定义 Dockerfile 语法。
逃
# escape=\
或
# escape=`
该指令设置用于转义
Dockerfile 文件。如果未指定,则默认转义字符为 .escape
\
转义字符既可用于转义行中的字符,也可用于
转义换行符。这允许 Dockerfile 指令
跨多行。请注意,无论解析器
directive 包含在 Dockerfile 中,则不会在
命令,行尾除外。escape
RUN
将转义字符设置为 在 上特别有用,其中 是目录路径分隔符。 是一致的
使用 Windows PowerShell。`
Windows
\
`
请考虑以下示例,该示例在
窗户。第二行末尾的第二个将被解释为
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>
上述方法的一种解决方案是将 和 用作指令的目标。然而,这种语法充其量只是令人困惑,因为它并非如此
对于 Windows 上的路径来说,这是自然的,最坏的情况是,由于并非所有命令都打开,因此容易出错
Windows 支持作为路径分隔符。/
COPY
dir
/
通过添加 parser 指令,以下 Dockerfile 成功成为
预期在 Windows 上对文件路径使用自然平台语义时:escape
# 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>
该指令用于配置如何评估 build 检查。默认情况下,将运行所有检查,并将失败视为
警告。check
您可以使用 .要指定
要跳过多个检查,请用逗号分隔它们:#check=skip=<check-name>
# check=skip=JSONArgsRecommended,StageNameCasing
要禁用所有检查,请使用 .#check=skip=all
默认情况下,生成检查失败的生成以零状态代码退出
尽管有警告。要使构建在出现警告时失败,请设置 .#check=error=true
# check=error=true
注意
当使用指令时,建议使用 option 将 Dockerfile 语法固定到特定版本。否则,您的 build 可能会 在将来的版本中添加新的检查时开始失败。
check
error=true
要组合 和 选项,请使用分号分隔
他们:skip
error
# check=skip=JSONArgsRecommended;error=true
要查看所有可用的检查,请参阅 构建检查参考.
请注意,可用的检查取决于 Dockerfile 语法版本。要使
确保您获得最新的检查,请使用 syntax
指令将 Dockerfile 语法版本指定为最新的稳定版
版本。
环境替换
环境变量(使用 ENV
语句声明)也可以是
在某些指令中用作变量,由
Dockerfile 文件。还处理转义以包含类似变量的语法
转换为语句。
环境变量在 Dockerfile 中用 或 表示。它们被等效地处理,并且
大括号语法通常用于解决变量名称中没有
空格,如 .$variable_name
${variable_name}
${foo}_bar
该语法还支持一些标准修饰符,如下所示:${variable_name}
bash
${variable:-word}
表示如果设置了 Job,则结果 将是该值。如果未设置,则将是结果。variable
variable
word
${variable:+word}
表示如果设置了 then 将为 result,否则结果为空字符串。variable
word
的预发布版本支持以下变量替换
Dockerfile 语法,当使用语法
指令中:# syntax=docker/dockerfile-upstream:master
${variable#pattern}
删除 FROM 的最短匹配项 , 从字符串的开头开始查找。pattern
variable
str=foobarbaz echo ${str#f*b} # arbaz
${variable##pattern}
删除 FROM 的最长匹配项 , 从字符串的开头开始查找。pattern
variable
str=foobarbaz echo ${str##f*b} # az
${variable%pattern}
删除 FROM 的最短匹配项 , 从字符串的末尾向后查找。pattern
variable
string=foobarbaz echo ${string%b*} # foobar
${variable%%pattern}
删除 FROM 的最长匹配项 , 从字符串的末尾向后查找。pattern
variable
string=foobarbaz echo ${string%%b*} # foo
${variable/pattern/replacement}
将 in 的第一个匹配项替换为pattern
variable
replacement
string=foobarbaz echo ${string/ba/fo} # fooforbaz
${variable//pattern/replacement}
将所有出现的 in 替换为pattern
variable
replacement
string=foobarbaz echo ${string//ba/fo} # fooforfoz
在所有情况下,可以是任何字符串,包括其他环境
变量。word
pattern
是匹配任何单个字符的 glob 模式
和任意数量的字符(包括零)。要匹配 literal 和 ,
使用反斜杠 escape: 和 .?
*
?
*
\?
\*
您可以通过在变量前添加 a 来转义整个变量名称:或 ,
例如,将分别转换为 和 Literals。\
\$foo
\${foo}
$foo
${foo}
示例(解析的表示显示在 之后):#
FROM busybox
ENV FOO=/bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux
环境变量由以下说明列表支持 Dockerfile 中:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
ONBUILD
(与上述支持的说明之一结合使用时)
您还可以将环境变量与 、 和 instructions 一起使用,但在这些情况下,变量替换由
命令 shell,而不是构建器。请注意,使用 exec 表单的说明
不要自动调用命令 shell。查看变量
替换。RUN
CMD
ENTRYPOINT
环境变量替换对每个变量使用相同的值 贯穿整个教学过程。更改变量的值只需要 effect 的 intent 的 intent请考虑以下示例:
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
- 的值变为
def
hello
- 的值变为
ghi
bye
.dockerignore 文件
您可以使用 file 从
构建上下文。有关更多信息,请参阅 .dockerignore 文件。.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 表单最适合用于指定
with 用于设置可在运行时覆盖的默认参数。为
有关更多信息,请参阅 ENTRYPOINT。ENTRYPOINT
CMD
变量替换
使用 exec 表单不会自动调用命令 shell。这意味着
正常的 shell 处理(例如变量替换)不会发生。
例如,不会处理 的变量替换。RUN [ "echo", "$HOME" ]
$HOME
如果您想要 shell 处理,请使用 shell 形式或执行 shell
直接使用 exec 表单,例如:.
当使用 exec 表单并直接执行 shell 时,就像
shell 形式,则是执行环境变量替换的 shell,
不是建筑商。RUN [ "sh", "-c", "echo $HOME" ]
反 斜线
在 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
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>]
该指令初始化一个新的构建阶段,并为后续
指示。因此,有效的 Dockerfile 必须以指令开头。
镜像可以是任何有效的镜像。FROM
FROM
ARG
是 Dockerfile 中可能位于之前的唯一指令。 请参阅了解 ARG 和 FROM 如何交互。FROM
FROM
可以在单个 Dockerfile 中多次出现,以 创建多个镜像或将一个构建阶段用作另一个构建阶段的依赖项。 只需在每个新指令之前记下提交输出的最后一个镜像 ID。每条指令都会清除上一个 指示。FROM
FROM
- (可选)可以通过添加到指令来为新的 build 阶段指定名称。该名称可以在后续的
COPY --from=<name>
中使用。 和RUN --mount=type=bind,from=<name>
指令 引用此阶段构建的镜像。AS name
FROM
FROM <name>
- or 值是可选的。如果省略其中任何一个,则
默认情况下,builder 会采用标记。如果 Builder 出现
找不到值。
tag
digest
latest
tag
可选标志可用于指定镜像的平台
in case 引用多平台镜像。例如, , , 或 .默认情况下,生成的目标平台
request 的 API 请求。全局构建参数可以在此标志的值中使用,
例如,自动平台 ARG 允许您强制将阶段转换为本机构建平台 (),
并使用它交叉编译到 stage 内的目标平台。--platform
FROM
linux/amd64
linux/arm64
windows/amd64
--platform=$BUILDPLATFORM
了解 ARG 和 FROM 如何交互
FROM
instructions 支持由第一个 .ARG
FROM
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
在 a 之前声明的 an 在构建阶段之外,因此它
不能在 .要使用默认值
an 在第一次使用没有
构建阶段中的值:ARG
FROM
FROM
ARG
FROM
ARG
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
跑
该指令将执行任何命令以在
当前镜像。添加的层将在 Dockerfile 的下一步中使用。 有两种形式:RUN
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 指令的缓存失效
指令的缓存不会在
下一个版本。指令 like 的缓存将在下一次构建期间重用。这
可以使用 flag 使 cache for instructions 失效,例如 .RUN
RUN apt-get dist-upgrade -y
RUN
--no-cache
docker build --no-cache
请参阅 Dockerfile 最佳实践 指南了解更多信息。
运行 --mount
RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]
RUN --mount
允许您创建构建可以访问的文件系统挂载。
这可用于:
- 创建绑定挂载到主机文件系统或其他构建阶段
- 访问构建密钥或 ssh-agent 套接字
- 使用持久性包管理缓存加快构建速度
支持的挂载类型包括:
类型 | 描述 |
---|---|
bind (默认) | 绑定挂载上下文目录(只读)。 |
cache | 挂载临时目录以缓存编译器和包管理器的目录。 |
tmpfs | 将 挂载到构建容器中。tmpfs |
secret | 允许构建容器访问私钥等安全文件,而无需将其烘焙到镜像或构建缓存中。 |
ssh | 允许构建容器通过 SSH 代理访问 SSH 密钥,并支持密码。 |
运行 --mount=type=bind
此挂载类型允许将文件或目录绑定到构建容器。一个 默认情况下,bind mount 是只读的。
选择 | 描述 |
---|---|
target , ,dst destination 1 | 挂载路径。 |
source | .默认为 的根 。from from |
from | 为源的根生成阶段、上下文或镜像名称。默认为 build 上下文。 |
rw ,readwrite | 允许在挂载上写入。写入的数据将被丢弃。 |
运行 --mount=type=cache
此挂载类型允许构建容器缓存编译器的目录 和包管理器。
选择 | 描述 |
---|---|
id | 用于标识单独/不同缓存的可选 ID。默认值为 。target |
target , ,dst destination 1 | 挂载路径。 |
ro ,readonly | 如果设置,则为 Read-only。 |
sharing | 、 或 之一。默认为 。一个缓存挂载可以被多个写入器同时使用。 如果有多个写入器,则创建一个新的挂载。 暂停第二个写入器,直到第一个写入器释放挂载。shared private locked shared shared 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 gcc
Apt 需要对其数据进行独占访问,因此缓存使用 option ,这将确保多个并行构建使用
相同的缓存挂载将相互等待,而不是访问相同的
cache 文件。你也可以使用 if
您更喜欢让每个构建在此
箱。sharing=locked
sharing=private
运行 --mount=type=tmpfs
此挂载类型允许在构建容器中挂载。tmpfs
选择 | 描述 |
---|---|
target , ,dst destination 1 | 挂载路径。 |
size | 指定文件系统大小的上限。 |
运行 --mount=type=secret
此挂载类型允许构建容器访问 secret 值,例如 令牌或私钥,而无需将它们烘焙到镜像中。
默认情况下,密钥作为文件挂载。您还可以将 secret 挂载为
环境变量。env
选择 | 描述 |
---|---|
id | 密钥的 ID。默认为目标路径的 basename 。 |
target , ,dst destination | 将密钥挂载到指定路径。如果未设置,则默认为 +,如果也未设置。/run/secrets/ id env |
env | 将密钥挂载到环境变量而不是文件,或同时挂载到两者。(自 Dockerfile v1.10.0 起) |
required | 如果设置为 ,则当密钥不可用时,指令会出错。默认为 。true 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 .
示例:作为环境变量挂载
以下示例采用密钥并将其挂载为
环境变量。API_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:API_KEY
$ 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 文件。*.pem
$SSH_AUTH_SOCK
运行 --network
RUN --network=<TYPE>
RUN --network
允许控制命令的联网环境
被磨合。
支持的网络类型包括:
运行 --network=default
相当于根本不提供标志,该命令在默认的 network 进行构建。
运行 --network=none
该命令在没有网络访问权限( 仍然可用,但
isolate to this process (隔离到此过程)lo
示例:隔离外部效果
# syntax=docker/dockerfile:1
FROM python:3.6
ADD mypackage.tgz wheels/
RUN --network=none pip install --find-links wheels mypackage
pip
将只能安装 tarfile 中提供的软件包,该软件包
可以由早期构建阶段控制。
运行 --network=host
该命令在主机的网络环境中运行(类似于 ,但基于每条指令)docker build --network=host
警告
的使用受权利保护, 当使用 flag 启动 buildkitd 守护进程或在 buildkitd 配置中启用时,需要启用它, 以及带有
--allow network.host
标志的构建请求。--network=host
network.host
--allow-insecure-entitlement network.host
运行 --security
注意
尚不可用稳定的语法,请使用
docker/dockerfile:1-labs
版本。
RUN --security=<sandbox|insecure>
默认安全模式为 。
使用 ,构建器在 insecure 中运行没有 sandbox 的命令
模式,允许运行需要提升权限的流(例如 containerd)。
这相当于运行 .sandbox
--security=insecure
docker run --privileged
警告
要访问此功能,授权应为 在使用 flag 启动 buildkitd 守护进程时或在 buildkitd 配置中启用, 以及带有
--allow security.insecure
标志的构建请求。security.insecure
--allow-insecure-entitlement security.insecure
默认沙盒模式可以通过 激活,但那是无操作。--security=sandbox
示例:检查权利
# syntax=docker/dockerfile:1-labs
FROM ubuntu
RUN --security=insecure cat /proc/self/status | grep CapEff
#84 0.093 CapEff: 0000003fffffffff
CMD
该指令设置在运行容器时要执行的命令
从镜像中。CMD
您可以使用 shell 或 exec 表单指定说明:CMD
CMD ["executable","param1","param2"]
(执行表单)CMD ["param1","param2"]
(exec 表单,作为ENTRYPOINT
)CMD command param1 param2
(壳体形式)
Dockerfile 中只能有一条指令。如果您列出的超过
one ,只有最后一个生效。CMD
CMD
a 的目的是为正在执行的容器提供默认值。这些
defaults 可以包含可执行文件,也可以省略可执行文件,其中
case 中,还必须指定一个指令。CMD
ENTRYPOINT
如果您希望容器每次都运行相同的可执行文件,则
您应该考虑与 结合使用。请参阅 ENTRYPOINT
。如果用户指定了参数,则他们将覆盖 中指定的默认值,但仍使用
违约。ENTRYPOINT
CMD
docker run
CMD
ENTRYPOINT
If 用于为指令提供默认参数,
AND 指令都应在 EXEC 表单中指定。CMD
ENTRYPOINT
CMD
ENTRYPOINT
注意
不要与 . 实际运行命令并提交 结果; 在构建时不执行任何内容,但指定 镜像的预期命令。
RUN
CMD
RUN
CMD
标签
LABEL <key>=<value> [<key>=<value>...]
该指令将元数据添加到镜像中。A 是
键值对。要在值中包含空格,请使用引号和
反斜杠,就像在命令行解析中所做的那样。一些使用示例:LABEL
LABEL
LABEL
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"
注意
请务必使用双引号,而不是单引号。特别是当您 使用字符串插值 (例如) , single quotes 将按原样获取字符串,而无需解压缩变量的值。
LABEL example="foo-$ENV_VAR"
基础镜像(行中的镜像)中包含的标签由
您的镜像。如果标签已存在但具有不同的值,则
最近应用的值将覆盖任何以前设置的值。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>
该指令设置生成镜像的 Author 字段。
该指令是 this 的更灵活的版本,您应该使用
相反,因为它可以设置您需要的任何元数据,并且可以查看
轻松,例如使用 .要设置与字段对应的标签,您可以使用:MAINTAINER
LABEL
docker inspect
MAINTAINER
LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"
然后,这将与其他标签一起可见。docker inspect
暴露
EXPOSE <port> [<port>/<protocol>...]
该指令通知 Docker 容器监听
在运行时指定网络端口。您可以指定端口是否侦听
TCP 或 UDP,如果您未指定协议,则默认为 TCP。EXPOSE
该指令实际上并未发布端口。它的功能是
构建镜像的人员与构建镜像的人员之间的文档类型
运行容器,了解要发布的端口。自
发布端口,使用标志 on 发布和映射一个或多个端口,或使用标志发布所有公开的
ports 并将它们映射到高阶 ports。EXPOSE
-p
docker run
-P
默认情况下,假定为 TCP。您还可以指定 UDP:EXPOSE
EXPOSE 80/udp
要在 TCP 和 UDP 上公开,请包含两行代码:
EXPOSE 80/tcp
EXPOSE 80/udp
在这种情况下,如果使用 ,则端口将公开一次
用于 TCP,一次用于 UDP。请记住,使用短暂的高序主机
端口,因此 TCP 和 UDP 不会使用相同的端口。-P
docker run
-P
无论设置如何,您都可以在运行时使用
国旗。例如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 实验室 |
该指令从中复制新文件或目录,并添加
它们到路径 .文件和目录
可以从构建上下文、远程 URL 或 Git 存储库中复制。ADD
<src>
<dest>
和 指令在功能上相似,但用途略有不同。
详细了解 ADD
和 COPY
之间的区别。ADD
COPY
源
您可以使用 指定多个源文件或目录。最后
argument 必须始终是 destination 。例如,要将两个文件 和 、 从 build 上下文添加到
生成容器:ADD
file1.txt
file2.txt
/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>
- 如果是本地 tar 存档,则会将其解压缩并提取到
指定的目标。请参阅添加本地 tar 存档。
<src>
- 如果是 URL,则下载 URL 的内容并将其放置在
指定的目标。请参阅从 URL 添加文件。
<src>
- 如果是 Git 存储库,则存储库将克隆到指定的
目的地。请参阅从 Git 存储库添加文件。
<src>
从构建上下文添加文件
任何不以 、 或 protocol 前缀开头的相对或本地路径都被视为本地文件路径。本地文件路径为
相对于 build 上下文。例如,如果构建上下文是当前的
目录中,将位于 的文件添加到
filesystem 中。http://
https://
git@
ADD file.txt /
./file.txt
从构建上下文添加源文件时,它们的路径被解释为
相对于上下文的根。如果指定相对路径前导
在构建上下文之外,例如 , parent
目录路径会自动剥离。中的 有效源路径
此示例变为 。ADD ../something /something
ADD something /something
如果源是目录,则复制该目录的内容, 包括 Filesystem 元数据。目录本身不会被复制,只会复制它的 内容。如果它包含子目录,则也会复制这些子目录,并与 目标上的任何现有目录。任何冲突都在 支持逐个文件添加的内容,除非您是 尝试将目录复制到现有文件上,在这种情况下,错误为 提出。
如果源是文件,则文件及其元数据将复制到 目的地。保留文件权限。如果源是文件且 目录,则会引发错误。
如果通过 stdin 将 Dockerfile 传递给 build (),则没有 build 上下文。在这种情况下,您只能使用该指令复制远程文件。您还可以通过
stdin: () 的 Dockerfile 位于
archive 和存档的其余部分将用作构建的上下文。docker build - < Dockerfile
ADD
docker build - < archive.tar
模式匹配
对于本地文件,每个文件都可能包含通配符,并且将进行匹配
使用 Go 的 filepath 。匹配规则。<src>
例如,要在构建上下文的根目录中添加所有文件和目录
以 结尾 :.png
ADD *.png /dest/
在以下示例中,是一个单字符通配符,匹配例如 和。?
index.js
index.ts
ADD index.?s /dest/
当添加包含特殊字符(如 和 )的文件或目录时,你需要按照 Golang 规则对这些路径进行转义,以防止
它们不再被视为匹配模式。例如,要添加文件
named ,使用以下命令;[
]
arr[0].txt
ADD arr[[]0].txt /dest/
添加本地 tar 存档
当使用本地 tar 存档作为 的源时,如果该存档位于
识别的压缩格式(、 、 或 未压缩 )时,
archive 将解压缩并提取到指定的目标中。只
提取本地 tar 档案。如果 tar 存档是远程 URL,则
存档不会提取,而是下载并放置在目标位置。ADD
gzip
bzip2
xz
提取目录时,它与 具有相同的行为。
结果是以下各项的并集:tar -x
- 目标路径中存在的任何内容,以及
- 源代码树的内容,冲突得到解决,有利于 逐个文件添加的内容。
注意
文件是否被识别为可识别的压缩格式是 仅根据文件的内容(而不是文件名)完成。为 示例,如果空文件恰好以 this 结尾,则无法识别 作为压缩文件,并且不会生成任何类型的解压缩错误 消息,而是简单地将文件复制到目标。
.tar.gz
从 URL 添加文件
如果 source 是远程文件 URL,则目标将具有
权限为 600。如果 HTTP 响应包含标头,则
timestamp 将用于设置目标
文件。但是,与在 期间处理的任何其他文件一样,, 不会
包含在确定文件是否已更改以及
cache 应该更新。Last-Modified
mtime
ADD
mtime
如果目标以尾部斜杠结尾,则推断文件名
从 URL 路径。例如,将创建
文件 .URL 必须具有重要的路径,以便适当的
filename ( 不起作用)。ADD http://example.com/foobar /
/foobar
http://example.com
如果目标不以尾部斜杠结尾,则目标路径
将成为从 URL 下载的文件的文件名。例如,创建文件 .ADD http://example.com/foo /bar
/bar
如果您的 URL 文件使用身份验证进行保护,则需要使用 ,或使用容器中的其他工具作为说明
不支持身份验证。RUN wget
RUN curl
ADD
从 Git 存储库添加文件
要使用 Git 存储库作为 的源,您可以引用
存储库的 HTTP 或 SSH 地址作为源。存储库将克隆到
指定的 destination 在镜像中。ADD
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,请将标志传递给 to mount
构建的 SSH 代理套接字。例如:--ssh
docker build
$ 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>
当 是远程 Git 仓库的 HTTP 或 SSH 地址时,
BuildKit 将 Git 存储库的内容添加到镜像中
默认情况下不包括目录。<src>
.git
该标志允许您保留目录。--keep-git-dir=true
.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>
该标志允许您验证远程资源的校验和。这
校验和的格式为 .支持的算法包括 、 和 。--checksum
<algorithm>:<hash>
sha256
sha384
sha512
ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz /
该标志仅支持 HTTP(S) 源。--checksum
添加 --chown --chmod
添加 --link
请参阅 COPY --link
。
添加 --exclude
请参阅 COPY --exclude
。
复制
COPY 有两种形式。 对于包含空格的路径,后一种形式是必需的。
COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]
可用的是:[OPTIONS]
该指令从中复制新文件或目录,并添加
它们到路径 .文件和目录
可以从 Build Context、Build Stage、named context 或镜像中复制。COPY
<src>
<dest>
和 指令在功能上相似,但用途略有不同。
详细了解 ADD
和 COPY
之间的区别。ADD
COPY
源
您可以使用 指定多个源文件或目录。最后
argument 必须始终是 destination 。例如,要将两个文件 和 、 从 build 上下文复制到
生成容器:COPY
file1.txt
file2.txt
/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
标志。
从构建上下文复制
从构建上下文复制源文件时,它们的路径被解释为
相对于上下文的根。如果指定相对路径前导
在构建上下文之外,例如 , parent
目录路径会自动剥离。中的 有效源路径
此示例变为 。COPY ../something /something
COPY something /something
如果源是目录,则复制该目录的内容, 包括 Filesystem 元数据。目录本身不会被复制,只会复制它的 内容。如果它包含子目录,则也会复制这些子目录,并与 目标上的任何现有目录。任何冲突都在 支持逐个文件添加的内容,除非您是 尝试将目录复制到现有文件上,在这种情况下,错误为 提出。
如果源是文件,则文件及其元数据将复制到 目的地。保留文件权限。如果源是文件且 目录,则会引发错误。
如果通过 stdin 将 Dockerfile 传递给 build (),则没有 build 上下文。在这种情况下,您只能使用该指令从其他阶段、命名上下文或镜像复制文件。
使用 --from
标志。您还可以传递 tar 存档
通过 stdin: () 获取位于
存档和存档的其余部分将用作
建。docker build - < Dockerfile
COPY
docker build - < archive.tar
当使用 Git 存储库作为构建上下文时,权限位 复制的文件为 644。如果存储库中的文件设置了可执行位,则 它将将 permissions 设置为 755。目录的权限设置为 755。
模式匹配
对于本地文件,每个文件都可能包含通配符,并且将进行匹配
使用 Go 的 filepath 。匹配规则。<src>
例如,要在构建上下文的根目录中添加所有文件和目录
以 结尾 :.png
COPY *.png /dest/
在以下示例中,是一个单字符通配符,匹配例如 和。?
index.js
index.ts
COPY index.?s /dest/
当添加包含特殊字符(如 和 )的文件或目录时,你需要按照 Golang 规则对这些路径进行转义,以防止
它们不再被视为匹配模式。例如,要添加文件
named ,使用以下命令;[
]
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
默认情况下,该指令从 build 上下文中复制文件。该标志允许您从镜像、构建阶段、
或命名上下文。COPY
COPY --from
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 /
也可以直接从命名上下文 (使用 指定) 或镜像复制文件。以下示例从 Nginx 官方镜像中复制一个文件。--build-context <name>=<source>
nginx.conf
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
的源路径始终从
Image 或 stage 中指定的 IMAGE 或 STAGE。COPY --from
复制 --chown --chmod
注意
目前仅支持八进制表示法。非八进制支持在 moby/buildkit#1951 中跟踪。
COPY [--chown=<user>:<group>] [--chmod=<perms> ...] <src> ... <dest>
和 功能仅在用于构建 Linux 容器的 Dockerfile 上受支持。
并且不适用于 Windows 容器。由于用户和组所有权概念确实如此
不在 Linux 和 Windows 之间转换,使用 和 for
将用户和组名称转换为 ID 会将此功能限制为仅适用于
基于 Linux 操作系统的容器。--chown
--chmod
/etc/passwd
/etc/group
从构建上下文复制的所有文件和目录都是使用 UID 和 GID 创建的,除非
optional 标志指定给定的用户名、组名或 UID/GID
组合以请求对复制内容的特定所有权。这
标志的格式允许使用 username 和 groupname 字符串
或直接整数 UID 和 GID 的任意组合。提供用户名,但不提供
groupname 或不带 GID 的 UID 将使用与 GID 相同的数字 UID。如果
username 或 groupname 时,将使用容器的根文件系统和文件来执行翻译
从 name 分别转换为整数 UID 或 GID。以下示例显示
标志的有效定义:0
--chown
--chown
/etc/passwd
/etc/group
--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/
如果容器根文件系统不包含 or 文件,并且在标志中使用了用户名或组名称,则构建将在操作中失败。使用数字 ID 需要
无需查找,并且不依赖于容器根文件系统内容。/etc/passwd
/etc/group
--chown
COPY
使用 Dockerfile 语法版本 1.10.0 及更高版本时,
该标志支持变量插值,
这允许您使用 build 参数定义权限位:--chmod
# syntax=docker/dockerfile:1.10
FROM alpine
WORKDIR /src
ARG MODE=440
COPY --chmod=$MODE . .
复制 --link
COPY [--link[=<boolean>]] <src> ... <dest>
在 or 命令中启用此标志允许您复制文件
增强的语义,其中文件在其自己的层上保持独立,并且
当先前层上的命令发生更改时,不会失效。COPY
ADD
使用 时,您的源文件将复制到空目标中
目录。该目录将转换为一个层,该层链接到
previous 状态。--link
# syntax=docker/dockerfile:1
FROM alpine
COPY --link /foo /bar
相当于执行两个构建:
FROM alpine
和
FROM scratch
COPY /foo /bar
并将两个镜像的所有图层合并在一起。
使用 --link
的好处
用于在后续构建中重用已构建的层,即使之前的层已更改。这一点尤其
对于多阶段构建很重要,其中 statement 会
如果同一阶段中的任何先前命令发生更改,则 previously 将失效,
导致需要再次重建中间阶段。使用
层被重用并合并到新的
层。这也意味着您可以在使用基础镜像时轻松变基镜像
接收更新,而无需再次执行整个构建。在后端
支持它,BuildKit 可以执行这个 rebase 操作,而无需推送或
拉取客户端和注册表之间的任何层。BuildKit 将检测到这一点
case 创建,并且仅创建包含新层和旧层的新镜像清单
图层。--link
--cache-from
COPY --from
--link
BuildKit 可以避免下拉基础镜像的相同行为也可以
当使用 且没有其他需要访问
基础镜像中的文件。在这种情况下,BuildKit 将仅构建层
对于这些命令,并将它们直接推送到注册表中的
图层。--link
COPY
与 --link=false
不兼容
使用命令时不允许读取任何文件
从上一个状态。这意味着,如果在先前的状态下,目标
directory 是一个包含符号链接的路径,不能跟随它。
在最终镜像中,创建的目标路径将始终为
path 中仅包含目录。--link
COPY/ADD
COPY/ADD
--link
如果您不依赖目标中以下符号链接的行为
path,则始终建议使用。的性能是
等同或优于默认行为,并且,它创建的
缓存重用的条件。--link
--link
复制 --parents
注意
尚不支持稳定语法,请使用
docker/dockerfile:1.7-labs
版本。
COPY [--parents[=<boolean>]] <src> ... <dest>
该标志保留条目的父目录。此标志默认为 .--parents
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
实用程序的 或 rsync
标志。--parents
--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
请注意,如果未指定标志,则任何文件名冲突都将
使 Linux 操作失败,并显示显式错误消息
(),其中
Buildkit 将静默覆盖目标处的目标文件。--parents
cp
cp: will not overwrite just-created './x/a.txt' with './y/a.txt'
虽然可以为仅包含一个条目的指令保留目录结构,但通常它更有益
以使结果镜像中的图层计数尽可能低。因此
使用该标志,Buildkit 能够将多个指令打包在一起,保持目录结构完整。COPY
src
--parents
COPY
复制 --exclude
注意
尚不支持稳定语法,请使用
docker/dockerfile:1.7-labs
版本。
COPY [--exclude=<path> ...] <src> ... <dest>
该标志允许您指定要排除的文件的路径表达式。--exclude
路径表达式遵循与 相同的格式 ,
支持通配符和使用 Go 的 filepath 进行匹配。匹配规则。
例如,要添加所有以 “hom” 开头的文件,不包括扩展名为 的文件:<src>
.txt
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY --exclude=*.txt hom* /mydir/
您可以为一条指令多次指定该选项。
Multiple 是与其模式匹配的文件,不被复制,
即使文件路径与 中指定的模式匹配。
要添加所有以 “hom” 开头的文件,不包括扩展名为 或 的文件:--exclude
COPY
--excludes
<src>
.txt
.md
# syntax=docker/dockerfile:1-labs
FROM scratch
COPY --exclude=*.txt --exclude=*.md hom* /mydir/
入口点
An 允许您配置将作为可执行文件运行的容器。ENTRYPOINT
ENTRYPOINT
有两种可能的形式:
exec 表单,这是首选表单:
ENTRYPOINT ["executable", "param1", "param2"]
壳体形式:
ENTRYPOINT command param1 param2
有关不同表单的更多信息,请参阅 Shell 和 exec 表单。
以下命令从具有默认
内容, 侦听端口 80:nginx
$ docker run -i -t --rm -p 80:80 nginx
命令行参数 to 将附加到
元素,并将覆盖所有指定的元素
用。docker run <image>
ENTRYPOINT
CMD
这允许将参数传递给入口点,即将参数传递给入口点。您可以覆盖
使用 flag.docker run <image> -d
-d
ENTRYPOINT
docker run --entrypoint
的 shell 形式阻止任何命令行参数
被利用。它还将 ur 作为 的子命令 ,
它不传递信号。这意味着可执行文件不会是
container的 ,并且不会接收 Unix 信号。在这种情况下,您的
可执行文件未收到 from .ENTRYPOINT
CMD
ENTRYPOINT
/bin/sh -c
PID 1
SIGTERM
docker stop <container>
只有 Dockerfile 中的最后一条指令才会生效。ENTRYPOINT
Exec 表单 ENTRYPOINT 示例
您可以使用 exec 形式 of 来设置相当稳定的默认命令
和参数,然后使用任一形式的 of 来设置额外的默认值,这些默认值
更有可能被更改。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 显示了使用 在
foreground (i.e., as ):ENTRYPOINT
PID 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"]
如果需要为单个可执行文件编写启动脚本,则可以确保
最终的可执行文件使用 and 命令接收 Unix 信号: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 "$@"
最后,如果您需要进行一些额外的清理(或与其他容器通信)
在关闭时,或者正在协调多个可执行文件时,您可能需要确保
脚本接收 Unix 信号,传递它们,然后
执行更多工作:ENTRYPOINT
#!/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"
如果使用 运行此镜像。
然后,您可以使用 、 或 、
然后要求脚本停止 Apache:docker run -it --rm -p 80:80 --name test apache
docker exec
docker top
$ 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
注意
您可以使用 覆盖设置 。 但这只能将二进制文件设置为 exec (不会使用 no)。
ENTRYPOINT
--entrypoint
sh -c
Shell 表单 ENTRYPOINT 示例
您可以为 指定一个纯字符串,它将在 中执行。
此表单将使用 shell 处理来替换 shell 环境变量,
并将忽略 any 或 命令行参数。
要确保这将向任何长时间运行的可执行文件发出信号
正确地,您需要记住以 :ENTRYPOINT
/bin/sh -c
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
从输出中可以看到,指定的 is not .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 如何交互
和 instructions 都定义了在运行容器时执行什么命令。
很少有规则可以描述他们的合作。CMD
ENTRYPOINT
Dockerfile 应至少指定一个 or 命令。
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 |
注意
如果从基础镜像定义,则设置将 reset 为空值。在这种情况下,必须在 current image 的值。
CMD
ENTRYPOINT
CMD
CMD
卷
VOLUME ["/data"]
该指令将创建一个具有指定名称的挂载点
并将其标记为保存来自本机主机或其他
器皿。该值可以是 JSON 数组、 或 plain
string 中具有多个参数,例如 or 。有关更多信息/示例和安装说明,请通过
Docker 客户端,请参阅通过 Volumes 共享目录文档。VOLUME
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
该命令使用任何数据初始化新创建的卷
位于基础镜像中的指定位置。例如
请考虑以下 Dockerfile 代码段:docker run
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>]
该指令设置用户名(或 UID)和用户(可选)
group(或 GID)作为
当前阶段。指定的用户用于说明,在
runtime 运行相关的 and 命令。USER
RUN
ENTRYPOINT
CMD
请注意,在为用户指定组时,用户将只有 指定的组成员身份。任何其他已配置的组成员资格都将被忽略。
警告
当用户没有主组时,镜像(或下一个 instructions) 将与该组一起运行。
root
在 Windows 上,如果用户不是内置帐户,则必须先创建用户。 这可以通过作为 Dockerfile 的一部分调用的命令来完成。
net user
FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrick
WORKDIR (工作目录)
WORKDIR /path/to/workdir
该指令为 Dockerfile 中遵循它的任何 、 、 和 指令设置工作目录。
如果 不存在,即使它未在任何
后续的 Dockerfile 指令。WORKDIR
RUN
CMD
ENTRYPOINT
COPY
ADD
WORKDIR
该指令可以在 Dockerfile 中多次使用。如果
relative path 时,它将相对于前一条指令的 path 。例如:WORKDIR
WORKDIR
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
此 Dockerfile 中最后一个命令的输出为 .pwd
/a/b/c
该指令可以解析以前使用 设置的环境变量。您只能使用在 Dockerfile 中显式设置的环境变量。
例如:WORKDIR
ENV
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
此 Dockerfile 中最终命令的输出为pwd
/path/$DIRNAME
如果未指定,则默认工作目录为 。在实践中,如果您不是从头开始构建 Dockerfile (),
这可能由您正在使用的基础镜像设置。/
FROM scratch
WORKDIR
因此,为避免在未知目录中进行意外操作,最佳做法是显式设置 your .WORKDIR
精 氨 酸
ARG <name>[=<default value>] [<name>[=<default value>]...]
该指令定义了一个变量,用户可以在构建时将其传递给
带有使用 flag.ARG
docker build
--build-arg <varname>=<value>
警告
不建议使用构建参数来传递密钥,例如 用户凭证、API 令牌等。构建参数在命令和模式出处证明中可见, 如果您使用 Buildx GitHub Actions,则默认附加到镜像 并且您的 GitHub 存储库是公共的。
docker history
max
请参阅
RUN --mount=type=secret
部分 了解在构建镜像时使用密钥的安全方法。
Dockerfile 可能包含一个或多个指令。例如
以下是有效的 Dockerfile:ARG
FROM busybox
ARG user1
ARG buildno
# ...
默认值
指令可以选择包含默认值:ARG
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
如果指令具有默认值,并且没有传递任何值
在构建时,构建器使用默认值。ARG
范围
变量从声明它的行开始生效
Dockerfile 中。例如,请考虑以下 Dockerfile:ARG
FROM busybox
USER ${username:-some_user}
ARG username
USER $username
# ...
用户通过调用来构建此文件:
$ docker build --build-arg username=what_user .
- 第 2 行的指令计算为回退
,因为该变量尚未声明。
USER
some_user
username
- 该变量在第 3 行声明,并可在
Dockerfile 指令。
username
- 第 4 行的指令计算结果为 ,因为在那
point 的参数具有一个值,该值被传递给
命令行。在指令定义之前,任何对
变量会导致空字符串。
USER
what_user
username
what_user
ARG
在构建阶段中声明的变量会自动由
其他阶段基于该阶段。不相关的构建阶段无权访问
变量。要在多个不同的阶段中使用参数,每个阶段都必须
包含指令,或者它们都必须基于共享基础
阶段。ARG
ARG
有关更多信息,请参阅 变量范围.
使用 ARG 变量
您可以使用 or 指令来指定
可用于指令。使用该指令定义的环境变量始终覆盖同名的指令。考虑
这个 Dockerfile 带有 and 指令。ARG
ENV
RUN
ENV
ARG
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 .
在这种情况下,指令使用 set 而不是 setting
由用户传递:此行为类似于 shell
脚本,其中本地范围的变量会覆盖作为
参数或从 environment 继承,从其定义点。RUN
v1.0.0
ARG
v2.0.1
使用上面的示例但使用不同的规范,您可以创建更多
和 说明之间的有用交互:ENV
ARG
ENV
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER
与指令不同,值始终持久保存在 built
镜像。考虑一个没有标志的 docker 构建:ARG
ENV
--build-arg
$ docker build .
使用此 Dockerfile 示例,仍保留在镜像中,但
它的值将是 as 它是指令在第 3 行中设置的默认值。CONT_IMG_VER
v1.0.0
ENV
此示例中的变量扩展技术允许您传递参数
并从命令行中,并利用该指令将它们保留在最终镜像中。仅一组有限的
Dockerfile 说明。ENV
预定义的 ARG
Docker 有一组预定义的变量,您可以在没有
Dockerfile 中的相应说明。ARG
ARG
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy
要使用这些,请在命令行上使用标志 for
例:--build-arg
$ 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"
在这种情况下,变量的值在 中不可用,并且不会缓存。如果您要更改位置,并且您的
代理服务器已更改为 ,后续的
build 不会导致缓存未命中。HTTP_PROXY
docker history
http://user:pass@proxy.sfo.example.com
如果需要覆盖此行为,则可以通过在 Dockerfile 中添加一条语句来实现,如下所示:ARG
FROM ubuntu
ARG HTTP_PROXY
RUN echo "Hello World"
构建此 Dockerfile 时,the 将保留在 中,更改其值会使构建缓存失效。HTTP_PROXY
docker history
全球范围内的自动平台 ARG
此功能仅在使用 BuildKit 后端时可用。
BuildKit 支持一组预定义的变量,其中包含平台上的信息
执行构建的节点 (Build Platform) 和
生成的镜像 (Target Platform)。目标平台可以使用
上的 标志。ARG
--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 context 以保留目录。.git |
BUILDKIT_INLINE_CACHE 2 | 布尔 | 是否将缓存元数据内联到镜像配置。 |
BUILDKIT_MULTI_PLATFORM | 布尔 | 选择确定性输出,无论是否多平台输出。 |
BUILDKIT_SANDBOX_HOSTNAME | 字符串 | 设置主机名(默认buildkitsandbox ) |
BUILDKIT_SYNTAX | 字符串 | 设置前端镜像 |
SOURCE_DATE_EPOCH | Int (整数) | 为创建的镜像和图层设置 Unix 时间戳。来自 Reroducible Builds 的更多信息。从 Dockerfile 1.5、BuildKit 0.11 开始支持 |
示例:保留 .git
dir
使用 Git 上下文时,dir 不会保留在检出中。可以是
如果您想在
您的版本:.git
# 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
变量不会像变量那样持久化到构建的镜像中。
但是,变量确实以类似的方式影响构建缓存。如果
Dockerfile 定义了一个变量,其值与之前的
build 的 build 中,则 “cache miss” 发生在它第一次使用时,而不是它的定义上。在
特别是,指令后面的所有指令都隐式使用该变量(作为环境变量),因此可能会导致缓存未命中。
所有预定义变量都免于缓存,除非存在
matching 语句。ENV
ARG
ARG
RUN
ARG
ARG
ARG
ARG
例如,考虑以下两个 Dockerfile:
FROM ubuntu
ARG CONT_IMG_VER
RUN echo $CONT_IMG_VER
FROM ubuntu
ARG CONT_IMG_VER
RUN echo hello
如果在命令行上指定,则在
的情况下,第 2 行的规范不会导致缓存未命中;3 号线
导致缓存未命中。 导致线路被识别
与 running 相同,因此如果发生更改,则会收到缓存未命中。--build-arg CONT_IMG_VER=<value>
ARG CONT_IMG_VER
RUN
CONT_IMG_VER=<value> echo hello
<value>
考虑同一命令行下的另一个示例:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=$CONT_IMG_VER
RUN echo $CONT_IMG_VER
在此示例中,缓存未命中发生在第 3 行。发生错过是因为
变量的值引用该变量,并且
变量通过命令行进行更改。在此示例中,该命令使镜像包含该值。ENV
ARG
ENV
如果一条指令覆盖了一条同名的指令,比如
这个 Dockerfile:ENV
ARG
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=hello
RUN echo $CONT_IMG_VER
第 3 行不会导致缓存未命中,因为 的值为
常量 ()。因此,在
(第 4 行)在 build 之间不会更改。CONT_IMG_VER
hello
RUN
构建
ONBUILD <INSTRUCTION>
该指令向镜像添加一个触发指令,以
在以后执行,当镜像用作
另一个版本。触发器将在
downstream build 的 build 中插入,就好像它是在下游 Dockerfile 中的指令之后立即插入的一样。ONBUILD
FROM
如果您正在构建将用作基础的镜像,这将非常有用 要构建其他镜像,例如应用程序构建环境或 守护进程,该守护进程可以使用用户特定的配置进行自定义。
例如,如果您的镜像是可重用的 Python 应用程序构建器,则
将要求将应用程序源代码添加到特定的
目录中,并且可能需要在
那。你不能现在就打电话,因为你还没有
可以访问应用程序源代码,并且
每个应用程序构建。您可以简单地为应用程序开发人员提供
使用样板 Dockerfile 复制粘贴到他们的应用程序中,但
这效率低下、容易出错且难以更新,因为它
与特定于应用程序的代码混合。ADD
RUN
解决方案是用于将预先指令注册到
稍后在下一个构建阶段运行。ONBUILD
以下是它的工作原理:
- 当遇到指令时,构建器会添加一个
trigger 添加到正在构建的镜像的元数据中。指令
不会影响当前版本。
ONBUILD
- 在构建结束时,所有触发器的列表都存储在
image 清单中,在键 .它们可以使用
命令。
OnBuild
docker inspect
- 稍后,可以使用该指令将镜像用作新构建的基础。作为处理指令的一部分,
下游构建器查找触发器,并执行
他们按照他们注册的顺序。如果任何触发器
fail 时,指令被中止,进而导致
构建失败。如果所有触发器都成功,则指令
完成,构建会照常继续。
FROM
FROM
ONBUILD
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 ...
如果 的源是构建阶段,则必须在
Dockerfile 触发的位置。如果它是一个命名上下文,则
context 必须传递给下游构建。from
ONBUILD
ONBUILD 限制
- 不允许链接指令 using。
ONBUILD
ONBUILD ONBUILD
- 指令 may not trigger 或 instructions.
ONBUILD
FROM
MAINTAINER
停止信号
STOPSIGNAL signal
该指令设置将发送到
容器退出。此信号可以是格式为 ,
例如,或与
kernel 的 syscall 表,例如 .默认值为 if not
定义。STOPSIGNAL
SIG<NAME>
SIGKILL
9
SIGTERM
可以使用标志 on 和 .--stop-signal
docker run
docker create
健康检查
该指令有两种形式:HEALTHCHECK
HEALTHCHECK [OPTIONS] CMD command
(通过在容器内运行命令来检查容器运行状况)HEALTHCHECK NONE
(禁用从基础镜像继承的任何运行状况检查)
该指令告诉 Docker 如何测试容器以检查
它仍然有效。这可以检测 Web 服务器卡在
无限循环,并且无法处理新连接,即使服务器
进程仍在运行。HEALTHCHECK
当容器指定了 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 或更高版本。
Dockerfile 中只能有一条指令。如果您列出
多于一个,则只有最后一个才会生效。HEALTHCHECK
HEALTHCHECK
关键字后面的命令可以是 shell 命令(例如 )或 exec 数组(与其他 Dockerfile 命令一样;
参见 e.g. 了解详情)。CMD
HEALTHCHECK CMD /bin/check-running
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 状态中,并且可以使用 .此类输出应保持简短(仅前 4096 字节
当前存储)。docker inspect
当容器的运行状况发生变化时,事件为
以新状态生成。health_status
壳
SHELL ["executable", "parameters"]
该指令允许用于 shell 形式的默认 shell
命令。Linux 上的默认 shell 是 ,而
Windows 是 .该指令必须以 JSON 编写
表单。SHELL
["/bin/sh", "-c"]
["cmd", "/S", "/C"]
SHELL
该指令在 Windows 上特别有用,因为 Windows 中有
两个常用且完全不同的原生 shell:和 、 AS
以及可用的替代 shell,包括 .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 形式在 Dockerfile: 和 .SHELL
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"
这效率低下,原因有两个。首先,调用了一个不必要的命令处理器(又名 shell)。其次,每个指令
shell 形式需要为 command 添加额外的前缀。cmd.exe
RUN
powershell -command
为了提高这一效率,可以采用两种机制之一。一是
使用命令的 JSON 格式,例如:RUN
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
虽然 JSON 表单是明确的,并且不使用不必要的 ,
它确实需要通过双引号和转义来更加冗长。替代
机制是使用 INSTRUCTION 和 shell 的形式,
为 Windows 用户提供更自然的语法,尤其是与
parser 指令:cmd.exe
SHELL
escape
# 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 运行。例如,在 Windows 上使用、延迟
环境变量扩展语义可以修改。SHELL
SHELL cmd /S /C /V:ON|OFF
如果备用 shell 是 Linux,该指令也可以在 Linux 上使用
必需,例如 、 和其他。SHELL
zsh
csh
tcsh
Here-文档
Here-documents 允许将后续 Dockerfile 行重定向到 or 命令的输入。如果此类命令包含 here-document,则 Dockerfile 会考虑下一行,直到该行仅包含
here-doc 分隔符作为同一命令的一部分。RUN
COPY
示例:运行多行脚本
# 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
示例:创建内嵌文件
根据说明,您可以将 source 参数替换为 here-doc
指示符将 here-document 的内容直接写入文件。这
以下示例创建一个包含 using
一个指令。COPY
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
# 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 的示例,请参阅: