使用--build-arg参数构建Docker镜像,该参数允许传入多个参数。

413
根据文档,可以为标志--build-arg定义多个参数,但我不知道如何操作。我尝试了以下方法:
docker build -t essearch/ess-elasticsearch:1.7.6 --build-arg number_of_shards=5 number_of_replicas=2 --no-cache .

=> 这会返回一个错误。

我还尝试了:

docker build -t essearch/ess-elasticsearch:1.7.6 --build-arg number_of_shards=5,number_of_replicas=2 --no-cache .

=> 这将一个变量,number_of_shards, 设置为值"5,number_of_replicas=2"

你有没有想过如何定义多个参数?

6个回答

824

每个参数都需要使用 --build-arg

如果您要传递两个参数,则需在每个参数后添加 --build-arg,例如:

docker build \
-t essearch/ess-elasticsearch:1.7.6 \
--build-arg number_of_shards=5 \
--build-arg number_of_replicas=2 \
--no-cache .

118
感谢您澄清这个问题。--help上的描述特别具有误导性:--build-arg list。它并不是一个列表! - cowlinator
8
可能已经过时了...我一直收到 "docker build" requires exactly 1 argument. 的错误提示。 - Sandburg
2
需要的“正好1个参数”是目录(在此示例的末尾为“.”)。 - Jason Orendorff
1
对于多行 --build-arg:https://dev59.com/qFUL5IYBdhLWcg3weH4j#50299998 - prayagupa
如果是这种情况,那么文档似乎是错误的。根据 "docker build --help" 的描述,--build_arg 被描述为一个列表。但如果我每次都要重复整个参数并且只有一个值,那么它并没有真正指定一个列表。 - shawn1874
“docker build” 需要且只能接受一个参数的错误信息有误导性!请确保您传递的参数不为空!(例如,如果您将一个变量注入到 docker build 命令中)。正如前面提到的,您需要为每个要传递的参数使用单独的 build-arg 标志。 - undefined

185
pl_rock所提供的答案是正确的,我想补充一点的是,如果没有在Dockerfile中预期ARG,则无法访问它。因此,如果您正在进行

docker build -t essearch/ess-elasticsearch:1.7.6 --build-arg number_of_shards=5 --build-arg number_of_replicas=2 --no-cache .

然后在Dockerfile内应添加以下内容:

ARG number_of_replicas
ARG number_of_shards

我遇到了这个问题,所以希望能在未来帮助到某些人(包括我自己)。


21
你也帮助了我,所以谢谢你。让我补充一点,ARGS 必须在 FROM 之后声明。 - Edoardo
20
哇,谢谢!在https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg中甚至没有提到使用`ARG`,而且没有`ARG`的情况下`--build-arg`对我来说毫无用处。 - HeyWatchThis
3
在 FROM... 之前对我也没用 :-/ - ibz
请注意,如果您计划在容器启动后利用环境变量,则使用相同的模式,只是您的Docker文件将使用ENV而不是ARG。https://dev59.com/blkS5IYBdhLWcg3woIJR - user6866797
这个问题浪费了我太多的时间。顺便说一下,这是文档,它明确说明ARG必须在FROM之后使用(如果我理解正确的话,在FROM之前的所有步骤中也可以使用ARG)。 - Greg7000

70

如果您想在构建过程中使用环境变量,比如设置用户名和密码。

username= Ubuntu
password= swed24sw

Dockerfile

FROM ubuntu:16.04
ARG SMB_PASS
ARG SMB_USER
# Creates a new User
RUN useradd -ms /bin/bash $SMB_USER
# Enters the password twice.
RUN echo "$SMB_PASS\n$SMB_PASS" | smbpasswd -a $SMB_USER

终端命令

docker build --build-arg SMB_PASS=swed24sw --build-arg SMB_USER=Ubuntu . -t IMAGE_TAG

该命令用于构建Docker镜像,并设置SMB用户和密码。请注意替换IMAGE_TAG为所需的标签名称。

23
请注意,这将使得使用 docker history 命令可以查看到 Docker 镜像中的秘密值。 - Gary

19

遗憾的是我们需要多个ARG,这会导致多层次和减慢构建速度,并且对于任何人来说也会有疑问,当前没有一种方法可以在一行中设置多个ARG。


2
这可以与multi stage builds结合使用,以减少最终构建图像上的层数。 - deepakkt
这并没有回答如何设置多个构建参数的问题。使用buildkit,您将看不到执行单独步骤,而使用经典构建,则不会生成文件系统层中的额外步骤。 - BMitch
这个答案可能会引导误解。事实是,没有办法在一行中设置多个参数。但是,多个参数肯定是被支持的。 - Willem
1
澄清了该声明。 - Vlad Kolbaia
ARG指令在现代Docker中不会创建新的层。 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers - Dzenly

15

如果您想从特定文件中自动传递构建参数,可以按照以下方式进行:

docker build  $(cat .my-env-file-name | while read line; do out+="--build-arg $line"; done; echo $out; out="") .

我想不出原因,但如果在命令替换$()周围加上引号,会导致docker build失败。 它会失去'=value'部分。 这让我疯狂了一段时间! 你有任何想法为什么吗? - vampiire
get_build_args() { for build_arg in "${BUILD_ARGS[@]}"; do out+="--build-arg $build_arg " done echo -n "$out" }我写这个函数是假设 BUILD_ARGS 是一个由 ARG_NAME=VALUE 元素组成的数组。它可以正常工作,当我回显输出时一切都在那里。但是,当我将其替换为 docker build 命令时,如果我加上引号,它就会出错。我真的很困惑。 - vampiire
build_args=get_build_args echo $build_args echo "$build_args" docker build $build_args . docker build "$build_args" . - vampiire

8
使用 xargs 将构建参数从文件传递进来的方式如下所示:
cat .MY_ENV_FILE | xargs printf -- '--build-arg %s\n' | xargs docker build -t MY_TAG .

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - mbuechmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接