设置 Docker 环境变量并在下一个 RUN 命令中使用它:

huangapple go评论66阅读模式
英文:

Docker: How to set env variable in one RUN command and use it in next RUN command?

问题

I'm trying to set a variable in a RUN command and use it in the next RUN command.

Depending on the TARGETARCH arg, I'm trying to set PROTOC_ARCH variable and use it in the next RUN command to download an architecture-specific file. But the variable isn't passing through. If I print the variable, it's always empty.

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

Can anyone please tell me what I'm doing wrong here?

Thanks in advance.

英文:

I'm trying to set a variable in a RUN command and use it in the next RUN command.

Depending on the TARGETARCH arg, I'm trying to set PROTOC_ARCH variable and use it in the next RUN command to download a architecture specific file. But the variable isn't passing through. If I print the variable, it's always empty.

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

Can anyone please tell me what I'm doing wrong here ?

Thanks in advance.

答案1

得分: 3

以下是您要的中文翻译部分:

不应将您的 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"]

希望这对您有所帮助。

英文:

You should not think of your Dockerfile in the same way we think about shell scripts, with state. However, you can move your heavy lifting into a shell script to access desired functionality. Example Dockerfile:

FROM ubuntu

ARG TARGETARCH="arm64"
ENV TARGETARCH=$TARGETARCH

COPY init.sh /
RUN chmod +x /init.sh

CMD /init.sh

And then your init.sh could look like this:

#!/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

Now you can access the env vars you expect and do conditional downloads, etc.

This pattern is quite common. You will find a lot of docker images using:

ENTRYPOINT ["docker-entrypoint.sh"]

答案2

得分: 1

每个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语句中没有一种条件设置变量的方式。

英文:

Each RUN statement is run in a separate shell. That means that any environment variables you set are lost when the RUN statement finishes.

What you can do is run all your commands in a single RUN statement, like this

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

Then PROTOC_ARCH will be available in the wget command, since it's not lost until the complete RUN statement is finished.

One thing to note is that at run-time, PROTOC_ARCH will be blank, since it's the value set in the ENV statement that is put in the image. AFAIK, there's no way to conditionally set a variable in an ENV statement.

huangapple
  • 本文由 发表于 2023年3月31日 02:02:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75891535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定