Docker 是一个开源平台,旨在自动化应用程序的构建、交付和运行。通过 Dockerfile,您可以定义镜像的构建过程。Dockerfile 是由一系列指令组成的文件,Docker 根据这些指令构建镜像。本文将介绍常用的 Dockerfile 指令、格式、解析器指令以及环境变量替换的用法,帮助开发者编写高效、规范的 Dockerfile。
Dockerfile 常用指令
| 指令 | 描述 |
|---|---|
| ADD | 添加本地或远程文件和目录。 |
| ARG | 使用构建时变量。 |
| CMD | 指定默认命令。 |
| COPY | 复制文件和目录。 |
| ENTRYPOINT | 指定默认可执行文件。 |
| ENV | 设置环境变量。 |
| EXPOSE | 描述您的应用程序正在监听的端口。 |
| FROM | 从基础镜像创建新的构建阶段。 |
| HEALTHCHECK | 启动时检查容器的健康状况。 |
| LABEL | 向镜像添加元数据。 |
| MAINTAINER | 指定镜像的作者。 |
| ONBUILD | 指定在构建中使用镜像时的说明。 |
| RUN | 执行构建命令。 |
| SHELL | 设置镜像的默认 shell。 |
| STOPSIGNAL | 指定退出容器的系统调用信号。 |
| USER | 设置用户和组 ID。 |
| VOLUME | 创建卷挂载。 |
| WORKDIR | 更改工作目录。 |
Dockerfile 格式
Dockerfile 的基本格式如下:
INSTRUCTION arguments
-
指令区分大小写,通常使用大写字母表示。
-
指令按顺序执行。
-
Dockerfile 必须以
FROM指令开头。 -
注释:以
#开头的行是注释,BuildKit 会忽略这些行,除非它们是有效的解析器指令。-
行中的任何其他位置的
#标记都被视为参数。这允许使用诸如以下语句RUN echo 'we are running some # of cool things' -
注释行在执行 Dockerfile 指令之前被删除。以下示例中的注释在 shell 执行
echo命令之前被删除。RUN echo hello \ # comment world以下示例是等效的。
RUN echo hello \ world -
注释不支持行延续字符。
-
-
空白符:指令参数中的空格不会被忽略。
指令参数中的空格不会被忽略。以下示例按指定的空格打印
hello worldRUN echo "\hello\world"
解析器指令
解析器指令是影响 Dockerfile 处理方式的可选指令,它们以特殊注释格式# directive=value 编写,并不会添加构建层,也不会显示为构建步骤。
规则
-
解析器指令必须位于 Dockerfile 的顶部。
-
解析器指令不支持行延续字符。
-
解析器指令不区分大小写,且通常采用小写。
支持的指令
-
# syntax=docker/dockerfile:1:指定 Dockerfile 的语法版本。-
如果未指定,BuildKit 使用捆绑的 Dockerfile 前端版本。
-
设置将使 BuildKit 在构建之前拉取最新的稳定版本的 Dockerfile 语法。
# syntax=docker/dockerfile:1
-
-
# escape=:设置转义字符,允许跨行书写指令。-
如果未指定,则默认转义字符为
\。 -
将转义字符设置为
\在Windows上特别有用,因为\是目录路径分隔符。\与 Windows PowerShell一致。# escape=`FROM microsoft/nanoserver COPY testfile.txt c:\ RUN dir c:\
-
无效示例
由于这些规则,以下示例都是无效的:
-
由于行延续而无效
# direc \ tive=value -
由于出现两次而无效
# directive=value1 # directive=value2FROM ImageName -
被视为注释,因为它出现在构建器指令之后
FROM ImageName # directive=value -
被视为注释,因为它出现在不是解析器指令的注释之后
# About my dockerfile # directive=value FROM ImageName -
以下
unknowndirective被视为注释,因为它不被识别。已知的syntax指令被视为注释,因为它出现在不是解析器指令的注释之后。# unknowndirective=value # syntax=value
解析器指令允许使用非换行符空格。因此,以下行都被视为相同
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
环境变量替换
Dockerfile 中的环境变量通过ENV 指令进行定义,可以在多个指令中作为变量进行替换。环境变量在 Dockerfile 中通常使用$variable_name 或${variable_name} 的形式进行引用,它们是等效的。大括号语法(${})一般用于处理没有空格的变量名问题,例如${foo}_bar。
变量替换语法
-
$variable_name和${variable_name}都可以表示环境变量。 -
${variable_name}语法支持一些标准的bash修饰符,例如:-
${variable:-word}:如果设置了variable,则结果为该值;如果未设置variable,则结果为word。 -
${variable:+word}:如果设置了variable,则结果为word;否则结果为空字符串。
-
转义环境变量
如果需要在 Dockerfile 中转义整个变量名,可以在变量名前添加\。例如:
-
\$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(与上述支持的指令之一组合时)
RUN、CMD 和ENTRYPOINT 中的环境变量
您还可以将环境变量与RUN、CMD 和ENTRYPOINT 指令一起使用。但在这些指令中,变量替换是由命令 shell 处理的,而不是由构建器处理的。
环境变量的作用范围
在 Dockerfile 中,环境变量的替换在整个指令中使用相同的值。修改环境变量的值仅对后续的指令生效。
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
在这个例子中:
-
def的值变为hello。 -
ghi的值变为bye。
总结
Dockerfile 是构建 Docker 镜像的核心工具,理解和掌握常用指令及解析器指令的使用,能够帮助您高效地构建镜像并简化 DevOps 流程。通过合理设置环境变量和优化构建过程,您可以提升应用程序的可移植性和可维护性。
