skip to Main Content

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.

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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"]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search