skip to Main Content

I want to use an env variable within Docker container.
By using a Makefile.
This variable only exists in Docker container.

I wrote a Makefile for reusing code in CICD pipeline.
But I have problems with right escaping of the passing variable.

Makefile

execute:
    @echo $(COMMAND)
    docker exec -it my-dev-container $(COMMAND)

Empty result of Makefile

$ make execute COMMAND="bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'"
bash -c echo
<< EMPTY >>

Expected result of Makefile:

$ make execute COMMAND="bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'"
I_AM_A_VARIABLE_VALUE_WITHIN_THE_CONTAINER

Without Makefile it’s working:

docker exec -it my-dev-container bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'  
I_AM_A_VARIABLE_VALUE_WITHIN_THE_CONTAINER

Any ideas how to escape the string correctly?

2

Answers


  1. Make variables are simple strings, and Make doesn’t have any way to escape a multi-word string so that it’s safe to pass to a shell context. For this to work as you’ve shown it, you need to escape the string in your host shell so that Make receives the string it needs to run the subcommand.

    In your setup, you need COMMAND to have the value

    bash -c 'echo $V'
    

    where the single quotes and dollars sign are part of the string. When you type make, you need to quote this (and especially the dollars sign) on the host:

    make execute COMMAND="bash -c 'echo $V'"
    

    You don’t seem to be using Make as a build system here, and the fragment you’ve shown doesn’t suggest dependencies on any other build rules. It may be simpler to just run the docker exec command you’ve shown (or, better, a standalone docker run command), or to use some other technology like a shell script for a wrapper tool.

    Login or Signup to reply.
  2. You have two escaping problems. The first problem is you have to escape the $ from the shell. By using double-quotes you are not escaping the $ from the shell: running echo "$foo" prints the value of the shell variable foo, it doesn’t print the string $foo.

    So when you run make COMMAND="bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'", the shell will expand $VARIABLE_ONLY_EXIST_IN_CONTAINER before it even invokes make which is not what you want. To avoid this you either have to use single-quotes or use a backslash:

    make COMMAND="bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'"
    

    Secondly, you need to escape the $ from make because that’s also a special character to make. If you only use the above then make will expand $V as a make variable which also won’t do what you want. In make you escape a $ by writing it twice, like $$

    You have two choices: you can either add the escaping on the command line, like this:

    make COMMAND="bash -c 'echo $$VARIABLE_ONLY_EXIST_IN_CONTAINER'"
    

    Or if you’re sure that you never want to expand anything in COMMAND as a make variable or function, you can use the GNU Make value function, like this:

    execute:
             @echo $(value COMMAND)
             docker exec -it my-dev-container $(value COMMAND)
    

    and running make COMMAND="bash -c 'echo $VARIABLE_ONLY_EXIST_IN_CONTAINER'" will do what you want.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search