How to make a build arg mandatory during Docker build?

后端 未结 6 1931
后悔当初
后悔当初 2020-12-23 16:15

Is there any way to make a build argument mandatory during docker build? The expected behaviour would be for the build to fail if the argument is missing.

相关标签:
6条回答
  • 2020-12-23 16:37

    Another simple way:

    RUN test -n "$MY_VARIABLE" || (echo "MY_VARIABLE  not set" && false)
    
    0 讨论(0)
  • 2020-12-23 16:44

    Long time ago I had a need to introduce a required (mandatory) ARG, and for better UX include the check at the beginning:

    FROM ubuntu:bionic
    ARG MY_ARG
    RUN [ -z "$MY_ARG" ] && echo "MY_ARG is required" && exit 1 || true
    
    ...
    
    RUN ./use-my-arg.sh
    

    But this busts the build cache for every single layer after the initial MY_ARG, because MY_ARG=VALUE is prepended to every RUN command afterwards.

    Whenever I changed MY_ARG it would end up rebuilding the whole image, instead of rerunning the last RUN command only.

    To bring caching back, I have changed my build to a multi-staged one:

    • The first stage uses MY_ARG and checks it's presence.
    • The second stage proceeds as usual and declares ARG MY_ARG right at the end.
    FROM alpine:3.11.5
    ARG MY_ARG
    RUN [ -z "$MY_ARG" ] && echo "MY_ARG is required" && exit 1 || true
    
    FROM ubuntu:bionic
    ...
    ARG MY_ARG
    RUN ./use-my-arg.sh
    

    Since ARG MY_ARG in the second stage is declared right before it's used, all the previous steps in that stage are unaffected, thus cache properly.

    0 讨论(0)
  • 2020-12-23 16:47

    I cannot comment yet because I do not have 50 reputation, but I would like to add onto @Jan Nash's solution because I had a little difficulty getting it to work with my image.

    If you copy/paste @Jan Nash's solution, it will work and spit out the error message that the build argument is not specified.

    What I want to add

    When I tried getting it to work on a CentOS 7 image (centos:7), Docker ran the RUN command without erroring out.

    Solution

    Ensure that you're executing the RUN command with the bash shell.

    RUN ["/bin/bash", "-c", ": ${MYUID:?Build argument needs to be set and not null.}"]

    I hope that helps for future incoming people. Otherwise, I believe @Jan Nash's solution is just brilliant.

    0 讨论(0)
  • 2020-12-23 16:52

    I tested with RUN test -n <ARGvariablename> what @konradstrack mentioned in the original (edit) post... that seems do the job of mandating the variable to be passed as the build time argument for the docker build command:

    FROM ubuntu
    
    ARG MY_VARIABLE
    RUN test -n "$MY_VARIABLE"
    ENV MY_VARIABLE $MY_VARIABLE
    
    0 讨论(0)
  • 2020-12-23 16:53

    You can also use shell parameter expansion to achieve this.

    Let's say your mandatory build argument is called MANDATORY_BUILD_ARGUMENT, and you want it to be set and non-empty, your Dockerfile could look like this:

        FROM debian:stretch-slim
        MAINTAINER Evel Knievel <evel@kniev.el>
    
        ARG MANDATORY_BUILD_ARGUMENT
    
        RUN \
        # Check for mandatory build arguments
            : "${MANDATORY_BUILD_ARGUMENT:?Build argument needs to be set and non-empty.}" \
    
        # Install libraries
        &&  apt-get update \
        &&  apt-get install -y \
                cowsay \
                fortune \
    
        # Cleanup
        &&  apt-get clean \
        &&  rm -rf \
                /var/lib/apt/lists/* \
                /var/tmp/* \
                /tmp/* \
    
        CMD ["/bin/bash", "-c", "/usr/games/fortune | /usr/games/cowsay"]
    

    Of course, you would also want to use the build-argument for something, unlike I did, but still, I recommend building this Dockerfile and taking it for a test-run :)

    0 讨论(0)
  • 2020-12-23 16:54

    You could do something like this...

     FROM ubuntu:14.04
     ONBUILD ARG MY_VARIABLE
     ONBUILD RUN if [ -z "$MY_VARIABLE" ]; then echo "NOT SET - ERROR"; exit 1; else : ; fi
    

    Then docker build -t my_variable_base .

    Then build your images based on this...

    FROM my_variable_base
    ...
    

    It's not super clean, but at least it abstracts the 'bleh' stuff away to the base image.

    0 讨论(0)
提交回复
热议问题