docker build
命令Dockerfile
根据上下文构建image。构建的上下文是指定位置PATH
或的文件URL
。这PATH
是本地文件系统上的目录。URL
是一个Git存储库位置。python
递归处理上下文。所以,a PATH
包括全部子目录,URL
包括存储库及其子模块。此示例显示了使用当前目录做为上下文的构建命令:nginx
$ docker build . Sending build context to Docker daemon 6.51 MB ...
构建由Docker守护程序运行,而不是由CLI运行。构建过程的第一件事是将整个上下文(递归地)发送到守护进程。在大多数状况下,最好从空目录开始做为上下文,并将Dockerfile保存在该目录中。仅添加构建Dockerfile所需的文件。git
警告:不要用你的根目录下,
/
做为PATH
由于它会致使生成到您的硬盘驱动器的所有内容传输到docker守护进程。github
要在构建上下文中使用文件,请Dockerfile
引用指令中指定的文件,例如COPY
指令。要提升构建的性能,请经过向.dockerignore
上下文目录添加文件来排除文件和目录。golang
它Dockerfile
被调用Dockerfile
并位于上下文的根中。您可使用-f
标志docker build
指向文件系统中任何位置的Dockerfile。docker
$ docker build -f /path/to/a/Dockerfile .
若是构建成功,您能够指定存储库和标记以保存新image:shell
$ docker build -t shykes/myapp .
要在构建后将映像标记为多个存储库,请在-t
运行build
命令时添加多个参数:apache
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
在Docker守护程序运行其中的指令以前Dockerfile
,它会执行初步验证Dockerfile
并在语法不正确时返回错误:ubuntu
$ docker build -t test/myapp . Sending build context to Docker daemon 2.048 kB Error response from daemon: Unknown instruction: RUNCMD
Docker守护程序Dockerfile
逐个运行指令,在必要时将每条指令的结果提交给新image,最后输出新image的ID。Docker守护程序将自动清理您发送的上下文。windows
请注意,每条指令都是独立运行的,会致使建立新image - 所以RUN cd /tmp
不会对下一条指令产生任何影响。
只要有可能,Docker将从新使用中间image(缓存),以docker build
显着加速该过程。
$ docker build -t svendowideit/ambassador . Sending build context to Docker daemon 15.36 kB Step 1/4 : FROM alpine:3.2 ---> 31f630c65071 Step 2/4 : MAINTAINER xxx@xxx.xx ---> Using cache ---> 2a1c91448f5f Step 3/4 : RUN apk update && apk add socat && rm -r /var/cache/ ---> Using cache ---> 21ed6e7fbb73 Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh ---> Using cache ---> 7ea8aef582cc Successfully built 7ea8aef582cc
构建缓存仅用于具备本地父链的。这意味着这些image是由之前的版本建立的,或者加载了整个image链docker load
。若是您但愿使用特定image的构建缓存,可使用--cache-from
选项指定它。指定的image --cache-from
不须要具备父链,能够从其余注册表中提取。
这是如下格式Dockerfile
:
# Comment INSTRUCTION arguments
该指令不区分大小写。可是,惯例是让它们成为大写的,以便更容易地将它们与参数区分开来。
Docker Dockerfile
按顺序运行指令。一个Dockerfile
必须用FROM
指令启动。该FROM
指令指定您正在构建的Baseimage。FROM
能够仅由一个或多个前面ARG
的指令,其声明了在使用的参数FROM
中的行Dockerfile
。
Docker 将以条目开头的行#
视为注释,除非该行是有效的parser-directives
。#
行中任何其余位置的标记都被视为参数。这容许这样的陈述:
# Comment RUN echo 'we are running some # of cool things'
注释中不支持行继续符。
解析器指令是可选的,而且影响Dockerfile
处理a 中后续行的方式。解析器指令不会向构建添加图层,也不会显示为构建步骤。解析器指令在表单中被写为特殊类型的注释# directive=value
。单个指令只能使用一次。
一旦处理了注释,空行或构建器指令,Docker就再也不查找解析器指令。相反,它将格式化为解析器指令的任何内容视为注释,而且不会尝试验证它是否多是解析器指令。所以,全部解析器指令必须位于a的顶部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
支持如下解析器指令:
escape
# escape=\ (backslash)
要么
# escape=` (backtick)
escape
指令设置用于转义字符的字符 Dockerfile
。若是未指定,则默认转义字符为\
。
FROM microsoft/nanoserver COPY testfile.txt c:\\ RUN dir c:\
结果是:
PS C:\John> 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 C:\John>
上面的一个解决方案是/
用做COPY
指令的目标,和dir
。可是,这种语法充其量是使人困惑的,由于对于路径来讲并不天然Windows
,而且最坏的状况是容易出错,由于并不是全部命令都 做为路径分隔符Windows
支持/
。
经过添加escape
解析器指令,如下Dockerfile
成功使用文件路径的天然平台语义Windows
:
# escape=` FROM microsoft/nanoserver COPY testfile.txt c:\ RUN dir c:\
结果是:
PS C:\John> 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 C:\John>
环境变量(声明的ENV
),也能够在特定指令做为变量用来被解释 Dockerfile
。还会处理转义,以便将相似变量的语法包含在字面上。
环境变量Dockerfile
用 $variable_name
or表示${variable_name}
。它们被等效地处理,而且括号语法一般用于解决具备没有空格的变量名称的问题,例如${foo}_bar
。
该${variable_name}
语法还支持一些标准的bash
修饰以下规定:
${variable:-word}
表示若是variable
设置后,结果将是该值。若是variable
未设置则结果将是word
。${variable:+word}
表示若是variable
设置,那么word
将是结果,不然结果是空字符串。在全部状况下,word
能够是任何字符串,包括其余环境变量。
经过\
在变量以前添加来实现转义:\$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
(当与上面支持的指令之一结合使用时)注意:在1.4以前,
ONBUILD
指令不支持环境变量,即便与上面列出的任何指令结合使用也是如此。
环境变量替换将在整个指令中对每一个变量使用相同的值。换句话说,在这个例子中:
ENV abc=hello ENV abc=bye def=$abc ENV ghi=$abc
将致使def
具备值hello
,而不是bye
。可是, ghi
将具备值,bye
由于它不是设置abc
为的相同指令的一部分bye
。
在docker CLI将上下文发送到docker守护程序以前,它会查找.dockerignore
在上下文的根目录中指定的文件。若是此文件存在,CLI将修改上下文以排除与其中的模式匹配的文件和目录。这有助于避免没必要要地将大型或敏感文件和目录发送到守护程序,并可能使用ADD
或将它们添加到映像中COPY
。
CLI将.dockerignore
文件解释为新行分隔的模式列表,相似于Unix shell的文件globs。出于匹配的目的,上下文的根被认为是工做目录和根目录。例如,模式 /foo/bar
和foo/bar
二者都排除bar
在位于的git存储库的foo
子目录PATH
或根目录中命名的文件或目录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
除了之外的README文件,上下文中不包含markdown文件 README-secret.md
。
如今考虑这个例子:
*.md README-secret.md !README*.md
包含全部README文件。中间线没有效果,由于 !README*.md
匹配README-secret.md
而且最后。
您甚至可使用.dockerignore
文件来排除Dockerfile
和.dockerignore
文件。这些文件仍然发送到守护程序,由于它须要它们来完成它的工做。可是ADD
和COPY
指令不会将它们复制到image中。
最后,您可能但愿指定要包含在上下文中的文件,而不是要排除的文件。要实现此目的,请指定*
第一个模式,而后指定一个或多个!
异常模式。
注意:因为历史缘由,将.
忽略该模式。
FROM <image> [AS <name>]
要么
FROM <image>[:<tag>] [AS <name>]
要么
FROM <image>[@<digest>] [AS <name>]
该FROM
指令初始化新的构建阶段并为后续指令设置Baseimage。所以,有效Dockerfile
必须以FROM
指令开始。image能够是任何有效image - 经过从dockerrepos提取image来启动它尤为容易。
ARG
是先于仅指示FROM
在Dockerfile
。FROM
能够在单个内容中屡次出现Dockerfile
以建立多个image,或者使用一个构建阶段做为另外一个构建阶段的依赖项。只需在每条新FROM
指令以前记下提交输出的最后一个imageID 。每条FROM
指令都清除先前指令建立的任何状态。AS name
到FROM
指令来将 名称赋予新的构建阶段。该名称可用于后续FROM
和 COPY --from=<name|index>
指令,以引用此阶段构建的image。tag
或digest
值是可选的。若是省略其中任何一个,则构建器默认采用latest
标记。若是找不到tag
值,构建器将返回错误。FROM
说明支持由ARG
第一个以前发生的任何指令声明的变量FROM
。
ARG CODE_VERSION=latest FROM base:${CODE_VERSION} CMD /code/run-app FROM extras:${CODE_VERSION} CMD /code/run-extras
在ARG
生命以前,FROM
是一个构建阶段以外,所以它不能在以后的任何指令使用FROM
。要ARG
在第一次FROM
使用以前使用声明的默认值,请在ARG
构建阶段内使用没有值的指令:
ARG VERSION=latest FROM busybox:$VERSION ARG VERSION RUN echo $VERSION > image_version
RUN有两种形式:
RUN <command>
(shell表单,该命令在shell中运行,默认状况下/bin/sh -c
在Linux或cmd /S /C
Windows 上运行)RUN ["executable", "param1", "param2"]
(执行形式)该RUN
指令将在当前image之上的新层中执行任何命令并提交结果。生成的提交image将用于下一步Dockerfile
。
分层RUN
指令和生成提交符合Docker的核心概念,能够从image历史中的任何点建立容器,就像源代码控制同样。
在EXEC形式使得可以避免壳串改写(munging),RUN
使用不包含指定壳可执行基本image命令。
可使用 SHELL
命令更改shell表单的默认shell。
在shell形式中,您可使用\
(反斜杠)将单个RUN指令继续到下一行。例如,考虑如下两行:
RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME'
它们一块儿至关于这一行:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
注意:要使用除“/ bin / sh”以外的其余shell,请使用传入所需shell 的exec表单。例如,
RUN ["/bin/bash", "-c", "echo hello"]
注意:exec表单被解析为JSON数组,这意味着您必须使用双引号(“)来围绕单词而不是单引号(')。
注意:与shell表单不一样,exec表单不会调用命令shell。这意味着不会发生正常的shell处理。例如,
RUN [ "echo", "$HOME" ]
不会对变量进行替换$HOME
。若是你想要shell处理,那么要么使用shell表单,要么直接执行shell,例如:RUN [ "sh", "-c", "echo $HOME" ]
。当使用exec表单并直接执行shell时,就像shell表单的状况同样,它是执行环境变量扩展的shell,而不是docker。注意:在JSON表单中,必须转义反斜杠。这在反斜杠是路径分隔符的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
。
RUN
指令的高速缓存能够经过ADD
该CMD
指令有三种形式:
CMD ["executable","param1","param2"]
(执行形式,这是首选形式)CMD ["param1","param2"]
(做为ENTRYPOINT的默认参数)CMD command param1 param2
(贝壳形式)a中只能有一条CMD
指令Dockerfile
。若是列出多个,CMD
则只有最后一个CMD
生效。
a的主要目的CMD是为执行容器提供默认值。这些默认值能够包含可执行文件,也能够省略可执行文件,在这种状况下,您还必须指定一条ENTRYPOINT
指令。
注意:若是
CMD
用于为ENTRYPOINT
指令提供默认参数,则应使用JSON数组格式指定CMD
和ENTRYPOINT
指令。
注意:exec表单被解析为JSON数组,这意味着您必须使用双引号(“)来围绕单词而不是单引号(')。
注意:与shell表单不一样,exec表单不会调用命令shell。这意味着不会发生正常的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>
没有 shell 的状况下运行,则必须将该命令表示为JSON数组,并提供可执行文件的完整路径。 此数组形式是首选格式CMD。任何其余参数必须在数组中单独表示为字符串:
FROM ubuntu CMD ["/usr/bin/wc","--help"]
若是您但愿容器每次都运行相同的可执行文件,那么您应该考虑ENTRYPOINT
结合使用CMD
。
若是用户指定了参数,docker run
那么它们将覆盖指定的默认值CMD
。
注意:不要混淆
RUN
使用CMD
。RUN
实际上运行一个命令并提交结果;CMD
在构建时不执行任何操做,但指定image的预期命令。
LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL
指令将元数据添加到image。 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."
image能够有多个标签。您能够在一行中指定多个标签。在Docker 1.10以前,这减少了最终image的大小,但如今再也不是这种状况了。您仍然能够选择在单个指令中指定多个标签,方法有如下两种:
LABEL multi.label1="value1" multi.label2="value2" other="value3" LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
基本或父image中包含的标签(FROM
线中的image)由image继承。若是标签已存在但具备不一样的值,则最近应用的值将覆盖任何先前设置的值。
要查看image的标签,请使用该docker inspect
命令。
"Labels": { "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" },
EXPOSE <port> [<port>/<protocol>...]
EXPOSE
指令通知Docker容器在运行时侦听指定的网络端口。您能够指定端口是侦听TCP仍是UDP,若是未指定协议,则默认为TCP。
该EXPOSE
指令实际上没有发布端口。它做为构建映像的人和运行容器的人之间的一种文档,用于发布要发布的端口。要在运行容器时实际发布端口,请使用-p
标志on docker run
来发布和映射一个或多个端口,或使用-P
标志发布全部公开的端口并将它们映射到高阶端口。
默认状况下,EXPOSE
假定为TCP。您还能够指定UDP:
EXPOSE 80/udp
要在TCP和UDP上公开,请包含两行:
EXPOSE 80/tcp EXPOSE 80/udp
在这种状况下,若是使用docker run
-P
,端口将为TCP暴露一次,对UDP则暴露一次。请记住,-P
在主机上使用短暂的高阶主机端口,所以TCP和UDP的端口不一样。
不管EXPOSE
设置如何,您均可以使用-p
标志在运行时覆盖它们。例如
docker run -p 80:80/tcp -p 80:80/udp ...
ENV <key> <value> ENV <key>=<value> ...
该ENV
指令将环境变量<key>
设置为该值 <value>
。此值将在构建阶段中全部后续指令的环境中。
ENV
指令有两种形式。第一种形式,ENV <key> <value>
将一个变量设置为一个值。第一个空格后的整个字符串将被视为<value>
- 包括空格字符。该值将针对其余环境变量进行解释,所以若是未对其进行转义,则将删除引号字符。
第二种形式ENV <key>=<value> ...
容许一次设置多个变量。请注意,第二种形式在语法中使用等号(=),而第一种形式则否则。与命令行解析同样,引号和反斜杠可用于在值内包含空格。
例如:
ENV myName="John Doe" myDog=Rex\ The\ Dog \ myCat=fluffy
和
ENV myName John Doe ENV myDog Rex The Dog ENV myCat fluffy
将在最终image中产生相同的结果。
ENV
当从生成的image运行容器时,使用的环境变量将保持不变。您可使用docker inspect
,查看值,并使用它们进行更改docker run --env <key>=<value>
。
注意:环境持久性可能会致使意外的反作用。例如,设置
ENV DEBIAN_FRONTEND noninteractive
可能会使基于Debian的image上的apt-get用户感到困惑。要为单个命令设置值,请使用RUN <key>=<value> <command>
。
ADD有两种形式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
(包含空格的路径须要此表单)注意:该
--chown
功能仅在用于构建Linux容器的Dockerfiles上受支持,而且不适用于Windows容器。因为用户和组全部权概念不能在Linux和Windows之间进行转换,所以使用/etc/passwd
和/etc/group
将用户名和组名转换为ID会限制此功能仅适用于基于Linux OS的容器。
该ADD
指令从中复制新文件,目录或远程文件URL <src>
,并将它们添加到路径上image的文件系统中<dest>
。
<src>
能够指定多个资源,但若是它们是文件或目录,则它们的路径将被解释为相对于构建上下文的源。
每一个都<src>
可能包含通配符,匹配将使用Go的 filepath.Match规则完成。例如:
ADD hom* /mydir/ # adds all files starting with "hom" ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
的<dest>
是一个绝对路径,或相对于一个路径WORKDIR
,到其中的源将在目标容器内进行复制。
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/ ADD test /absoluteDir/ # adds "test" to /absoluteDir/
添加包含特殊字符(例如[
和]
)的文件或目录时,须要按照Golang规则转义这些路径,以防止它们被视为匹配模式。例如,要添加名为的文件arr[0].txt
,请使用如下命令;
ADD arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/
除非可选--chown
标志指定给定用户名,组名或UID / GID组合以请求所添加内容的特定全部权,不然将使用UID和GID为0建立全部新文件和目录。--chown
标志的格式容许用户名和组名字符串或任意组合的直接整数UID和GID。提供没有组名的用户名或没有GID的UID将使用与GID相同的数字UID。若是提供了用户名或组名,则容器的根文件系统 /etc/passwd
和/etc/group
文件将分别用于执行从名称到整数UID或GID的转换。如下示例显示了该--chown
标志的有效定义:
ADD --chown=55:mygroup files* /somedir/ ADD --chown=bin files* /somedir/ ADD --chown=1 files* /somedir/ ADD --chown=10:11 files* /somedir/
若是容器根文件系统不包含任何文件/etc/passwd
或 /etc/group
文件,而且--chown
标志中使用了用户名或组名,则构建将在ADD
操做上失败。使用数字ID不须要查找,也不依赖于容器根文件系统内容。
在<src>
远程文件URL 的状况下,目标将具备600的权限。若是正在检索的远程文件具备HTTPLast-Modified
标头,则来自该标头的时间戳将用于设置mtime
目标文件。可是,与在处理期间处理的任何其余文件同样ADD
,mtime
将不包括在肯定文件是否已更改且应更新缓存中。
注意:若是经过传递
Dockerfile
STDIN(docker build - < somefile
)进行构建,则没有构建上下文,所以Dockerfile
只能包含基于URL的ADD
指令。您还能够经过STDIN :(docker build - < archive.tar.gz
)传递压缩存档Dockerfile
,该存档位于存档的根目录,其他存档将用做构建的上下文。
注意:若是您的网址文件都使用认证保护,您将须要使用
RUN wget
,RUN curl
或使用其它工具从容器内的ADD
指令不支持验证。
注意:
ADD
若是内容<src>
已更改,则第一个遇到的指令将使来自Dockerfile的全部后续指令的高速缓存无效。这包括使缓存无效以获取RUN
指令。
ADD
遵照如下规则:
<src>
路径必须是内部语境的构建; 你不能ADD ../something /something
,由于a的第一步 docker build
是将上下文目录(和子目录)发送到docker守护程序。<src>
是URL而且<dest>
不以尾部斜杠结尾,则从URL下载文件并将其复制到<dest>
。<src>
是URL而且<dest>
以尾部斜杠结尾,则从URL推断文件名并将文件下载到<dest>/<filename>
。例如,ADD http://example.com/foobar /
将建立该文件/foobar
。URL必须具备很是重要的路径,以便在这种状况下能够发现适当的文件名(http://example.com
不起做用)。<src>
是目录,则复制目录的所有内容,包括文件系统元数据。注意:不复制目录自己,只复制其内容。
若是<src>
是以可识别的压缩格式(identity,gzip,bzip2或xz)的本地 tar存档,则将其解压缩为目录。从资源远程网址不解压。复制或解压缩目录时,它具备与之相同的行为tar -x
,结果是:
注意:文件是否被识别为可识别的压缩格式仅基于文件的内容而不是文件的名称来完成。例如,若是一个空文件碰巧结束,
.tar.gz
这将不会被识别为压缩文件,而且不会生成任何类型的解压缩错误消息,而是将文件简单地复制到目标。
若是<src>
是任何其余类型的文件,则将其与元数据一块儿单独复制。在这种状况下,若是<dest>
以尾部斜杠结尾/
,则将其视为目录,<src>
并将写入内容<dest>/base(<src>)
。
若是<src>
直接或因为使用通配符指定了多个资源,则<dest>
必须是目录,而且必须以斜杠结尾/
。
若是<dest>
不以尾部斜杠结束,则将其视为常规文件,<src>
并将写入其中的内容<dest>
。
若是<dest>
不存在,则会在其路径中建立全部缺乏的目录。
COPY有两种形式:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
(包含空格的路径须要此表单)注意:该
--chown
功能仅在用于构建Linux容器的Dockerfiles上受支持,而且不适用于Windows容器。因为用户和组全部权概念不能在Linux和Windows之间进行转换,所以使用/etc/passwd
和/etc/group
将用户名和组名转换为ID会限制此功能仅适用于基于Linux OS的容器。
该COPY
指令从中复制新文件或目录<src>
,并将它们添加到路径中容器的文件系统中<dest>
。
<src>
能够指定多个资源,但文件和目录的路径将被解释为相对于构建上下文的源。
每一个都<src>
可能包含通配符,匹配将使用Go的 filepath.Match规则完成。例如:
COPY hom* /mydir/ # adds all files starting with "hom" COPY hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
的<dest>
是一个绝对路径,或相对于一个路径WORKDIR
,到其中的源将在目标容器内进行复制。
COPY test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/ COPY test /absoluteDir/ # adds "test" to /absoluteDir/
复制包含特殊字符(例如[
和]
)的文件或目录时,须要按照Golang规则转义这些路径,以防止它们被视为匹配模式。例如,要复制名为的文件arr[0].txt
,请使用如下命令;
COPY arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/
除非可选--chown
标志指定给定用户名,组名或UID / GID组合以请求复制内容的特定全部权,不然将使用UID和GID为0建立全部新文件和目录。--chown
标志的格式容许用户名和组名字符串或任意组合的直接整数UID和GID。提供没有组名的用户名或没有GID的UID将使用与GID相同的数字UID。若是提供了用户名或组名,则容器的根文件系统 /etc/passwd
和/etc/group
文件将分别用于执行从名称到整数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/
若是容器根文件系统不包含任何文件/etc/passwd
或 /etc/group
文件,而且--chown
标志中使用了用户名或组名,则构建将在COPY
操做上失败。使用数字ID不须要查找,也不依赖于容器根文件系统内容。
注意:若是使用STDIN(
docker build - < somefile
)构建,则没有构建上下文,所以COPY
没法使用。
(可选)COPY
接受一个标志--from=<name|index>
,该标志可用于将源位置设置为FROM .. AS <name>
将用于替代用户发送的构建上下文的先前构建阶段(使用其建立)。该标志还接受为FROM
指令启动的全部先前构建阶段分配的数字索引 。若是找不到具备指定名称的构建阶段,则尝试使用具备相同名称的image。
COPY
遵照如下规则:
<src>
路径必须是内部语境的构建; 你不能COPY ../something /something
,由于a的第一步 docker build
是将上下文目录(和子目录)发送到docker守护程序。<src>
是目录,则复制目录的所有内容,包括文件系统元数据。注意:不复制目录自己,只复制其内容。
<src>
是任何其余类型的文件,则将其与元数据一块儿单独复制。在这种状况下,若是<dest>
以尾部斜杠结尾/
,则将其视为目录,<src>
并将写入内容<dest>/base(<src>)
。<src>
直接或因为使用通配符指定了多个资源,则<dest>
必须是目录,而且必须以斜杠结尾/
。<dest>
不以尾部斜杠结束,则将其视为常规文件,<src>
并将写入其中的内容<dest>
。<dest>
不存在,则会在其路径中建立全部缺乏的目录。ENTRYPOINT有两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec形式,首选)ENTRYPOINT command param1 param2
(shell形式)ENTRYPOINT
容许您配置将做为可执行文件运行的容器。
例如,如下将使用其默认内容启动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形式防止任何CMD
或run
被使用命令行参数,可是具备你的缺点ENTRYPOINT
将被开始做为一个子命令/bin/sh -c
,其不经过信号。这意味着可执行文件将不是容器PID 1
- 而且不会收到Unix信号 - 所以您的可执行文件将不会收到 SIGTERM
来自docker stop <container>
。
只有意志中的最后一条ENTRYPOINT
指令Dockerfile
才有效。
您可使用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
而且您能够优雅地请求docker stop test
来关闭top
。
如下Dockerfile
显示使用ENTRYPOINT
在前台运行Apache(即as 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"]
若是须要为单个可执行文件编写启动脚本,可使用exec
和gosu
命令确保最终的可执行文件接收Unix信号:
#!/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
脚本接收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
设置--entrypoint
,但这只能将二进制设置为exec(不会sh -c
使用)。
注意:exec表单被解析为JSON数组,这意味着您必须使用双引号(“)来围绕单词而不是单引号(')。
注意:与shell表单不一样,exec表单不会调用命令shell。这意味着不会发生正常的shell处理。例如,
ENTRYPOINT [ "echo", "$HOME" ]
不会对变量进行替换$HOME
。若是你想要shell处理,那么要么使用shell表单,要么直接执行shell,例如:ENTRYPOINT [ "sh", "-c", "echo $HOME" ]
。当使用exec表单并直接执行shell时,就像shell表单的状况同样,它是执行环境变量扩展的shell,而不是docker。
您能够为ENTRYPOINT
它指定一个纯字符串,它将在其中执行/bin/sh -c
。此表单将使用shell处理来替换shell环境变量,并将忽略任何CMD
或docker run
命令行参数。为了确保可以正确地docker stop
发出任何长时间运行的ENTRYPOINT
可执行文件,您须要记住启动它exec
:
FROM ubuntu ENTRYPOINT exec top -b
运行此image时,您将看到单个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 Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq Load average: 0.01 0.02 0.05 2/101 7 PID PPID USER STAT VSZ %VSZ %CPU COMMAND 1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2 7 1 root R 3164 0% 0% top -b
您能够从输出中top
看到指定ENTRYPOINT
的不是PID 1
。
若是而后运行docker stop test
,容器将不会干净地退出 - stop
命令将被强制SIGKILL
在超时后发送:
$ docker exec -it test ps aux PID USER COMMAND 1 root /bin/sh -c top -b cmd cmd2 7 root top -b 8 root ps aux $ /usr/bin/time docker stop test test real 0m 10.19s user 0m 0.04s sys 0m 0.03s
CMD
和ENTRYPOINT
指定运行容器时执行的命令。不多有规则描述他们的合做。
CMD
或ENTRYPOINT
命令。ENTRYPOINT
应该在将容器用做可执行文件时定义。CMD
应该用做定义ENTRYPOINT
命令的默认参数或在容器中执行ad-hoc命令的方法。CMD
在使用替代参数运行容器时将被覆盖。下表显示了针对不一样ENTRYPOINT
/ CMD
组合执行的命令:
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”,“p1_entry”] | |
---|---|---|---|
No CMD | error,not allowed | / 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 [“p1_cmd”,“p2_cmd”] | p1_cmd p2_cmd | / bin / sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_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 |
VOLUME ["/data"]
VOLUME
指令建立具备指定名称的安装点,并将其标记为从本机主机或其余容器保存外部安装的卷。该值能够是JSON数组,VOLUME ["/var/log/"]
或具备多个参数的普通字符串,例如VOLUME /var/log
或VOLUME /var/log /var/db
。
docker run
命令使用基础映像中指定位置存在的任何数据初始化新建立的卷。例如,请考虑如下Dockerfile片断:
FROM ubuntu RUN mkdir /myvol RUN echo "hello world" > /myvol/greeting VOLUME /myvol
此Dockerfile会docker run
生成一个image,该image将致使建立新的挂载点/myvol
并将greeting
文件复制到新建立的卷中。
关于卷中的卷,请记住如下事项Dockerfile
。
C:
"
)而不是单引号('
)括起单词。VOLUME
指令不支持指定host-dir
参数。您必须在建立或运行容器时指定安装点。USER <user>[:<group>] or USER <UID>[:<GID>]
USER
运行的image和用于当任何指令设置的用户名(或UID)和任选的所述用户组(或GID)使用RUN
,CMD
和 ENTRYPOINT
它后面的指令Dockerfile
。
警告:当用户没有主要组时,image(或下一个说明)将与该
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 /path/to/workdir
WORKDIR
指令集的工做目录对任何RUN
,CMD
, ENTRYPOINT
,COPY
和ADD
它后面的说明Dockerfile
。若是WORKDIR
不存在,即便它未在任何后续Dockerfile
指令中使用,也将建立它。
WORKDIR
指令能够在a中屡次使用Dockerfile
。若是提供了相对路径,则它将相对于前一条WORKDIR
指令的路径 。例如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
最终pwd
命令的输出Dockerfile
将是 /a/b/c
。
WORKDIR
指令能够解析先前使用的环境变量 ENV
。您只能使用显式设置的环境变量Dockerfile
。例如:
ENV DIRPATH /path WORKDIR $DIRPATH/$DIRNAME RUN pwd
最终pwd
命令的输出Dockerfile
将是 /path/$DIRNAME
ARG <name>[=<default value>]
ARG
指令定义了一个变量,用户能够docker build
使用该--build-arg <varname>=<value>
标志在构建时将该变量传递给构建器。若是用户指定了未在Dockerfile中定义的构建参数,则构建会输出警告。
[Warning] One or more build-args [foo] were not consumed.
Dockerfile能够包括一个或多个ARG
指令。例如,如下是有效的Dockerfile:
FROM busybox ARG user1 ARG buildno ...
警告:建议不要使用构建时变量来传递密码,例如github密钥,用户凭据等
docker history
。使用该命令,构建时变量值对于映像的任何用户都是可见的。
的ARG
指令能够可选地包括一个默认值:
FROM busybox ARG user1=someuser ARG buildno=1 ...
若是ARG
指令具备默认值,而且在构建时没有传递值,则构建器将使用默认值。
一个ARG
变量定义进入从在其上在限定的线效果Dockerfile
不从参数对命令行或其余地方使用。例如,考虑这个Dockerfile:
1 FROM busybox 2 USER ${user:-some_user} 3 ARG user 4 USER $user ...
用户经过调用如下内容构建此文件:
$ docker build --build-arg user=what_user .
第2行计算USER``some_user
为user
变量在后续第3行定义。第4行USER
计算结果what_user
为user
定义,并what_user
在命令行上传递值。在经过ARG
指令定义以前 ,对变量的任何使用都会致使空字符串。
一个ARG
指令超出范围在它被定义的构建阶段结束。要在多个阶段中使用arg,每一个阶段都必须包含该ARG
指令。
FROM busybox ARG SETTINGS RUN ./run/setup $SETTINGS FROM busybox ARG SETTINGS RUN ./run/other $SETTINGS
您可使用ARG
或ENV
指令指定指令可用的变量RUN
。使用该ENV
指令定义的环境变量 始终覆盖ARG
同名指令。考虑这个Dockerfile和一个ENV
和ARG
指令。
1 FROM ubuntu 2 ARG CONT_IMG_VER 3 ENV CONT_IMG_VER v1.0.0 4 RUN echo $CONT_IMG_VER
而后,假设使用此命令构建此映像:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .
在这种状况下,RUN
指令使用v1.0.0
而不是ARG
用户传递的设置:v2.0.1
此行为相似于shell脚本,其中本地范围的变量覆盖做为参数传递的变量或从其定义的环境继承的变量。
使用上面的示例但不一样的ENV
规范,您能够在指令ARG
和ENV
指令之间建立更有用的交互:
1 FROM ubuntu 2 ARG CONT_IMG_VER 3 ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0} 4 RUN echo $CONT_IMG_VER
与ARG
指令不一样,ENV
值始终保留在构建的image中。考虑没有--build-arg
标志的docker构建:
$ docker build .
使用此Dockerfile示例CONT_IMG_VER
仍然保留在image中,但其值将是指令v1.0.0
中第3行的默认值ENV
。
Docker有一组预约义ARG
变量,您能够ARG
在Dockerfile中使用相应的指令。
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
要使用它们,只需使用标志在命令行上传递它们:
--build-arg <varname>=<value>
默认状况下,这些预约义变量将从输出中排除 docker history
。排除它们能够下降在HTTP_PROXY
变量中意外泄露敏感验证信息的风险。
例如,考虑使用构建如下Dockerfile--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
,则后续构建不会致使缓存未命中。
若是须要覆盖此行为,则能够经过ARG
在Dockerfile中添加语句来执行此操做,以下所示:
FROM ubuntu ARG HTTP_PROXY RUN echo "Hello World"
构建此Dockerfile时,HTTP_PROXY
会保留在其中 docker history
,而且更改其值会使构建缓存无效。
ARG
变量不会像ENV
变量那样持久保存在构建的image中。可是,ARG
变量确实以相似的方式影响构建缓存。若是Dockerfile定义了一个ARG
值与前一个版本不一样的变量,则在第一次使用时会发生“缓存未命中”,而不是其定义。特别是,RUN
指令后面的全部指令都 隐式ARG
使用ARG
变量(做为环境变量),所以可能致使高速缓存未命中。ARG
除非在中包含匹配的ARG
语句,不然全部预约义变量都将免于缓存Dockerfile
。
例如,考虑这两个Dockerfile:
1 FROM ubuntu 2 ARG CONT_IMG_VER 3 RUN echo $CONT_IMG_VER 1 FROM ubuntu 2 ARG CONT_IMG_VER 3 RUN echo hello
若是--build-arg CONT_IMG_VER=<value>
在命令行中指定,则在两种状况下,第2行上的规范都不会致使高速缓存未命中; 第3行确实致使缓存未命中。ARG CONT_IMG_VER
致使RUN行被识别为与运行CONT_IMG_VER=<value>
echo hello 相同,所以若是<value>
更改,咱们将得到缓存未命中。
考虑同一命令行下的另外一个示例:
1 FROM ubuntu 2 ARG CONT_IMG_VER 3 ENV CONT_IMG_VER $CONT_IMG_VER 4 RUN echo $CONT_IMG_VER
在此示例中,高速缓存未命中发生在第3行。发生未命中是由于ENV
引用ARG
变量的变量值和经过命令行更改了该变量。在此示例中,该ENV
命令使image包含该值。
若是一条ENV
指令覆盖了一个ARG
同名的指令,好比这个Dockerfile:
1 FROM ubuntu 2 ARG CONT_IMG_VER 3 ENV CONT_IMG_VER hello 4 RUN echo $CONT_IMG_VER
第3行不会致使缓存未命中,由于值为CONT_IMG_VER
常量(hello
)。所以,RUN
(第4行)上使用的环境变量和值在构建之间不会发生变化。
ONBUILD [INSTRUCTION]
当image用做另外一个构建的基础时,该ONBUILD
指令向image添加将在稍后执行的触发指令。触发器将在下游构建的上下文中执行,就好像它已经FROM
在下游指令以后当即插入同样Dockerfile
。
任何构建指令均可以注册为触发器。
若是要构建将用做构建其余映像的基础的映像(例如,可使用特定于用户的配置自定义的应用程序构建环境或守护程序),这将很是有用。
例如,若是您的映像是可重用的Python应用程序构建器,则须要将应用程序源代码添加到特定目录中,而且可能须要在 此以后调用构建脚本。你不能只是打电话ADD
和RUN
如今,由于你尚未访问应用程序的源代码,这将是为每一个应用程序生成不一样的。您能够简单地为应用程序开发人员提供Dockerfile
复制粘贴到他们的应用程序中的样板,但这样作效率低,容易出错且难以更新,由于它与特定于应用程序的代码混合在一块儿。
解决方案是用于ONBUILD
在下一个构建阶段注册预先指令以便稍后运行。
如下是它的工做原理:
ONBUILD
指令时,构建器会向正在构建的image的元数据添加触发器。该指令不会影响当前构建。OnBuild
。可使用该docker inspect
命令检查它们。FROM
指令将image用做新构建的基础 。做为处理FROM
指令的一部分,下游构建器查找ONBUILD
触发器,并按照它们注册的顺序执行它们。若是任何触发器失败,FROM
则停止指令,这反过来致使构建失败。若是全部触发器都成功,则FROM
指令完成而且构建继续照常进行。例如,您能够添加如下内容:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
警告:不容许
ONBUILD
使用连接指令ONBUILD ONBUILD
。
警告:
ONBUILD
指令可能不会触发FROM
或MAINTAINER
指令。
STOPSIGNAL signal
该STOPSIGNAL
指令设置将发送到容器的系统调用信号以退出。此信号能够是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或SIGNAME格式的信号名,例如SIGKILL。
HEALTHCHECK
指令有两种形式:
HEALTHCHECK [OPTIONS] CMD command
(经过在容器内运行命令来检查容器运行情况)HEALTHCHECK NONE
(禁用从基础映像继承的任何运行情况检查)该HEALTHCHECK
指令告诉Docker如何测试容器以检查它是否仍在工做。即便服务器进程仍在运行,这也能够检测到陷入无限循环且没法处理新链接的Web服务器等状况。
当容器指定了运行情况检查时,除了正常状态外,它还具备运行情况。这个状态最初是starting
。每当健康检查经过时,它就会变成healthy
(之前的状态)。通过必定数量的连续失败后,它就变成了unhealthy
。
以前能够出现的选项CMD
是:
--interval=DURATION
(默认值:30s
)--timeout=DURATION
(默认值:30s
)--start-period=DURATION
(默认值:0s
)--retries=N
(默认值:3
)运行情况检查将首先在容器启动后的间隔秒运行,而后在每次上一次检查完成后再间隔秒。
若是单次运行的检查花费的时间超过超时秒数,那么检查将被视为失败。
它须要重试连续的健康检查失败才能考虑容器unhealthy
。
start period为须要时间引导的容器提供初始化时间。在此期间探测失败将不计入最大重试次数。可是,若是在启动期间运行情况检查成功,则会将容器视为已启动,而且全部连续失败将计入最大重试次数。
HEALTHCHECK
Dockerfile中只能有一条指令。若是列出多个,则只有最后一个HEALTHCHECK
生效。
CMD
关键字后面的命令能够是shell命令(例如HEALTHCHECK CMD /bin/check-running
)或exec数组(与其余Dockerfile命令同样; ENTRYPOINT
有关详细信息,请参阅参考资料)。
命令的退出状态指示容器的运行情况。可能的值是:
例如,要检查每五分钟左右网络服务器可以在三秒钟内为网站的主页面提供服务:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
为了帮助调试失败的探测器,命令在stdout或stderr上写入的任何输出文本(UTF-8编码)将存储在运行情况中并可使用查询 docker inspect
。此类输出应保持较短(目前仅存储前4096个字节)。
当容器的运行情况更改时,将health_status
生成具备新状态的事件。
该HEALTHCHECK
功能已添加到Docker 1.12中。
SHELL ["executable", "parameters"]
SHELL
指令容许覆盖用于shell形式的命令的默认shell 。Linux上的默认shell是["/bin/sh", "-c"]
,而在Windows上["cmd", "/S", "/C"]
。该SHELL
指令必须以JSON格式写入Dockerfile。
的SHELL
:其中有两个经常使用的和彻底不一样的原生贝壳指令是在Windows上特别有用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使用:RUN
,CMD
和ENTRYPOINT
。
如下示例是在Windows上找到的常见模式,可使用如下SHELL
指令简化:
... RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt" ...
docker调用的命令将是:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
因为两个缘由,这是低效的。首先,调用一个没必要要的cmd.exe命令处理器(也就是shell)。其次,shell 形式的每条RUN
指令都须要额外的命令前缀。powershell -command
为了提升效率,能够采用两种机制中的一种。一种是使用RUN命令的JSON形式,例如:
... RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""] ...
虽然JSON表单是明确的,而且不使用没必要要的cmd.exe,但它确实须要经过双引号和转义更加详细。替代机制是使用SHELL
指令和shell表单,为Windows用户建立更天然的语法,尤为是与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:\docker\build\shell> 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:\docker\build\shell>
SHELL
指令还可用于修改shell的运行方式。例如,SHELL cmd /S /C /V:ON|OFF
在Windows上使用,能够修改延迟的环境变量扩展语义。
的SHELL
,也能够在Linux上使用的指令应当替代壳须要如zsh
,csh
,tcsh
和其余。
该SHELL
功能已添加到Docker 1.12中。
# Nginx # # VERSION 0.0.1 FROM ubuntu LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0" RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server # Firefox over VNC # # VERSION 0.3 FROM ubuntu # Install vnc, xvfb in order to create a 'fake' display and firefox RUN apt-get update && apt-get install -y x11vnc xvfb firefox RUN mkdir ~/.vnc # Setup a password RUN x11vnc -storepasswd 1234 ~/.vnc/passwd # Autostart firefox (might not be the best way, but it does the trick) RUN bash -c 'echo "firefox" >> /.bashrc' EXPOSE 5900 CMD ["x11vnc", "-forever", "-usepw", "-create"] # Multiple images example # # VERSION 0.1 FROM ubuntu RUN echo foo > bar # Will output something like ===> 907ad6c2736f FROM ubuntu RUN echo moo > oink # Will output something like ===> 695d7793cbe4 # You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with # /oink.