dockerfile 语法
Posted kingle-study
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dockerfile 语法相关的知识,希望对你有一定的参考价值。
基本语法格式:INSTRUCTION arguments (指令+参数)不分大小写
注释格式:# 注释
第一个指令必须是FROM,标示使用什么镜像
1、解析器指令
解析器指令是可选的,并且影响处理Dockerfile中后续行的方式。 解析器指令不会向构建中添加图层,并且不会显示为构建步骤。 解析器指令以#directive = value的形式写为特殊类型的注释。 单个指令只能使用一次。
一旦注释,空行或构建器指令已经被处理,Docker不再寻找解析器指令。 相反,它将格式化为解析器指令的任何内容视为注释,并且不尝试验证它是否可能是解析器指令。 因此,所有解析器指令必须位于Dockerfile的最顶端。
解析器指令不区分大小写。 然而,约定是他们是小写的。 约定还要包括一个空白行,遵循任何解析器指令。 解析器指令不支持行连续字符。
由于这些规则,以下示例都无效:
- 行延续而无效:
# direc
tive=value - 重复出现
# directive=value1
# directive=value2 - 出现在构建指令后
FROM ImageName
# directive=value - 作为注释处理,由于出现在不是解析器指令的注释之后
# About my dockerfile
FROM ImageName
# directive=value - 未知指令由于未被识别而被视为注释。 此外,由于出现在不是解析器指令的注释之后,已知指令被视为注释。
# unknowndirective=value
# knowndirective=value
在解析器指令中允许使用非换行符空格。 因此,以下行都被相同地处理
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
支持以下解析器指令:(目前就一个)
- escape
# escape= (反斜杠)
OR
# escape=` (反引号)
escape指令设置了用于在Dockerfile中转义字符的字符。 如果未指定,则缺省转义字符为
转义字符既用于转义行中的字符,也用于转义换行符。 这允许Dockerfile指令跨越多行。 注意,不管escape解析器指令是否包括在Dockerfile中,在RUN命令中不执行转义,除非在行的末尾。
将转义字符设置为`在Windows上特别有用,其中是目录路径分隔符。 `与Windows PowerShell一致。
2、环境变量替换
环境变量(使用ENV语句声明)也可以在某些指令中用作要由Dockerfile解释的变量。还可以处理转义,以将类似变量的语法包含到语句中。
FROM busybox
ENV foo /bar
Dockerfile中的以下指令列表支持环境变量:
- ADD
- COPY
- ENV
- EXPOSE
- LABEL
- USER
- WORKDIR
- VOLUME
- STOPSIGNAL
- ONBUILD
3、.dockerignore 文件
在docker CLI将内容送到docker守护程序之前,它会在内容的根目录中查找名为.dockerignore的文件。如果此文件存在,CLI将修改内容以排除与其中的模式匹配的文件和目录。这有助于避免不必要地向守护程序发送大型或敏感文件和目录,并可能使用ADD或COPY将其添加到映像。
CLI将.dockerignore文件解释为换行符分隔的模式列表,类似于Unix shell的文件glob。为了匹配的目的,内容的根被认为是工作目录和根目录。例如,模式/ foo / bar和foo / bar都排除了PATH的foo子目录或位于URL的git存储库根目录中名为bar的文件或目录。也不排除任何其他。
如果.dockerignore文件中的一行以第1列中的#开头,则此行将被视为注释,并在CLI解释之前被忽略。
这里是一个例子.dockerignore文件:
# comment
*/temp*
*/*/temp*
temp?
此文件导致以下构建行为:
规则 | 行为 |
---|---|
# comment | 注释 忽略 |
*/temp* | 排除其根目录的任何直接子目录中以temp开头的文件和目录。<br />例如,普通文件/somedir/temporary.txt被排除,<br />目录/ somedir / temp也被排除。 |
*/*/temp* | 从根目录下两级的任何子目录中排除以temp开头的文件和目录。<br /> 例如,排除了/somedir/subdir/temporary.txt。 |
temp? | 排除根目录中名称为temp的单字符扩展名的文件和目录。 <br />例如,/ tempa和/ tempb被排除。 |
行开头! (感叹号)可用于排除例外。 以下是使用此机制的.dockerignore文件示例:
*.md
!README.md
放置! 异常规则影响行为:匹配特定文件的.dockerignore的最后一行确定它是包含还是排除。 请考虑以下示例:
*.md
!README*.md
README-secret.md
只排除了README-secret.md
*.md
README-secret.md
!README*.md
排除所有README开头的.md文件
甚至可以使用.dockerignore文件来排除Dockerfile和.dockerignore文件。 这些文件仍然发送到守护程序,因为它需要它们来完成它的工作。 但是ADD和COPY命令不会将它们复制到映像。
最后,可能需要指定要包括在内容中的文件,而不是要排除的文件。 要实现这一点,指定*作为第一个模式,后面跟一个或多个! 异常模式。
4、FROM
FROM指令为后续指令设置基本镜像。 因此,有效的Dockerfile必须具有FROM作为其第一条指令。 镜像可以是任何有效的镜像 - 通过从公共存储库拉取镜像
FROM <image>
OR
FROM <image>:<tag>
OR
FROM <image>@<digest>
5、RUN
有两种格式
- RUN 指令
- RUN ["指令", "参数1", "参数2"...](json格式,必须双引号)
RUN指令将在当前镜像之上的新层中执行任何命令,并提交结果。 生成的已提交映像将用于Dockerfile中的下一步。
分层RUN指令和生成提交符合Docker的核心概念,其中提交很方便,可以从镜像历史中的任何点创建容器,就像源代码控制一样。
exec形式使得可以避免shell字符串变化,以及使用不包含指定的shell可执行文件的基本映像来运行RUN命令。
可以使用SHELL命令更改shell窗体的默认shell。
在shell形式中,可以使用(反斜杠)将单个RUN指令继续到下一行。 例如,考虑这两行:
RUN /bin/bash -c ‘source $HOME/.bashrc;
echo $HOME‘
当行形式:
RUN /bin/bash -c ‘source $HOME/.bashrc; echo $HOME‘
使用不同的shell,例如使用/bin/sh
RUN ["/bin/bash", "-c", "echo hello"]
用于RUN指令的高速缓存在下一次构建期间不会自动失效。 用于诸如RUN apt-get dist-upgrade之类的指令的高速缓存将在下一次构建期间被重用。 可以通过使用--no-cache标志(例如docker build --no-cache)使用于RUN指令的高速缓存无效,详细参看:最佳实践指南
已知问题(RUN)
问题783是关于在使用AUFS文件系统时可能发生的文件权限问题。 例如,您可能会在尝试rm文件时注意到它。
对于具有最近aufs版本的系统(即,可以设置dirperm1安装选项),docker将尝试通过使用dirperm1选项安装图层来自动解决问题。 有关dirperm1选项的更多详细信息,请参见aufs man page
如果您的系统不支持dirperm1,则该问题描述了一种解决方法。
6、CMD
格式:
- CMD ["executable","param1","param2"]
- CMD ["param1","param2"]
- CMD command param1 param2
在Dockerfile中只能有一个CMD指令。 如果您列出多个CMD,则只有最后一个CMD将生效。
CMD的主要目的是为执行容器提供默认值。 这些默认值可以包括可执行文件,或者它们可以省略可执行文件,在这种情况下,您还必须指定ENTRYPOINT指令。
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
7、LABEL
LABEL指令向镜像添加元数据。 LABEL是键值对。 要在LABEL值中包含空格,请使用引号和反斜杠,就像在命令行解析中一样。 几个使用示例:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates
that label-values can span multiple lines."
查看镜像的label信息,使用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.",
"other": "value3"
},
8、MAINTAINER
MAINTAINER指令设置生成的镜像的作者字段。 LABEL指令是一个更灵活的版本,你应该使用它,因为它可以设置任何所需的元数据,并可以很容易地查看,例如使用docker检查。 要设置与MAINTAINER字段对应的标签,您可以使用:
LABEL maintainer "[email protected]"
设置的数据,可以在docker inspect指令展示的数据的other选项中
9、EXPOSE
格式:EXPOSE prot port
EXPOSE指令通知Docker容器在运行时侦听指定的网络端口。 EXPOSE不会使主机的端口可访问。 为此,必须使用-p标志发布一系列端口,或使用-P标志发布所有暴露的端口。 您可以公开一个端口号,并在另一个号码外部发布。
要在主机系统上设置端口重定向,请参阅使用-P标志。 Docker网络功能支持创建网络,无需在网络中公开端口,有关详细信息,请参阅此 功能的概述)。
10、ENV
格式:ENV <key> <value> OR ENV <key>=<value> ...
ENV指令将环境变量<key>设置为值<value>。 此值将在所有“descendant”Dockerfile命令的环境中,并且可以在许多中被替换为inline。
ENV指令有两种形式。 第一种形式,ENV <key> <value>,将单个变量设置为一个值。 第一个空格后面的整个字符串将被视为<value> - 包括空格和引号等字符。
第二种形式,ENV <key> = <value> ...,允许一次设置多个变量。 注意,第二种形式在语法中使用等号(=),而第一种形式不使用。 与命令行解析类似,引号和反斜杠可用于在值中包含空格。
ENV myName="John Doe" myDog=Rex The Dog
myCat=fluffy
OR
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
11、ADD
格式:ADD <src> <dest> OR ADD ["<src>", "<dest>"]
ADD指令从<src>复制新文件,目录或远程文件URL,并将它们添加到路径<dest>的映像文件系统。
DD hom* /mydir/ # 添加全部以hom开头的文件
ADD hom?.txt /mydir/ # ? 代表单个任意字符
ADD遵守以下规则:
- <src>路径必须在构建的上下文中; 你不能ADD ../something /东西,因为docker build的第一步是发送上下文目录(和子目录)到docker守护进程。
- 如果<src>是URL并且<dest>不以尾部斜杠结尾,则从URL下载文件并将其复制到<dest>。
- 如果<src>是URL并且<dest>以尾部斜杠结尾,则从URL中推断文件名,并将文件下载到<dest> / <filename>。 例如,ADD http://example.com/foobar /会创建文件/ foobar。 该网址必须有一个非平凡的路径,以便在这种情况下可以发现一个适当的文件名(http://example.com不会工作)。
- 如果<src>是目录,则复制目录的全部内容,包括文件系统元数据。
12、COPY
格式:COPY <src> <dest> OR COPY ["<src>", "<dest>"]
COPY指令从<src>复制新文件或目录,并将它们添加到容器的文件系统,路径<dest>。
可以指定多个<src>资源,但它们必须是相对于正在构建的源目录
COPY hom* /mydir/
COPY hom?.txt /mydir/
COPY遵守以下规则:
- <src>路径必须在构建的目录中; 你不能COPY ../something / something,因为docker build的第一步是将当前目录(和子目录)发送到docker守护进程。
- 如果<src>是目录,则复制目录的全部内容,包括文件系统元数据。
13、ENTRYPOINT
格式:
- ENTRYPOINT ["executable", "param1", "param2"]
- ENTRYPOINT command param1 param2
ENTRYPOINT允许您配置将作为可执行文件运行的容器。
例如:下面将启动 nginx,监听80端口
docker run -i -t --rm -p 80:80 nginx
docker run <image>的命令行参数将附加在exec形式的ENTRYPOINT中的所有元素之后,并将覆盖使用CMD指定的所有元素。 这允许将参数传递到入口点,即docker run <image> -d将把-d参数传递给入口点。 您可以使用docker run --entrypoint标志覆盖ENTRYPOINT指令。
shell形式防止使用任何CMD或运行命令行参数,但缺点是您的ENTRYPOINT将作为/ bin / sh -c的子命令启动,它不传递信号。 这意味着可执行文件将不是容器的PID 1,并且不会接收Unix信号,因此您的可执行文件将不会从docker stop <container>接收到SIGTERM。
只有Dockerfile中最后一个ENTRYPOINT指令会有效果。
您可以使用ENTRYPOINT的exec形式设置相当稳定的默认命令和参数,然后使用任一形式的CMD设置更可能更改的其他默认值。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
以下Dockerfile显示使用ENTRYPOINT在前台运行Apache
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"]
最后,如果需要在关闭时进行一些额外的清理(或与其他容器通信),或者协调多个可执行文件,您可能需要确保ENTRYPOINT脚本接收到Unix信号,传递它们,然后 做一些更多的工作:
14、VOLUME
格式:VOLUM ["/data"]
VOLUME指令创建具有指定名称的装入点,并将其标记为从本机主机或其他容器保存外部装入的卷。 该值可以是JSON数组VOLUME [“/ var / log /”]或具有多个参数的纯字符串,例如VOLUME / var / log或VOLUME / var / log / var / db。 有关通过Docker客户端的更多信息/示例和安装说明,请参阅文档
docker run命令用存在于基本映像中指定位置的任何数据初始化新创建的卷。 例如,考虑以下Dockerfile片段:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
此Dockerfile导致导致docker运行的映像,在/ myvol中创建新的安装点,并将greeting文件复制到新创建的卷中。
15、USER
USER daemon
USER指令设置运行映像时使用的用户名或UID,以及Dockerfile中的任何RUN,CMD和ENTRYPOINT指令。
16、WORKDIR
WORKDIR /path/to/workdir
WORKDIR指令为Dockerfile中的任何RUN,CMD,ENTRYPOINT,COPY和ADD指令设置工作目录。 如果WORKDIR不存在,它将被创建,即使它没有在任何后续的Dockerfile指令中使用。
它可以在一个Dockerfile中多次使用。 如果提供了相对路径,它将相对于先前WORKDIR指令的路径。 例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终输出 /a/b/c
WORKDIR指令可以解析先前使用ENV设置的环境变量。 您只能使用在Dockerfile中显式设置的环境变量。 例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
输出 /path/$DIRNAME
17、ARG
格式:ARG <name>[=<default value>]
ARG指令定义一个变量,用户可以使用docker build命令使用--build-arg <varname> = <value>标志,在构建时将其传递给构建器。 如果用户指定未在Dockerfile中定义的构建参数,构建将输出警告。例如:
FROM busybox
USER ${user:-some_user}
ARG user
USER $user
构建时:docker build --build-arg user=what_user Dockerfile
您可以使用ARG或ENV指令来指定RUN指令可用的变量。 使用ENV指令定义的环境变量总是覆盖同名的ARG指令。 考虑这个带有ENV和ARG指令的Dockerfile。
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 Dockerfile
输出:v1.0.0
18、ONBUILD
格式:ONBUIL 指令
ONBUILD指令在镜像被用作另一个构建的基础时,向镜像添加要在以后执行的触发指令。触发器将在下游构建的上下文中执行,就好像它已经在下游Dockerfile中的FROM指令之后立即插入。
任何构建指令都可以注册为触发器。
如果您正在构建一个将用作构建其他映像的基础,例如应用程序构建环境或可以使用用户特定配置进行定制的守护程序,这将非常有用。
例如,如果您的映像是可重用的Python应用程序构建器,则需要将应用程序源代码添加到特定目录中,并且可能需要在此之后调用构建脚本。你不能只是调用ADD和RUN现在,因为你还没有访问应用程序源代码,它将是不同的每个应用程序构建。您可以简单地为应用程序开发人员提供一个样板Dockerfile以将其复制粘贴到其应用程序中,但这是低效,容易出错的并且难以更新,因为它与特定于应用程序的代码混合在一起。
解决方案是使用ONBUILD来注册提前指令,以便稍后在下一个构建阶段运行。
以下是它的工作原理:
- 当遇到ONBUILD指令时,构建器会向正在构建的镜像的元数据添加触发器。 该指令不会另外影响当前构建。
- 在构建结束时,所有触发器的列表存储在图像清单中的键OnBuild下。 可以使用docker inspect命令检查它们。
- 稍后,可以使用FROM指令将镜像用作新构建的基础。 作为处理FROM指令的一部分,下游构建器会查找ONBUILD触发器,并按照它们注册的顺序执行它们。 如果任何触发器失败,则FROM指令中止,这又导致构建失败。 如果所有触发器都成功,则FROM指令完成,并且构建如常继续。
- 触发器在执行后从最终镜像中清除。 换句话说,它们不会被“grand-children”构建继承。
19、STOPSIGNAL
格式:STOPSIGNAL signal
STOPSIGNAL指令设置将发送到容器以退出的系统调用信号。 该信号可以是与内核系统调用表中的位置匹配的有效无符号数,例如9,或者是SIGNAME格式的信号名称,例如SIGKILL。
20、HEALTHCHECK
格式:
- HEALTHCHECK [OPTIONS] CMD command通过在容器中运行命令来检查容器运行状况
- HEALTHCHECK NONE 禁用从基本映像继承的任何健康检查
HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。 这可以检测到诸如Web服务器被卡在无限循环中并且无法处理新连接的情况,即使服务器进程仍在运行。
当容器指定了healthcheck时,除了其正常状态外,它还具有健康状态。 此状态最初开始。 每当健康检查通过,它变得健康(无论之前的状态)。 在一定数量的连续故障后,它变得不健康。
可选参数:
- --interval=DURATION (默认30s) 30s检查一次
- --timeout=DURATION (默认: 30s) 超过30s,认定检查失败
- --retries=N (默认: 3) 尝试3次,认定容器不健康
命令的退出状态表示容器的运行状况。 可能的值是:
- 0 成功,健康
- 1 不健康
- 2 保留 不要用此退出代码
例:
HEALTHCHECK --interval=5m --timeout=3s
CMD curl -f http://localhost/ || exit 1
21、SHELL
格式:SHELL ["命令", "参数"]
SHELL指令允许用于命令的shell形式的默认shell被覆盖。 Linux上的默认shell是[“/ bin / sh”,“-c”],在Windows上是[“cmd”,“/ S”,“/ C”]。 SHELL指令必须以JSON形式写在Dockerfile中。
SHELL指令在Windows上特别有用,其中有两个常用的和完全不同的本机shell:cmd和powershell,以及包括sh的备用shell。
SHELL指令可以多次出现。 每个SHELL指令覆盖所有先前的SHELL指令,并影响所有后续指令。 例如:
FROM microsoft/windowsservercore
RUN echo default
RUN powershell -command Write-Host default
SHELL ["powershell", "-command"]
RUN Write-Host hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
链接:https://www.jianshu.com/p/46db3c909fdf
來源:简书