How to unset “ENV” in dockerfile?

后端 未结 5 411
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-07 22:03

For some certain reasons, I have to set \"http_proxy\" and \"https_proxy\" ENV in my dockerfile. I would like to now unset them because there are also some buil

相关标签:
5条回答
  • 2021-01-07 22:42

    I found the secret approach didn't work because I needed the env variable to persist in the container when I ran it in interactive mode but then needed to completely remove the variable for a later stage build for production.

    What worked was in building for the development phase I appended the environment variable to the /root/.basrc file as

    RUN echo export AWS_PROFILE=role-name >> /root/.bashrc
    ``
    
    In the production stage of the build I then removed the last line of /root/.bashrc:
    

    RUN sed -i '$ d' /root/.bashrc

    0 讨论(0)
  • 2021-01-07 22:45

    According to docker docs you need to use shell command instead:

    FROM alpine
    RUN export ADMIN_USER="mark" \
    && echo $ADMIN_USER > ./mark \
    && unset ADMIN_USER
    CMD sh
    

    See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#env for more details.

    0 讨论(0)
  • 2021-01-07 22:45

    If one needs env vars during the image build but they should not persist, just clear them. In the following example, the running container shows empty env vars.

    Dockerfile

    # set proxy
    ARG http_proxy
    ARG https_proxy
    ARG no_proxy
    ENV http_proxy=$http_proxy
    ENV https_proxy=$http_proxy
    ENV no_proxy=$no_proxy
    
    # ... do stuff that needs the proxy during the build, like apt-get, curl, et al.
    
    # unset proxy
    ENV http_proxy=
    ENV https_proxy=
    ENV no_proxy=
    

    build.sh

    docker build -t the-image \
        --build-arg http_proxy="$http_proxy" \
        --build-arg https_proxy="$http_proxy" \
        --build-arg no_proxy="$no_proxy" \
        --no-cache \
        .
    

    run.sh

    docker run --rm -i \
        the-image \
        sh << COMMANDS
            env
    COMMANDS
    

    Output

    no_proxy=
    https_proxy=
    http_proxy=
    ...
    
    0 讨论(0)
  • 2021-01-07 22:48

    It depends on what effect you are trying to achieve.

    Note that, as a matter of pragmatics (i.e. how developers actually speak), "unsetting a variable" can mean two things: removing it from the environment, or setting the variable to an empty value. Technically, these are two different operations. In practice though I have not run into a case where the software I'm trying to control differentiates between the variable being absent from the environment, and the variable being present in the environment but set to an empty value. I generally can use either method to get the same result.

    If you don't care whether the variable is in the layers produced by Docker, but leaving it with a non-empty value causes problems in later build steps.

    For this case, you can use ENV VAR_NAME= at the point in your Dockerfile from which you want to unset the variable. Syntactic note: Docker allows two syntaxes for ENV: this ENV VAR=1 is the same as ENV VAR 1. You can separate the variable name from the value with a space or an equal sign. When you want to "unset" a variable by setting it to an empty value you must use the equal sign syntax or you get an error at build time.

    So for instance, you could do this:

    ENV NOT_SENSITIVE some_value
    RUN something
    
    ENV NOT_SENSITIVE=
    RUN something_else
    

    When something runs, NOT_SENSITIVE is set to some_value. When something_else runs, NOT_SENSITIVE is set to the empty string.

    It is important to note that doing unset NOT_SENSITIVE as a shell command will not affect anything else than what executes in this shell. Here's an example:

    ENV NOT_SENSITIVE some_value
    RUN unset NOT_SENSITIVE && printenv NOT_SENSITIVE || echo "does not exist"
    
    RUN printenv NOT_SENSITIVE
    

    The first RUN will print does not exist because NOT_SENSITIVE is unset when printenv executes and because it is unset printenv returns a non-zero exit code which causes the echo to execute. The second RUN is not affected by the unset in the first RUN. It will print some_value to the screen.

    But what if I need to remove the variable from the environment, not just set it to an empty value?

    In this case using ENV VAR_NAME= won't work. I don't know of any way to tell Docker "from this point on, you must remove this variable from the environment, not just set it to an empty value".

    If you still want to use ENV to set your variable, then you'll have to start each RUN in which you want the variable to be unset with unset VAR_NAME, which will unset it for that specific RUN only.

    If you want to prevent the variable from being present in the layers produced by Docker.

    Suppose that variable contains a secret and the layer could fall into the hands of people who should not have the secret. In this case you CANNOT use ENV to set the variable. A variable set with ENV is baked into the layers to which it applies and cannot be removed from those layers. In particular, (assuming the variable is named SENSITIVE) running

    RUN unset SENSITIVE
    

    does not do anything to remove it from the layer. The unset command above only removes SENSITIVE from the shell process that RUN starts. It affects only that shell. It won't affect shells spawned by CMD, ENTRYPOINT, or any command provided through running docker run at the command line.

    In order to prevent the layers from containing the secret, I would use docker build --secret= and RUN --mount=type=secret.... For instance, assuming that I've stored my secret in a file named sensitive, I could have a RUN like this:

    RUN --mount=type=secret,id=sensitive,target=/root/sensitive \
     export SENSITIVE=$(cat /root/sensitive) \
     && [[... do stuff that requires SENSITIVE ]] \
    

    Note that the command given to RUN does not need to end with unset SENSITIVE. Due to the way processes and their environments are managed, setting SENSITIVE in the shell spawned by RUN does not have any effect beyond what that shell itself spawns. Environment changes in this shell won't affect future shells nor will it affect what Docker bakes into the layers it creates.

    Then the build can be run with:

    $ DOCKER_BUILDKIT=1 docker build --secret id=secret,src=path/to/sensitive [...]
    

    The environment for the docker build command needs DOCKER_BUILDKIT=1 to use BuildKit because this method of passing secrets is only available if Docker uses BuildKit to build the images.

    0 讨论(0)
  • 2021-01-07 23:03

    You can add below lines in the Dockerfile

    ENV http_proxy ""
    ENV https_proxy ""
    
    0 讨论(0)
提交回复
热议问题