Dockerfile参考
预计阅读时间:81分钟
Docker可以通过阅读Docker中的指令来自动构建映像
Dockerfile
。ADockerfile
是一个文本文档,其中包含用户可以在命令行上调用以组合图像的所有命令。使用docker build
用户可以创建自动构建,该构建连续执行多个命令行指令。
本页描述您可以在中使用的命令Dockerfile
。阅读完此页面后,请参考Dockerfile
最佳实践以获取有关技巧的指南。
用法
的搬运工构建命令从一个构建的图像Dockerfile
和一个上下文。构建的上下文是指定位置PATH
或的文件集URL
。这PATH
是本地文件系统上的目录。该URL
是一个Git仓库的位置。
构建上下文是递归处理的。因此,aPATH
包括任何子目录,并且a包括URL
存储库及其子模块。本示例显示了一个使用当前目录(.
)作为构建上下文的构建命令:
$ docker build .
Sending build context to Docker daemon 6.51 MB
...
构建是由Docker守护程序而不是CLI运行的。构建过程要做的第一件事是将整个上下文(递归)发送到守护程序。在大多数情况下,最好从空目录开始作为上下文,并将Dockerfile保留在该目录中。仅添加构建Dockerfile所需的文件。
警告
不要将根目录
/
用作PATH
构建上下文,因为它会导致构建将硬盘驱动器的全部内容传输到Docker守护程序。
要在构建上下文中使用文件,Dockerfile
引用指的是指令(例如,COPY
指令)中指定的文件。要提高构建的性能,请通过将.dockerignore
文件添加到上下文目录来排除文件和目录。有关如何创建.dockerignore
文件的信息,请参阅此页面上的文档。
传统上,Dockerfile
称为,Dockerfile
并且位于上下文的根中。您可以使用-f
标志withdocker build
指向文件系统中任何位置的Dockerfile。
$ docker build -f /path/to/a/Dockerfile .
如果构建成功,则可以指定存储新映像的存储库和标记:
$ docker build -t shykes/myapp .
要在构建后将映像标记到多个存储库中,请在-t
运行build
命令时添加多个参数:
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
在Docker守护程序运行中的指令之前Dockerfile
,它会对进行初步验证,Dockerfile
如果语法不正确,则会返回错误:
$ docker build -t test/myapp .
[+] Building 0.3s (2/2) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 60B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
error: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition:
dockerfile parse error line 2: unknown instruction: RUNCMD
Docker守护程序Dockerfile
逐一运行指令,如有必要,将每条指令的结果提交到新映像,然后最终输出新映像的ID。Docker守护程序将自动清理您发送的上下文。
请注意,每条指令都是独立运行的,并会导致创建新的映像-因此RUN cd /tmp
对下一条指令不会有任何影响。
Docker尽可能使用构建缓存来docker build
显着加速该过程。这由CACHED
控制台输出中的消息指示。(有关详细信息,请参阅Dockerfile
最佳做法指南:
$ docker build -t svendowideit/ambassador .
[+] Building 0.7s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 286B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:3.2 0.4s
=> CACHED [1/2] FROM docker.io/library/alpine:3.2@sha256:e9a2035f9d0d7ce 0.0s
=> CACHED [2/2] RUN apk add --no-cache socat 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:1affb80ca37018ac12067fa2af38cc5bcc2a8f09963de 0.0s
=> => naming to docker.io/svendowideit/ambassador 0.0s
默认情况下,构建缓存基于要构建的计算机上先前构建的结果。该--cache-from
选项还允许您使用通过映像注册表分发的构建缓存,请参考命令参考
中的“
指定外部缓存源”部分docker build
。
完成构建后,您就可以考虑使用扫描映像docker scan
并将其推送到Docker Hub了。
编译工具
从版本18.09开始,Docker支持由moby / buildkit 项目提供的用于执行构建的新后端。与旧的实现相比,BuildKit后端提供了许多好处。例如,BuildKit可以:
- 检测并跳过执行未使用的构建阶段
- 并行构建独立构建阶段
- 两次构建之间仅增量传输构建上下文中的已更改文件
- 在构建上下文中检测并跳过传输未使用的文件
- 使用具有许多新功能的外部Dockerfile实现
- 避免其他API(中间图像和容器)的副作用
- 优先考虑构建缓存以进行自动修剪
要使用BuildKit后端,您需要DOCKER_BUILDKIT=1
在CLI上设置环境变量
,然后再调用docker build
。
要了解基于BuildKit的构建可用的实验性Dockerfile语法,请参阅BuildKit存储库中的文档。
格式
这是的格式Dockerfile
:
# Comment
INSTRUCTION arguments
该指令不区分大小写。但是,惯例是将它们大写以更轻松地将它们与参数区分开。
DockerDockerfile
按顺序运行指令。一个Dockerfile
必须以开始FROM
的指令。这可能在解析器指令,注释和全局范围的
ARG之后。该FROM
指令指定要从中构建父图像。FROM
只能在一个或多个ARG
指令之前,这些指令声明在中的FROM
行中使用的参数Dockerfile
。
该码头工人对待线开始以#
作为注释,除非该行是一个有效的解析器指令。#
一行中其他任何地方的标记都被视为参数。这允许如下语句:
# Comment
RUN echo 'we are running some # of cool things'
在执行Dockerfile指令之前,将删除注释行,这意味着以下示例中的注释不会由执行echo
命令的Shell处理,并且以下两个示例是等效的:
RUN echo hello \
# comment
world
RUN echo hello \
world
注释中不支持换行符。
注意空白
为了向后兼容,将忽略但不鼓励在注释(
#
)和指令(例如RUN
)之前的前导空白。在这些情况下,不保留前导空格,因此以下示例是等效的:# this is a comment-line RUN echo hello RUN echo world
# this is a comment-line RUN echo hello RUN echo world
但是请注意,指令参数中的空格(例如跟随其后的命令
RUN
)被保留,因此以下示例使用指定的前导空格打印“ hello world”:RUN echo "\ hello\ world"
解析器指令
解析器指令是可选的,并且会影响Dockerfile
处理a中后续行的方式。解析器指令不会在构建中添加图层,也不会显示为构建步骤。解析器指令以形式写为特殊类型的注释# directive=value
。单个指令只能使用一次。
处理完注释,空行或生成器指令后,Docker不再寻找解析器指令。而是将格式化为解析器指令的任何内容都视为注释,并且不会尝试验证它是否可能是解析器指令。因此,所有解析器指令必须位于的最顶部Dockerfile
。
解析器指令不区分大小写。但是,约定是小写的。约定还应在任何解析器指令之后包含一个空白行。解析器指令不支持行继续符。
由于这些规则,以下示例均无效:
由于行继续而无效:
# direc \
tive=value
由于出现两次而无效:
# directive=value1
# directive=value2
FROM ImageName
由于出现在构建器指令之后而被视为注释:
FROM ImageName
# directive=value
由于出现在不是解析器指令的注释之后,因此被视为注释:
# About my dockerfile
# directive=value
FROM ImageName
由于未被识别,未知指令被视为注释。另外,由于在不是解析器指令的注释之后出现,所以已知指令被视为注释。
# unknowndirective=value
# knowndirective=value
解析器指令中允许不使用换行符的空格。因此,以下各行都被相同地对待:
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
支持以下解析器指令:
syntax
escape
句法
# syntax=[remote image reference]
例如:
# syntax=docker/dockerfile:1
# syntax=docker.io/docker/dockerfile:1
# syntax=example.com/user/repo:tag@sha256:abcdef...
此功能仅在使用BuildKit后端时可用,而在使用传统生成器后端时将被忽略。
语法指令定义用于构建Dockerfile的Dockerfile语法的位置。BuildKit后端允许无缝使用作为Docker映像分发并在容器沙箱环境中执行的外部实现。
自定义Dockerfile实现使您能够:
- 自动获取错误修正,而无需更新Docker守护程序
- 确保所有用户都使用相同的实现来构建您的Dockerfile
- 使用最新功能而无需更新Docker守护程序
- 在将新功能或第三方功能集成到Docker守护程序中之前,先对其进行尝试
- 使用替代的构建定义,或创建自己的构建定义
正式发布
Docker分发了映像的正式版本,这些映像可用于docker/dockerfile
在Docker Hub上的存储库下构建Dockerfile 。有两个发布新图像的渠道:stable
和labs
。
稳定的通道遵循语义版本控制。例如:
docker/dockerfile:1
-保持更新与最新的1.x.x
次要版本和补丁程序版本docker/dockerfile:1.2
-保持最新1.2.x
补丁程序的更新,并在版本1.3.0
发布后停止接收更新。docker/dockerfile:1.2.1
-不可变:永不更新
我们建议使用docker/dockerfile:1
,它始终指向版本1语法的最新稳定版本,并在版本1发行周期中同时接收“次要”更新和“补丁”更新。BuildKit在执行构建时会自动检查语法更新,以确保您使用的是最新版本。
如果使用特定版本(例如1.2
或)1.2.1
,则需要手动更新Dockerfile才能继续接收错误修正和新功能。Dockerfile的旧版本与构建器的新版本保持兼容。
实验室频道
“实验室”通道可提供对稳定通道中尚不可用的Dockerfile功能的早期访问。Labs频道图片是与稳定版一起发布的,并带有相同的-labs
后缀版本,例如:
docker/dockerfile:labs
-实验室频道的最新版本docker/dockerfile:1-labs
-与dockerfile:1
稳定频道相同,并启用了实验室功能docker/dockerfile:1.2-labs
-与dockerfile:1.2
稳定频道相同,并启用了实验室功能docker/dockerfile:1.2.1-labs
-不可变:永远不会更新。与dockerfile:1.2.1
稳定频道中相同,并启用了实验室功能
选择最适合您需求的渠道;如果您想从新功能中受益,请使用实验室频道。实验室频道中的图像提供了稳定频道中功能的超集;请注意,stable
实验室频道映像中的功能遵循语义版本控制,但“实验室”功能不遵循语义版本控制,并且较新的发行版可能不向后兼容,因此建议使用不可变的完整版本。
有关“实验室”功能,主版本和每夜发布的功能的文档,请参阅GitHub上BuildKit源存储库中的描述。有关可用映像的完整列表,请访问Docker Hub上的映像存储库,以及 用于开发构建的docker / dockerfile-upstream映像存储库。
逃脱
# escape=\ (backslash)
或者
# escape=` (backtick)
该escape
指令设置用来逃避的字符的字符
Dockerfile
。如果未指定,则默认转义字符为\
。
转义字符用于转义一行中的字符和转义换行符。这允许一条Dockerfile
指令跨越多行。请注意,无论escape
parser指令是否包含在Dockerfile
,都不会在RUN
命令中执行转义,除非在行末。
将转义符设置`
为尤其有用
Windows
,其中\
目录路径分隔符为。`
与Windows PowerShell一致。
考虑以下示例,该示例将以非显而易见的方式在上失败
Windows
。第二\
,在第二行的端部将被解释为用于换行的逃逸,而不是从第一逸出的目标\
。类似地,\
假设第三行的末尾实际上被当作一条指令来处理,则将其视为行的延续。此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
dir
Windows
Windows
/
通过添加escape
解析器指令,通过对以下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>
更换环境
环境变量(与声明的ENV
声明),也可以在特定指令作为变量用来被解释
Dockerfile
。转义也可以通过在字面上将类似变量的语法包含到语句中来进行处理。
环境变量Dockerfile
用
$variable_name
或表示${variable_name}
。它们被同等对待,并且大括号语法通常用于解决变量名不带空格的问题,例如${foo}_bar
。
该${variable_name}
语法还支持一些标准bash
修饰符,如下所示:
${variable:-word}
表示如果variable
设置,则结果将是该值。如果variable
未设置,则为word
结果。${variable:+word}
指示如果variable
设置了if,则将为word
结果,否则结果为空字符串。
在所有情况下,word
都可以是任何字符串,包括其他环境变量。
可以通过\
在变量前添加a来进行转义:例如,\$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
(当与上述受支持的说明之一结合使用时)
在整个指令中,环境变量替换将对每个变量使用相同的值。换句话说,在此示例中:
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
将导致def
值为hello
,而不是bye
。但是,
ghi
将具有的值,bye
因为它不是设置abc
为的同一指令的一部分bye
。
.dockerignore文件
在docker CLI将上下文发送到docker守护程序之前,它会.dockerignore
在上下文的根目录中查找名为的文件。如果此文件存在,则CLI会修改上下文以排除与其中的模式匹配的文件和目录。这有助于避免不必要地将大型文件或敏感文件和目录发送到守护程序,并避免使用ADD
或将它们添加到映像中COPY
。
CLI将.dockerignore
文件解释为以换行符分隔的模式列表,类似于Unix Shell的文件组。为了匹配,上下文的根被认为是工作目录和根目录。例如,图案
/foo/bar
和foo/bar
两个排除命名的文件或目录bar
的foo
子目录PATH
或位于Git仓库的根URL
。两者都不排除其他任何东西。
如果.dockerignore
文件中的一行以第#
1列开头,则该行将被视为注释,并且在CLI解释之前将被忽略。
这是一个示例.dockerignore
文件:
# comment
*/temp*
*/*/temp*
temp?
此文件导致以下生成行为:
规则 | 行为 |
---|---|
# comment |
忽略了。 |
*/temp* |
排除名称以temp 根的任何直接子目录开头的文件和目录。例如,/somedir/temporary.txt 排除了普通文件,也排除了目录/somedir/temp 。 |
*/*/temp* |
排除temp 从根以下两个级别的任何子目录开始的文件和目录。例如,/somedir/subdir/temporary.txt 被排除。 |
temp? |
排除根目录中名称为的一个字符扩展名的文件和目录temp 。例如,/tempa 和/tempb 被排除。 |
匹配使用Go的
filepath.Match规则完成。预处理步骤使用Go的filepath.Clean除去开头和结尾的空格,并消除.
和..
元素
。预处理后空白的行将被忽略。
除了Go的filepath.Match规则外,Docker还支持一个特殊的通配符字符串**
,该字符串可匹配任意数量的目录(包括零个)。例如,**/*.go
将排除.go
在所有目录(包括构建上下文的根目录)中找到的所有以结尾结尾的文件。
以!
(感叹号)开头的行可用于排除例外。以下是.dockerignore
使用此机制的示例文件:
*.md
!README.md
除了 README.md
上下文之外,所有降价文件都被排除在外。
!
异常规则的位置会影响行为:.dockerignore
与特定文件匹配的的最后一行确定是包含还是排除该文件。考虑以下示例:
*.md
!README*.md
README-secret.md
除了以外的自述文件,上下文中不包括markdown文件
README-secret.md
。
现在考虑以下示例:
*.md
README-secret.md
!README*.md
包括所有自述文件。中线没有作用,因为
!README*.md
匹配README-secret.md
并排在最后。
您甚至可以使用该.dockerignore
文件排除Dockerfile
和.dockerignore
文件。这些文件仍被发送到守护程序,因为它需要它们来完成其工作。但是ADD
和COPY
指令不会将它们复制到映像中。
最后,您可能想要指定要包含在上下文中的文件,而不是要排除的文件。为此,请指定*
为第一个模式,然后指定一个或多个!
异常模式。
笔记
由于历史原因,该模式
.
被忽略。
从
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
指令之前记录一次提交所输出的最后一个图像ID 。每个FROM
指令清除由先前指令创建的任何状态。- 可选的名称可以通过添加给予一个新的构建阶段
AS name
的FROM
指令。该名称可以在后续版本FROM
和COPY --from=<name>
说明中使用,以引用此阶段中构建的映像。 - 该
tag
或digest
值是可选的。如果您忽略其中任何一个,那么构建器latest
默认情况下都将使用标签。如果构建器找不到该tag
值,则返回错误。
--platform
在FROM
引用多平台图像的情况下,可选标志可用于指定图像的平台。例如,linux/amd64
,
linux/arm64
,或windows/amd64
。默认情况下,使用构建请求的目标平台。可以在此标志的值中使用全局构建参数,例如,自动平台ARG
允许您将阶段强制到本机构建平台(--platform=$BUILDPLATFORM
),并使用它来交叉编译到阶段内部的目标平台。
了解ARG和FROM之间的交互方式
FROM
指令支持由ARG
第一条指令之前的任何指令所声明的变量FROM
。
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
ARG
在a之前的声明FROM
位于构建阶段之外,因此在a之后的任何指令中都不能使用它FROM
。要ARG
在第一次FROM
使用声明之前使用默认值,请在ARG
构建阶段使用不带值的指令:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
跑步
RUN有2种形式:
RUN <command>
(shell形式,该命令在shell中运行,默认情况下/bin/sh -c
在Linux或cmd /S /C
Windows上运行)RUN ["executable", "param1", "param2"]
(执行表格)
该RUN
指令将在当前图像顶部的新层中执行所有命令,并提交结果。生成的提交映像将用于中的下一步Dockerfile
。
分层RUN
指令和生成提交符合Docker的核心概念,在Docker上,提交很便宜,并且可以从映像历史记录的任何位置创建容器,就像源代码控制一样。
在EXEC形式使得能够避免壳串改写(munging),并RUN
使用不包含指定壳可执行基本图像的命令。
可以使用以下
命令更改外壳程序表单的默认外壳程序SHELL
。
在shell形式中,您可以使用\
(反斜杠)将一条RUN指令继续到下一行。例如,考虑以下两行:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
它们在一起等效于以下这一行:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
要使用'/ bin / sh'以外的其他shell,请使用exec形式传入所需的shell。例如:
RUN ["/bin/bash", "-c", "echo hello"]
笔记
在EXEC形式被解析为一个JSON阵列,这意味着必须使用双引号(“)周围的话不单引号(')。
与shell表单不同,exec表单不会调用命令shell。这意味着正常的外壳处理不会发生。例如,
RUN [ "echo", "$HOME" ]
将不会对进行变量替换$HOME
。如果要进行shell处理,则可以使用shell形式或直接执行shell,例如:RUN [ "sh", "-c", "echo $HOME" ]
。当使用exec表单并直接执行shell时(例如在shell表单中),是由shell进行环境变量扩展,而不是docker。
笔记
在JSON格式中,必须转义反斜杠。这在Windows中特别有用,在Windows中反斜杠是路径分隔符。由于无效的JSON,以下几行将被视为shell形式,并以意外的方式失败:
RUN ["c:\windows\system32\tasklist.exe"]
此示例的正确语法为:
RUN ["c:\\windows\\system32\\tasklist.exe"]
RUN
下一次构建期间,指令缓存不会自动失效。类似指令的缓存
RUN apt-get dist-upgrade -y
将在下一个构建中重用。RUN
指令的缓存可以通过使用--no-cache
标志来使无效,例如docker build --no-cache
。
有关更多信息,请参见“Dockerfile
最佳实践”指南。
已知问题(运行)
-
问题783是有关使用AUFS文件系统时可能发生的文件权限问题。例如,您在尝试
rm
文件过程中可能会注意到它。对于具有最新aufs版本的系统(即,
dirperm1
可以设置安装选项),docker将尝试通过使用options挂载层来尝试自动修复该问题dirperm1
。有关dirperm1
选项的更多详细信息,请参见aufs
手册页如果您的系统不支持
dirperm1
,则该问题描述了一种解决方法。
CMD
该CMD
指令具有三种形式:
CMD ["executable","param1","param2"]
(exec形式,这是首选形式)CMD ["param1","param2"]
(作为ENTRYPOINT的默认参数)CMD command param1 param2
(外壳形式)
CMD
指令中只能有一条指令Dockerfile
。如果您列出多个,CMD
则只有最后一个CMD
才会生效。
a的主要目的CMD
是为执行中的容器提供默认值。这些默认值可以包含一个可执行文件,也可以忽略该可执行文件,在这种情况下,您还必须指定一条ENTRYPOINT
指令。
如果CMD
用于为ENTRYPOINT
指令提供默认参数,则CMD
和ENTRYPOINT
指令均应使用JSON数组格式指定。
笔记
在EXEC形式被解析为一个JSON阵列,这意味着必须使用双引号(“)周围的话不单引号(')。
与shell表单不同,exec表单不会调用命令shell。这意味着正常的外壳处理不会发生。例如,
CMD [ "echo", "$HOME" ]
将不会对进行变量替换$HOME
。如果要进行shell处理,则可以使用shell形式或直接执行shell,例如:CMD [ "sh", "-c", "echo $HOME" ]
。当使用exec表单并直接执行shell时(例如在shell表单中),是由shell进行环境变量扩展,而不是docker。
当以shell或exec格式使用时,该CMD
指令设置运行映像时要执行的命令。
如果您使用的shell形式CMD
,则将在中<command>
执行
/bin/sh -c
:
FROM ubuntu
CMD echo "This is a test." | wc -
如果要在 <command>
没有外壳的情况下运行,则必须将命令表示为JSON数组,并提供可执行文件的完整路径。
此数组形式是的首选格式CMD
。任何其他参数必须在数组中分别表示为字符串:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
如果您希望容器每次都运行相同的可执行文件,则应考虑ENTRYPOINT
与结合使用CMD
。请参阅
ENTRYPOINT。
如果用户指定的参数,docker run
则它们将覆盖中指定的默认值CMD
。
笔记
不要混淆
RUN
与CMD
。RUN
实际运行命令并提交结果;CMD
在生成时不执行任何操作,但指定映像的预期命令。
标签
LABEL <key>=<value> <key>=<value> <key>=<value> ...
该LABEL
指令将元数据添加到图像。ALABEL
是键值对。要在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"
基本或父图像(行中的图像FROM
)中包含的标签由您的图像继承。如果标签已经存在但具有不同的值,则最近应用的值将覆盖任何先前设置的值。
要查看图像的标签,请使用docker image inspect
命令。您可以使用该--format
选项仅显示标签。
$ docker image inspect --format='' 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"
}
MAAINAINER(已弃用)
MAINTAINER <name>
该MAINTAINER
指令设置所生成图像的“作者”字段。该LABEL
指令是此版本的灵活得多,您应该改用它,因为它可以设置所需的任何元数据,并且可以轻松查看(例如使用)docker inspect
。要设置与该MAINTAINER
字段相对应的标签,
您可以使用:
LABEL maintainer="SvenDowideit@home.org.au"
这样docker inspect
,其他标签就可以显示出来了。
暴露
EXPOSE <port> [<port>/<protocol>...]
该EXPOSE
指令通知Docker容器在运行时监听指定的网络端口。您可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。
该EXPOSE
指令实际上并未发布端口。它充当构建映像的人员和运行容器的人员之间的一种文档类型,有关打算发布哪些端口的信息。要在运行容器时实际发布端口,请使用-p
标记ondocker run
发布和映射一个或多个端口,或者使用-P
标记发布所有公开的端口并将它们映射到高阶端口。
默认情况下,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
命令支持创建网络以在容器之间进行通信,而无需e