Michaël Perrin
Michaël Perrin

Reputation: 6238

Expand environment variable inside container on Docker command line

Suppose that I create a Dockerfile that just runs an echo command:

FROM alpine
ENTRYPOINT [ "echo" ]

and that I build it like this:

docker build -t my_echo .

If I run docker run --rm my_echo test it will output test as expected.

But how can I run the command to display an environment variable that is inside the container?

Example:

docker run --rm --env MYVAR=foo my_echo ???

How to access the $MYVAR variable that is in the container to display foo by replacing the ??? part of that command?


Note: This is a simplified version of my real use case. My real use case is a WP-CLI Docker image that I built with a Dockerfile. It has the wp-cli command as the ENTRYPOINT.

I am trying to run a container based on this image to update a WordPress parameter with an environment variable. My command without Docker is wp-cli option update siteurl "http://example.com" where http://example.com would be in an environment variable.

This is the command I am trying to run (wp_cli is the name of my container):

docker run --rm --env WEBSITE_URL="http://example.com" wp_cli option update siteurl ???

Upvotes: 0

Views: 2290

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295308

It's possible to have the argument that immediately follows ["bash", "-c"] itself be a shell script that looks for sigils to replace. For example, consider the following script, which I'm going to call argEnvSubst:

#!/usr/bin/env bash
args=( "$@" )                           # collect all arguments into a single array
for idx in "${!args[@]}"; do            # iterate over the indices of that array...
  arg=${args[$idx]}                     # ...and collect the associated values.
  if [[ $arg =~ ^@ENV[.](.*)@$ ]]; then # if we have a value that matches a pattern...
    varname=${BASH_REMATCH[1]}          # extract the variable name from that pattern
    args[$idx]=${!varname}              # and replace the value with a lookup result
  fi
done
exec "${args[@]}"                       # run our resulting array as a command.

Thus, argEnvSubst "echo" "@ENV.foobar@" will replace @ENV.foobar@ with the value of the environment named foobar before it invokes echo.


While I would strongly suggest injecting this into your Dockerfile as a separate script and naming that script as your ENTRYPOINT, it's possible to do it in-line:

ENTRYPOINT [ "bash", "-c", "args=(\"$@\"); for idx in \"${!args[@]}\"; do arg=${args[$idx]}; if [[ $arg =~ ^@ENV[.](.*)@$ ]]; then varname=${BASH_REMATCH[1]}; args[$idx]=${!varname}; fi; done; \"${args[@]}\"", "_" ]

...such that you can then invoke:

docker run --rm --env WEBSITE_URL="http://example.com" \
       wp_cli option update siteurl '@ENV.WEBSITE_URL@'

Note the use of bash -- this means alpine (providing only dash) isn't sufficient.

Upvotes: 1

Related Questions