如何在 Docker 构建期间强制使用构建参数?

有没有办法在 docker build期间强制使用构建参数?如果缺少参数,那么预期的行为将是构建失败。

例如,对于以下 Dockerfile:

FROM ubuntu


ARG MY_VARIABLE
ENV MY_VARIABLE $MY_VARIABLE


RUN ...

我希望构建失败时,在 ARG MY_VARIABLE构建与 docker build -t my-tag .和通过时,与 docker build -t my-tag --build-arg MY_VARIABLE=my_value .构建。

有什么方法可以实现这种行为吗? 在我的例子中,设置一个默认值并没有真正起到作用。

(我正在 darwin/amd64上运行 Docker 1.11.1。)

编辑: 我能想到的一种方法是运行一个在 MY_VARIABLE为空时失败的命令,例如:

FROM ubuntu


ARG MY_VARIABLE
RUN test -n "$MY_VARIABLE"
ENV MY_VARIABLE $MY_VARIABLE


RUN ...

但这似乎并不是解决当前问题的一种非常惯用的方法。

24108 次浏览

你可以这么做。

 FROM ubuntu:14.04
ONBUILD ARG MY_VARIABLE
ONBUILD RUN if [ -z "$MY_VARIABLE" ]; then echo "NOT SET - ERROR"; exit 1; else : ; fi

然后是 docker build -t my_variable_base .

然后根据这个建立你的图像。

FROM my_variable_base
...

它不是 好极了干净的,但至少它抽象了“ bleh”的东西远离基础图像。

我用 RUN test -n <ARGvariablename>测试了@konradstrack 在原始(编辑)文章中提到的... ... 它似乎完成了强制将变量作为 docker build命令的构建时参数传递的工作:

FROM ubuntu


ARG MY_VARIABLE
RUN test -n "$MY_VARIABLE"
ENV MY_VARIABLE $MY_VARIABLE

您还可以使用 壳参数展开式壳参数展开式来实现这一点。

假设您的强制构建参数名为 MANDATORY_BUILD_ARGUMENT,并且您希望它被设置为非空,那么您的 Dockerfile 可以如下所示:

    FROM debian:stretch-slim
MAINTAINER Evel Knievel <evel@kniev.el>
    

ARG MANDATORY_BUILD_ARGUMENT
    

RUN \
# Check for mandatory build arguments
: "${MANDATORY_BUILD_ARGUMENT:?Build argument needs to be set and non-empty.}" \
    

# Install libraries
&&  apt-get update \
&&  apt-get install -y \
cowsay \
fortune \


# Cleanup
&&  apt-get clean \
&&  rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \


CMD ["/bin/bash", "-c", "/usr/games/fortune | /usr/games/cowsay"]

当然,与我不同的是,您可能还希望对某些内容使用 build 参数,但是我仍然建议构建这个 Dockerfile 并将其用于测试运行:)

剪辑

正如在 @ Jeffrey Wen 的回答中提到的,为了确保这个错误出现在 centos:7图像上(可能还有其他图像,我承认除了 stretch-slim我还没有在其他图像上测试过) :

确保使用 bash shell 执行 RUN 命令。

RUN ["/bin/bash", "-c", ": ${MYUID:?Build argument needs to be set and not null.}"]

我还不能评论,因为我没有50的声誉,但我想添加到@Jan Nash 的解决方案,因为我有一点困难,让它与我的形象工作。

如果您复制/粘贴@Jan Nash 的解决方案,它将工作并输出未指定构建参数的错误消息。

我想补充的是

当我试图让它在 CentOS 7映像(CentOS: 7)上工作时,Docker 运行 RUN命令 没有出错。

解决方案

确保使用 bash shell 执行 RUN命令。

RUN ["/bin/bash", "-c", ": ${MYUID:?Build argument needs to be set and not null.}"]

我希望这对未来的新人有所帮助。否则,我相信@Jan Nash 的解决方案非常聪明。

另一个简单的方法:

RUN test -n "$MY_VARIABLE" || (echo "MY_VARIABLE  not set" && false)

很久以前,我需要引入一个必需的(强制性的) ARG,并且为了更好的用户体验,在开始的时候包括检查:

FROM ubuntu:bionic
ARG MY_ARG
RUN [ -z "$MY_ARG" ] && echo "MY_ARG is required" && exit 1 || true


...


RUN ./use-my-arg.sh

但是 这会破坏每一层的构建缓存在最初的 MY_ARG之后,因为 MY_ARG=VALUE在之后的每个 RUN命令中都被预先设置。

每当我更改 MY_ARG时,它都会重新构建整个映像,而不是仅仅重新运行最后一个 RUN命令。

为了恢复缓存,我将构建更改为多阶段构建:

  • 第一阶段使用 MY_ARG并检查它的存在。
  • 第二阶段像往常一样进行,并在最后声明 ARG MY_ARG
FROM alpine:3.11.5
ARG MY_ARG
RUN [ -z "$MY_ARG" ] && echo "MY_ARG is required" && exit 1 || true


FROM ubuntu:bionic
...
ARG MY_ARG
RUN ./use-my-arg.sh

由于第二阶段中的 ARG MY_ARG声明为右 之前,因此使用它,该阶段中的所有前面的步骤都不受影响,因此可以正确缓存。

如果有人正在寻找解决方案,但对于 docker compose build,我使用了强制变量。

version: "3.9"
services:
my-service:
build:
context: .
args:
- ENVVAR=${ENVVAR:?See build instructions}

运行 docker compose build之后:

  • 在导出 ENVVAR: 无效模板: “必需变量 ENVVAR 缺少一个值: 请参阅构建说明”之前
  • 导出 ENVVAR: 建立收益之后

对所需环境变量的支持 编写环境变量

这些答案对我都不管用。我想要 ${MY_VARIABLE:?},但不想打印任何东西,所以我这样做:

ARG MY_VARIABLE
RUN test -n ${MY_VARIABLE:?}

没有任何东西是以成功为基础的。如果出现错误,你可以看到这一点,这是一个足够好的错误:

错误运行测试-n ${ MY _ VARIABLE: ? }
/bin/sh: MY _ VARIABLE: 参数未设置或为空
执行器运行[/bin/sh-c test-n ${ MY _ VARIABLE: ? }] : > 退出代码: 2失败