Dockerfile 使用 ARG 参数实现构建模板
Intro
Dockerfile
里用来表示变量的主要有两个东西,一个是 ENV
代表了环境变量,另外一个则是 ARG
代表是构建 docker 镜像时的一个构建参数,需要在执行 docker build
命令时指定变量的值,最近使用了 ARG
来表示在 Dockerfile
里安装 dotnet global tool 的版本
Sample
来看一个使用示例,下面是一个 Dockerfile 示例
FROM mcr.microsoft.com/dotnet/runtime:6.0-alpine AS base
LABEL Maintainer="WeihanLi"FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env
# dotnet-httpie version, docker build --build-arg TOOL_VERSION=0.1.0 -t weihanli/dotnet-httpie:0.1.0 .
ARG TOOL_VERSION
RUN dotnet tool install --global dotnet-httpie --version ${TOOL_VERSION}FROM base AS final
COPY --from=build-env /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="/root/.dotnet/tools:${PATH}"
在上面的 Dockerfile 中我们声明了一个 TOOL_VERSION
的参数,需要在 docker build
的时候通过 build-arg
来指定这个参数,如果不指定会报错,因为我们并没有指定默认值,你也可以在声明的时候指定一个默认值 ARG TOOL_VERSION=1.0.0
实际 build docker 镜像时使用下面的命令:
docker build --build-arg TOOL_VERSION=0.1.0 -t weihanli/dotnet-httpie:0.1.0 .docker build --build-arg TOOL_VERSION=0.1.1-preview-20210829-075835 -t weihanli/dotnet-httpie:0.1.1-preview-20210829-075835 .
可以看到实际安装的 dotnet tool 版本就是 build 的时候指定的版本
More
很多人可能会想要问什么时候用 ARG
什么时候用 ENV
呢,刚好看到 StackOverflow 上的一个回答,可以参考:https://stackoverflow.com/questions/41916386/arg-or-env-which-one-to-use-in-this-case
如果你想在构建镜像时自定义,那你应该考虑使用 ARG
,因为 ARG
是构建时的参数,而 ENV
则是最终运行时容器的一个变量,你可以在 docker run
创建容器的时候指定环境变量的时,两个参数属于不同的阶段,具体要看自己的需求了,根据需要灵活选择
大名鼎鼎的 v2ray 在构建 docker 镜像的时候也是选择了使用 ARG
来动态地在构建镜像时参数化,可以参考文末 v2ray 的链接
ARG
还有一些内置的参数,有需要可以参考文末 docker 的文档
References
https://docs.docker.com/engine/reference/builder/#arg
https://github.com/WeihanLi/dotnet-httpie/blob/dev/Dockerfile
https://github.com/v2fly/docker/blob/master/Dockerfile
https://github.com/v2fly/docker/blob/master/.github/workflows/docker-push.yml