我试图在RUN
命令中设置一个变量,并在下一个RUN
命令中使用它。
根据TARGETARCH
参数,我试图设置PROTOC_ARCH
变量并在下一个RUN
命令中使用它来下载特定于体系结构的文件。但是变量没有通过。如果我打印这个变量,它总是空的。
FROM ubuntu
ARG TARGETARCH="arm64"
ENV PROTOC_ARCH=""
RUN if [ "$TARGETARCH" = "arm64" ]; then
PROTOC_ARCH="aarch_64";
else
PROTOC_ARCH="x86_64";
fi
RUN apt-get update && apt-get install -y wget
RUN echo "PROTOC_ARCH=$PROTOC_ARCH"
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v22.2/protoc-22.2-linux-$PROTOC_ARCH.zip
谁能告诉我我哪里做错了?
提前感谢。
你不应该把你的Dockerfile想象成shell脚本那样,有状态。但是,您可以将繁重的工作转移到shell脚本中以访问所需的功能。示例Dockerfile
:
FROM ubuntu
ARG TARGETARCH="arm64"
ENV TARGETARCH=$TARGETARCH
COPY init.sh /
RUN chmod +x /init.sh
CMD /init.sh
然后你的init.sh
可以像这样:
#!/bin/bash
if [ "$TARGETARCH" = "arm64" ]; then
PROTOC_ARCH="aarch_64"
else
PROTOC_ARCH="x86_64"
fi
echo PROTOC_ARCH is $PROTOC_ARCH and TARGETARCH is $TARGETARCH
现在你可以访问你想要的环境变量,并进行条件下载,等等。
这种模式很常见。你会发现很多docker镜像使用:
ENTRYPOINT ["docker-entrypoint.sh"]
每个RUN语句在单独的shell中运行。这意味着当RUN语句结束时,您设置的任何环境变量都将丢失。
可以做的是在一个run语句中运行所有的命令,就像这样
FROM ubuntu
ARG TARGETARCH="arm64"
ENV PROTOC_ARCH=""
RUN if [ "$TARGETARCH" = "arm64" ]; then
PROTOC_ARCH="aarch_64";
else
PROTOC_ARCH="x86_64";
fi &&
apt-get update && apt-get install -y wget &&
echo "PROTOC_ARCH=$PROTOC_ARCH" &&
wget https://github.com/protocolbuffers/protobuf/releases/download/v22.2/protoc-22.2-linux-$PROTOC_ARCH.zip
那么PROTOC_ARCH
将在wget
命令中可用,因为它在完整的RUN语句完成之前不会丢失。
需要注意的一点是,在运行时,PROTOC_ARCH
将为空,因为它是放在图像中的ENV语句中设置的值。我知道,在ENV语句中没有办法有条件地设置变量。