我有以下Dockerfile:
FROM golang:1.19.2-bullseye@sha256:2fddf0539591f8e364c9adb3d495d1ba2ca8a8df420ad23b58e7bcee7986ea6c as gobuilder
ARG CGO_ENABLED
ARG CGO_CFLAGS
RUN set -x && \
printf 'package main\nimport (\n\t"fmt"\n\t"os"\n)\nfunc main(){\n\tfmt.Println(os.Getenv("CGO_CFLAGS"))\n}\n' > main.go && \
cat main.go && \
CGO_ENABLED="${CGO_ENABLED}" CGO_CFLAGS="${CGO_CFLAGS}" go build main.go && \
ls && \
CGO_CFLAGS="${CGO_CFLAGS}" ./main
字符串
(Yes我知道FROM
行中的as gobuilder
部分是不必要的,让我们暂时忽略它。
当我构建这个时,set -x
输出没有正确引用构建参数:
$ docker build -t mre --build-arg CGO_ENABLED=1 --build-arg CGO_CFLAGS='-Wall -Wextra' .
Sending build context to Docker daemon 13.82kB
Step 1/4 : FROM golang:1.19.2-bullseye@sha256:2fddf0539591f8e364c9adb3d495d1ba2ca8a8df420ad23b58e7bcee7986ea6c as gobuilder
---> dce494d5814b
Step 2/4 : ARG CGO_ENABLED
---> Using cache
---> 39d4b3dd0c4e
Step 3/4 : ARG CGO_CFLAGS
---> Using cache
---> bfdf4834ae3b
Step 4/4 : RUN set -x && printf 'package main\nimport (\n\t"fmt"\n\t"os"\n)\nfunc main(){\n\tfmt.Println(os.Getenv("CGO_CFLAGS"))\n}\n' > main.go && cat main.go && CGO_ENABLED="${CGO_ENABLED}" CGO_CFLAGS="${CGO_CFLAGS}" go build main.go && ls && CGO_CFLAGS="${CGO_CFLAGS}" ./main
---> Running in 1936a6076a84
+ printf package main\nimport (\n\t"fmt"\n\t"os"\n)\nfunc main(){\n\tfmt.Println(os.Getenv("CGO_CFLAGS"))\n}\n
+ cat main.go
package main
import (
"fmt"
"os"
)
func main(){
fmt.Println(os.Getenv("CGO_CFLAGS"))
}
+ CGO_ENABLED=1 CGO_CFLAGS=-Wall -Wextra go build main.go
+ ls
bin
main
main.go
src
+ CGO_CFLAGS=-Wall -Wextra ./main
-Wall -Wextra
Removing intermediate container 1936a6076a84
---> a5c293ba4ba8
Successfully built a5c293ba4ba8
Successfully tagged mre:latest
型
请注意,main
二进制文件输出预期的环境变量值,但我希望看到CGO_CFLAGS
部分像+ CGO_CFLAGS='-Wall -Wextra' ./main
一样被引用。同样,我希望在go build
命令中引用:
+ CGO_ENABLED=1 CGO_CFLAGS='-Wall -Wextra' go build main.go
型
为了进行比较,我尝试了一个带有不同基础镜像的不同Dockerfile的示例。
Dockerfile:
FROM alpine:3.17.3
ARG ENV_VAR1
RUN set -x && ENV_VAR1="${ENV_VAR1}" ENV_VAR2='hello world' true 'minimal reproducible example'
型
构建输出:
$ docker build -t mre2 --build-arg ENV_VAR1='foo bar' .
Sending build context to Docker daemon 13.82kB
Step 1/3 : FROM alpine:3.17.3
---> 9ed4aefc74f6
Step 2/3 : ARG ENV_VAR1
---> Running in 182a965d4c83
Removing intermediate container 182a965d4c83
---> fc5f7f7f2e01
Step 3/3 : RUN set -x && ENV_VAR1="${ENV_VAR1}" ENV_VAR2='hello world' true 'minimal reproducible example'
---> Running in 6ebec9bed99a
+ ENV_VAR1='foo bar' ENV_VAR2='hello world' true 'minimal reproducible example'
Removing intermediate container 6ebec9bed99a
---> 5e1901518b51
Successfully built 5e1901518b51
Successfully tagged mre2:latest
型
注意线上
+ ENV_VAR1='foo bar' ENV_VAR2='hello world' true 'minimal reproducible example'
型
两个环境变量都如我所料被引用了。
我想帮助理解为什么基于golang:1.19.2-bullseye
基础镜像的Docker构建中不包含引号。
对于上下文,我希望能够在我的构建中看到引用,这样我就可以确保我所有的命令都被shell扩展和引用。但是如果引用不起作用,我就不能轻易地验证这一点。
1条答案
按热度按时间7gcisfzg1#
一个更好的解决方法是不依赖
set -x
来显示您想要的格式。字符串
输出会稍微少一些(如果你真的想看到所有的东西,当然可以放回
set -x
;但是要知道输出格式将依赖于shell),但是这样,你就可以完全控制printf
以明确的格式显示变量值。将
ARG
变量恢复为它们本身基本上是不必要的(正如在注解中提到的);但我保留它们只是为了演示如何在当前RUN
指令的剩余时间内设置一次变量。(You我还注意到我重构了第一个
printf
。我想如果你真的想的话,你可以在源文件中获得制表符缩进;但对我来说,易读性胜过完全控制。)