Dockerfile用法选项示例权威详解
源自专栏《docker常用命令系列目录导航?》
Docker可以通过读取Dockerfile中的指令自动构建镜像。Dockerfile是一个文本文档,包含用户可以在命令行上调用的所有命令,用于组装镜像。本页面描述了在Dockerfile中可以使用的指令。
概述
Dockerfile支持以下指令:
指令 | 描述 |
---|---|
ADD | 添加本地或远程文件和目录 |
ARG | 使用构建时变量 |
CMD | 指定默认命令 |
COPY | 复制文件和目录 |
ENTRYPOINT | 指定默认可执行文件 |
ENV | 设置环境变量 |
EXPOSE | 描述应用程序正在侦听的端口 |
FROM | 从基础镜像创建新的构建阶段 |
HEALTHCHECK | 在启动时检查容器的健康状况 |
LABEL | 向镜像添加元数据 |
MAINTAINER | 指定镜像的作者 |
ONBUILD | 指定在构建中使用镜像时的指令 |
RUN | 执行构建命令 |
SHELL | 设置镜像的默认shell |
STOPSIGNAL | 指定退出容器的系统调用信号 |
USER | 设置用户和组ID |
VOLUME | 创建卷挂载 |
WORKDIR | 更改工作目录 |
格式
以下是Dockerfile的格式:
# 注释
INSTRUCTION 参数
指令对大小写不敏感。但是,按照惯例,它们通常大写,以便更容易区分它们和参数。
Docker按照Dockerfile中的顺序运行指令。Dockerfile必须以FROM指令开头。这可能是在解析器指令、注释和全局范围的ARG之后。FROM指令指定构建所使用的父镜像。FROM之前只能是一个或多个ARG指令,这些指令声明在Dockerfile中的FROM行中使用的参数。
BuildKit将以#开头的行视为注释,除非该行是有效的解析器指令。否则,行中的#标记将被视为参数。这允许如下语句:
# 注释
RUN echo 'we are running some # of cool things'
在执行Dockerfile指令之前,注释行将被移除。在以下示例中的注释在shell执行echo命令之前被移除:
RUN echo hello \
# 注释
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
然而,指令参数中的空格不会被忽略。以下示例将以指定的前导空格打印出hello world:
RUN echo "\
hello\
world"
解析器指令
解析器指令是可选的,并影响Dockerfile中后续行的处理方式。解析器指令不会增加构建的层,并且不会显示为构建步骤。解析器指令写为一种特殊类型的注释,形式为# 指令=值。一个解析指令只能使用一次。
一旦处理了注释、空行或构建器指令,BuildKit就不再查找解析器指令。相反,它将任何格式为解析器指令的内容视为注释,并不尝试验证是否可能是解析器指令。因此,所有解析器指令必须位于Dockerfile的顶部。
解析器指令对大小写不敏感,但按照惯例,它们是小写的。在任何解析器指令后面通常会包含一个空行。解析器指令中不支持换行字符。
由于这些规则,以下示例都是无效的:
由于换行符的原因无效:
# 指令 \
tive=值
由于出现两次而无效:
# 指令=值1
# 指令=值2
作为构建器指令之后的注释而被视为注释:
FROM 镜像名称
# 指令=值
因为它出现在不是解析器指令的注释之后而被视为注释:
# 关于我的Dockerfile
# 指令=值
FROM 镜像名称
以下未知指令被视为注释,因为它是未被识别的。已知语法指令被视为注释,因为它出现在不是解析器指令的注释之后。
# 未知指令=值
# 语法=值
解析器指令中允许非换行空格。因此,以下行都被等同地处理:
#指令=值
# 指令 =值
# 指令= 值
# 指令 = 值
# dIrEcTiVe=值
支持以下解析器指令:
- syntax
- escape
syntax
使用语法解析器指令声明用于构建的Dockerfile语法版本。如果未指定,BuildKit将使用Dockerfile前端的捆绑版本。声明语法版本使您可以自动使用最新的Dockerfile版本,而无需升级BuildKit或Docker Engine,甚至使用自定义的Dockerfile实现。
大多数用户将想要将此解析器指令设置为docker/dockerfile:1
,这会导致BuildKit在构建之前拉取Dockerfile语法的最新稳定版本。
# syntax=docker/dockerfile:1
有关解析器指令如何工作的更多信息,请参阅自定义Dockerfile语法。
escape
# escape=\
或
# escape=`
escape指令设置用于在Dockerfile中转义字符的字符。如果未指定,默认转义字符为\。
转义字符用于转义行中的字符,以及转义换行符。这允许Dockerfile指令跨越多行。请注意,无论是否在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