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
只能有一个或多个ARG
instructions,其中
声明在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=value
parser 指令中允许使用非换行空格。因此, 以下行的处理方式相同:
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
语法
使用syntax
parser 指令将 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>
上述方法的一种解决方案是将/
COPY
instruction,以及dir
.然而,这种语法充其量只是令人困惑,因为它并非如此
对于 Windows 上的路径来说,这是自然的,最坏的情况是,由于并非所有命令都打开,因此容易出错
Windows 支持作为路径分隔符。/
通过添加escape
parser 指令,以下 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
跟replacement
string=foobarbaz echo ${string/ba/fo} # fooforbaz
${variable//pattern/replacement}
替换所有出现的pattern
在variable
跟replacement
string=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 中:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
ONBUILD
(与上述支持的说明之一结合使用时)
您还可以将环境变量与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 文件
您可以使用.dockerignore
file 从
构建上下文。有关更多信息,请参阅 .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
价值。
可选的--platform
flag 可用于指定镜像的平台
倘FROM
引用多平台镜像。例如linux/amd64
,linux/arm64
或windows/amd64
.默认情况下,生成的目标平台
request 的 API 请求。全局构建参数可以在此标志的值中使用,
例如,自动平台 ARG 允许您强制将阶段转换为本机构建平台 (--platform=$BUILDPLATFORM
),
并使用它交叉编译到 stage 内的目标平台。
了解 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
一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-cache
flag 的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 ,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 cache 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 gcc
Apt 需要对其数据进行独占访问,因此缓存使用sharing=locked
,这将确保使用
相同的缓存挂载将相互等待,而不是访问相同的
cache 文件。您还可以使用sharing=private
如果
您更喜欢让每个构建在此
箱。
运行 --mount=type=tmpfs
这种安装类型允许安装tmpfs
在 Build Container 中。
选择 | 描述 |
---|---|
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 ,则当 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 mypackage
pip
将只能安装 tarfile 中提供的软件包,该软件包
可以由早期构建阶段控制。
运行 --network=host
该命令在主机的网络环境中运行(类似于docker build --network=host
,但基于每条指令)
警告
的使用
--network=host
受network.host
权利 在使用--allow-insecure-entitlement network.host
flag 或 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.insecure
flag 或 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: 0000003fffffffff
CMD
这CMD
instruction 设置运行容器时要执行的命令
从镜像中。
您可以指定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
是一个
键值对。要在LABEL
value、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 字段。
这LABEL
instruction 是其更灵活的版本,您应该使用
相反,因为它可以设置您需要的任何元数据,并且可以查看
轻松,例如使用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
发布和映射一个或多个端口,或者选择-P
flag 发布所有公开的
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,请将--ssh
flag 添加到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=true
flag 允许您保留.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
flag 允许您验证远程资源的校验和。这
校验和的格式为<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 --from
flag 允许您从镜像、构建阶段、
或命名上下文。
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
除非
自选--chown
flag 指定给定的用户名、组名或 UID/GID
组合以请求对复制内容的特定所有权。这
格式--chown
flag 允许使用 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/group
files 和用户名或组名称用于--chown
标志,则构建将在COPY
操作。使用数字 ID 需要
无需查找,并且不依赖于容器根文件系统内容。
使用 Dockerfile 语法版本 1.10.0 及更高版本时,
这--chmod
flag 支持变量插值,
这允许您使用 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 --from
statement 将
如果同一阶段中的任何先前命令发生更改,则 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>
这--parents
flag 保留父目录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
请注意,如果没有--parents
flag 指定,则任何文件名冲突都将
使 Linux 失败cp
带有明确错误消息的作
(cp: will not overwrite just-created './x/a.txt' with './y/a.txt'
),其中
Buildkit 将静默覆盖目标处的目标文件。
虽然可以保留COPY
指令仅包含一个src
entry,通常更有利
以使结果镜像中的图层计数尽可能低。因此
使用--parents
标志,则 Buildkit 能够打包多个COPY
说明中,保持目录结构不变。
复制 --exclude
注意
目前尚不支持稳定的语法,请使用
docker/dockerfile:1.7-labs
版本。
COPY [--exclude=<path> ...] <src> ... <dest>
这--exclude
flag 允许您指定要排除的文件的路径表达式。
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 "$@"
最后,如果您需要进行一些额外的清理(或与其他容器通信)
在关闭时,或者正在协调多个可执行文件时,您可能需要确保
该ENTRYPOINT
script 接收 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)作为
当前阶段。指定的用户用于RUN
instructions 和 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 patrick
WORKDIR (工作目录)
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
最终pwd
command 将是/a/b/c
.
这WORKDIR
指令可以解析先前使用ENV
.您只能使用在 Dockerfile 中显式设置的环境变量。
例如:
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
最终pwd
command 将是/path/$DIRNAME
如果未指定,则默认工作目录为 。在实践中,如果您不是从头开始构建 Dockerfile (/
FROM scratch
),
这WORKDIR
可能由您正在使用的基本镜像设置。
因此,为避免在未知目录中执行意外作,最佳实践是将WORKDIR
明确地。
精 氨 酸
ARG <name>[=<default value>] [<name>[=<default value>]...]
这ARG
instruction 定义了一个变量,用户可以在构建时传递给该变量
具有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
# ...
默认值
一ARG
instruction 可以选择包含默认值:
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
如果ARG
instruction 具有默认值,如果未传递值
在构建时,构建器使用默认值。
范围
一ARG
variable 从声明它的行开始生效
Dockerfile 中。例如,请考虑以下 Dockerfile:
FROM busybox
USER ${username:-some_user}
ARG username
USER $username
# ...
用户通过调用来构建此文件:
$ docker build --build-arg username=what_user .
- 这
USER
指令的计算结果为some_user
后备 因为username
variable 尚未声明。 - 这
username
variable 在第 3 行声明,并可在 Dockerfile 指令。 - 这
USER
第 4 行的 instruction 的计算结果为what_user
,因为在那时 将username
参数的值为what_user
这被传递了 命令行。在它由ARG
instruction、任何对 变量会导致空字符串。
一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_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy
要使用这些,请在命令行中使用--build-arg
flag, 用于
例:
$ 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_CACHE 2 | 布尔 | 是否将缓存元数据内联到镜像配置。 |
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 上下文时,.git
dir 不会保留在检出中。可以是
如果您想在
您的版本:
# 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_VER
FROM 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
将生效。
命令位于CMD
keyword 可以是 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_status
event 为
以新状态生成。
壳
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 用户提供更自然的语法,尤其是与
这escape
parser 指令:
# 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 的示例,请参阅: