Dockerfile中使用ARG固定Alpine apk包版本失败求助
问题:Dockerfile中用ARG传递版本给apk add失败,能否用ARG设置版本?
问题场景
我编写了如下Dockerfile:
ARG ALPINE_VERSION=3.16.2 ARG GLAB_VERSION="1.22.0" ARG JQ_VERSION="1.6" FROM alpine:$ALPINE_VERSION RUN apk add --no-cache "glab~=${GLAB_VERSION}" "jq~=${JQ_VERSION}" ENTRYPOINT [ "glab" ]
尝试构建镜像时出现版本解析错误:
docker build -t gitlab/glab:latest . [+] Building 6.6s (5/5) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 258B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:3.16.2 2.0s => CACHED [1/2] FROM docker.io/library/alpine:3.16.2@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad 0.0s => ERROR [2/2] RUN apk add --no-cache "glab~=${GLAB_VERSION}" "jq~=${JQ_VERSION}" 4.4s ------ > [2/2] RUN apk add --no-cache "glab~=${GLAB_VERSION}" "jq~=${JQ_VERSION}": #5 1.009 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz #5 1.880 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz #5 4.227 ERROR: 'glab~=' is not a valid world dependency, format is name(@tag)([<>~=]version) ------ executor failed running [/bin/sh -c apk add --no-cache "glab~=${GLAB_VERSION}" "jq~=${JQ_VERSION}"]: exit code: 99
但将版本硬编码后构建就能成功:
RUN apk add --no-cache "glab~=1.22.0" "jq~=1.6"
构建结果:
docker build -t gitlab/glab:latest . [+] Building 17.5s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 239B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:3.16.2 0.6s => CACHED [1/2] FROM docker.io/library/alpine:3.16.2@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad 0.0s => [2/2] RUN apk add --no-cache "glab~=1.22.0" "jq~=1.6" 16.6s => exporting to image 0.2s => => exporting layers 0.2s => => writing image sha256:46bccd18a999a696ef9e80fb75983a6b5655a774b88b1412b55707cb152823e5 0.0s => => naming to docker.io/gitlab/glab:latest 0.0s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
核心疑问:能否通过ARG来设置这些版本?
解答
原因
问题出在ARG变量的作用域:你在FROM之前定义的ARG属于全局构建参数,但FROM之后的容器构建阶段默认不会继承这些参数,导致${GLAB_VERSION}和${JQ_VERSION}没有被正确替换,apk收到的是glab~=这种不完整的依赖格式,所以报错。
可行方案
完全可以用ARG设置版本,两种解决方式:
方案1:在FROM后重新声明ARG
在FROM指令之后,重新声明需要使用的ARG,让容器阶段能获取到全局参数的值:
ARG ALPINE_VERSION=3.16.2 ARG GLAB_VERSION="1.22.0" ARG JQ_VERSION="1.6" FROM alpine:$ALPINE_VERSION # 重新声明ARG,继承全局变量值 ARG GLAB_VERSION ARG JQ_VERSION RUN apk add --no-cache "glab~=${GLAB_VERSION}" "jq~=${JQ_VERSION}" ENTRYPOINT [ "glab" ]
方案2:去掉引号让shell先解析变量
如果不想重新声明ARG,可以去掉依赖项的引号,让shell先完成变量替换再传递给apk:
ARG ALPINE_VERSION=3.16.2 ARG GLAB_VERSION="1.22.0" ARG JQ_VERSION="1.6" FROM alpine:$ALPINE_VERSION RUN apk add --no-cache glab~=${GLAB_VERSION} jq~=${JQ_VERSION} ENTRYPOINT [ "glab" ]
注意:如果版本号包含空格、特殊字符,这种方式可能出问题,更推荐第一种方案,作用域更清晰。
验证
修改后执行docker build -t gitlab/glab:latest .,就能正常完成构建,效果和硬编码版本一致。
内容的提问来源于stack exchange,提问作者rj93
相关产品推荐
相关产品推荐

