如何在Docker构建过程中强制使用构建参数?

jgovgodb  于 2022-11-28  发布在  Docker
关注(0)|答案(8)|浏览(191)

docker build期间,是否有任何方法可以强制使用构建参数?如果缺少参数,预期的行为将是构建失败。
例如,对于以下Dockerfile:

FROM ubuntu

ARG MY_VARIABLE
ENV MY_VARIABLE $MY_VARIABLE

RUN ...

我希望使用docker build -t my-tag .构建时,构建在ARG MY_VARIABLE处失败,使用docker build -t my-tag --build-arg MY_VARIABLE=my_value .构建时通过。
有什么方法可以实现这种行为吗?在我的例子中,设置一个默认值并不能真正达到这个目的。
(我在darwin/amd64上运行Docker 1.11.1。)

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

FROM ubuntu

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

RUN ...

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

au9on6nz

au9on6nz1#

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

FROM ubuntu

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

mklgxw1f2#

您也可以使用shell parameter expansion来实现这一点。
假设您的强制构建参数名为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"]

当然,您也可能希望使用构建参数,这与我所做的不同,但我仍然建议构建此Dockerfile并对其进行测试运行:)

编辑

正如在@Jeffrey Wen的回答中提到的,为了确保在centos:7图像上(可能还有其他图像,我承认我没有在stretch-slim以外的其他图像上测试过):
确保您正在使用bash shell执行RUN命令。
RUN ["/bin/bash", "-c", ": ${MYUID:?Build argument needs to be set and not null.}"]

mf98qq94

mf98qq943#

另一个简单道:

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

5m1hhzi44#

很久以前,我需要引入一个必需的(强制性的)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是在它被使用 * 之前 * 声明的,因此该阶段中的所有先前步骤都不受影响,因此缓存正确。

k4aesqcs

k4aesqcs5#

你可以这样做...

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”的东西抽象到了基础图像中。

kknvjkwl

kknvjkwl6#

我还不能发表评论,因为我没有50的声望,但我想补充到@扬纳什的解决方案,因为我有一点困难,让它与我的形象工作。
如果您复制/粘贴@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.}"]
我希望这对未来的新人有帮助。否则,我相信“扬·纳什的解决方案是非常棒的。”

hwazgwia

hwazgwia7#

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

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

运行docker compose build后:

  • 导出ENVVAR之前:无效的模板:“必需的变量ENVVAR缺少值:请参见构建说明”
  • 导出ENVVAR后:* 建造收益 *

Support for Required Environment variablesCompose Environment Variables显示器

au9on6nz

au9on6nz8#

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

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

成功时不会打印任何内容。如果出现错误,您会看到以下内容,这是一个足够好的错误:
运行测试时出错-n ${MY_VARIABLE:?}
/bin/sh:我的变量:参数未设置或为空
执行程式无法执行[/bin/sh -c test -n ${MY_VARIABLE:?}]:〉退出代码:2

相关问题