I'm facing some problems to pass some environment parameters to docker run
in a relatively generic way.
Our first iteration was to load a .env
file into the environment via these lines:
set -o allexport;
. "${PROJECT_DIR}/.env";
set +o allexport;
And then manually typing the --env VARNAME=$VARNAME
as options for the docker run
command. But this can be quite annoying when you have dozens of variables.
Then we tried to just pass the file, with --env-file .env
, and it seems to work, but it doesn't, because it does not play well with quotes around the variable values.
Here is where I started doing crazy/ugly things. The basic idea was to do something like:
set_docker_parameters()
{
grep -v '^$' "${PROJECT_DIR}/.env" | while IFS= read -r LINE; do
printf " -e %s" "${LINE}"
done
}
docker run $(set_docker_parameters) --rm image:label command
Where the parsed lines are like VARIABLE="value"
, VARIABLE='value'
, or VARIABLE=value
. Blank lines are discarded by the piped grep
.
But docker run
complains all the time about not being called properly. When I expand the result of set_docker_parameters
I get what I expected, and when I copy its result and replace $(set_docker_parameters)
, then docker run
works as expected too, flawless.
Any idea on what I'm doing wrong here?
Thank you very much!
P.S.: I'm trying to make my script 100% POSIX-compatible, so I'll prefer any solution that does not rely on Bash-specific features.
Based on the comments of @jordanm I devised the following solution:
docker_run_wrapper()
{
# That's not ideal, but in any case it's not directly related to the question.
cmd=$1
set --; # Unset all positional arguments ($@ will be emptied)
# We don't have arrays (we want to be POSIX compatible), so we'll
# use $@ as a sort of substitute, appending new values to it.
grep -v '^$' "${PROJECT_DIR}/.env" | while IFS= read -r LINE; do
set -- "$@" "--env";
set -- "$@" "${LINE}";
done
# We use $@ in a clearly non-standard way, just to expand the values
# coming from the .env file.
docker run "$@" "image:label" /bin/sh -c "${cmd}";
}
Then again, this is not the code I wrote for my particular use case, but a simplification that shows the basic idea. If you can rely on having Bash, then it could be much cleaner, by not overloading $@
and using arrays.