Search code examples
dockerdockerfile

safe way to use build-time argument in Docker


I have a build time Argument with which I would like to build my Docker file; Since that argument is confidential in nature (github key of a private repo) I don't want that to end up in a docker image. This quotes is from official docker documentation regarding the build-time arguments.

Warning: It is not recommended to use build-time variables for passing secrets like github keys, user credentials etc. Build-time variable values are visible to any user of the image with the docker history command.

Anybody know what is the recommended way to achieve the same?


Solution

  • With docker 18.09+, that will be: docker build --secret id=mysecret,src=/secret/file (using buildkit).

    See PR 1288, announced in this tweet.
    --secret is now guarded by API version 1.39.

    Example:

    printf "hello secret" > ./mysecret.txt
    
    export DOCKER_BUILDKIT=1
    
    docker build --no-cache --progress=plain --secret id=mysecret,src=$(pwd)/mysecret.txt -f - . <<EOF
    # syntax = tonistiigi/dockerfile:secrets20180808
    FROM busybox
    RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
    RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
    EOF
    

    It sure would help if you could please extend this Dockerfile with an example of making the secret available in a Docker variable so it can be used, like to compose a URL for an artifact repository that requires credentials.
    I tried this but it did not work: RUN export MYSECRET=$(cat /foobar)

    The issue with setting the secret as an environment variable inside the Dockerfile (e.g., RUN export MYSECRET=$(cat /foobar)) is that environment variables do not persist between RUN instructions by default.
    And using ENV to store the secret would bake it into the image layers, making it visible to anyone who inspects the image: see docker inspect and "How to get ENV variable when doing docker inspect"

    The recommended approach is to use the secret in the same RUN instruction where it is read. That way, the secret is never stored as a persistent environment variable or in a layer—only used transiently during that particular build step.

    For example, if you want to use the secret to form a URL and fetch some artifact, you could do this:

    # syntax = tonistiigi/dockerfile:secrets20180808
    FROM busybox
    
    RUN --mount=type=secret,id=mysecret \
        sh -c 'MYSECRET=$(cat /run/secrets/mysecret) && \
               echo "Secret read, now using it in a command" && \
               curl -fSL "https://myrepo.com/artifact?token=${MYSECRET}" -o /artifact.tar.gz'
    

    MYSECRET is defined and used within the same sh -c command sequence. Once the RUN step completes, MYSECRET and the secret file are gone.