Home > Mobile >  Use ENV Variables as flags for python script in dockerfile? (Boolean Flags)
Use ENV Variables as flags for python script in dockerfile? (Boolean Flags)

Time:10-29

Lets say I have the following python script

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--host", required=True)
parser.add_argument("--enabled", default=False, action="store_true")
args = parser.parse_args()

print("host: "   args.host)
print("enabled: "   str(args.enabled))
$ python3 test.py --host test.com
host: test.com
enabled: False

$ python3 test.py --host test.com --enabled
host: test.com
enabled: True

Now the script is used in a docker image and I want to pass the variables in docker run. For the host parameter it is quite easy

FROM python:3.10-alpine

ENV MY_HOST=default.com
#ENV MY_ENABLED=

ENV TZ=Europe/Berlin

WORKDIR /usr/src/app

COPY test.py .

CMD ["sh", "-c", "python test.py --host ${MY_HOST}"]

But how can I can make the --enabled flag to work? So when the/an ENV is unset or is 0 or off ore something, --enabled should be suppressed, otherwise it should be included in the CMD.

Is is possible without modify the python script?

CodePudding user response:

For exactly the reasons you're showing here, I'd suggest modifying your script to be able to accept command-line options from environment variables. If you add a line

parser.set_defaults(
  host=os.environ.get('MY_HOST'),
  enabled=(os.environ.get('MY_ENABLED') == 'true')
)

then you can use docker run -e options to provide these values, without the complexity of trying to reconstruct the command line based on which options are and aren't present. (Also see Setting options from environment variables when using argparse.)

CMD ["./test.py"] # a fixed string, environment variables specified separately
docker run -e MY_HOST=example.com -e MY_ENABLED=true my-image

Conversely, you can provide the entire command line and its options when you run the container. (But depending on the context you might just be pushing the "how to construct the command" question up a layer.)

docker run my-image \
  ./test.py --host=example.com --enabled

In principle you can construct this using a separate shell script without modifying your Python script, but it will be somewhat harder and significantly less safe. That script could look something like

#!/bin/sh

TEST_ARGS="--host $MY_HOST"
if [ -n "$MY_ENABLED" ]; then
  TEST_ARGS="$TEST_ARGS --enabled"
fi

exec ./test.py $TEST_ARGS
#              ^^^^^^^^^^ without double quotes (usually a bug)

Expanding $TEST_ARGS without putting it in double quotes causes the shell to split the string's value on whitespace. This is usually a bug since it would cause directory names like /home/user/My Files to get split into multiple words. You're still at some risk if the environment variable values happen to contain whitespace or other punctuation, intentionally or otherwise.

There are safer but more obscure ways to approach this in shells with extensions like GNU bash, but not all Docker images contain these. Rather than double-check that your image has bash, and figure out bash array syntax, and write a separate script to do the argument handling, this is where I suggest handling it exclusively at the Python layer is a better approach.

  • Related