Reputation: 20757
I created a custom docker container, which calls a startup script. That script requires some data, which is stored in my .env
file.
All variables required by all files are stored in .env
, and that is where I want to keep it. I can pass variables this way without error... it's only arrays that I can't pass correctly.
.env
:
FOO=1 # blah
BAR='bar' # this does blah
MYARRAY=(
hello # blah
world # blah
)
docker-compose.yml
:
mycontainer:
env_file: .env
build:
context: .
args: # pass variables into dockerfile
FOO: ${FOO}
MYARRAY: ${MYARRAY}
Dockerfile
:
FROM some_app
ARG FOO
ARG MYARRAY
ENV \
FOO=$FOO \
MYARRAY=$MYARRAY # pass variables into script
CMD [ "myscript.sh" ]
myscript.sh
:
#!/bin/bash
set -Eeuo pipefail
echo "$FOO" # works
for i in "${MYARRAY[@]}"; do echo "$i"; done # <---- problem is here
The array does not arrive intact in the script - it arrives as "("
. This is because it is "translated" from ini to yaml to dockerfile syntax to bash.
How do I escape/format the stuff in .env
so that it arrives in the bash script correctly?
Upvotes: 4
Views: 4526
Reputation: 141200
Use declare -p
output and transmit the array as plain text.
MYARRAY=(hello world)
Later in your script:
declare -a MYARRAY="$MYARRAY"
printf "%s\n" "${MYARRAY[@]}"
Bash arrays is an extension by bash, it's not supported anywhere else. Environment variables can contain only text, a value. Pass anything more complicated using text properly escaped and extracted with declare -p
(or even functions with declare -f
). For hard cases you can prepare (or even autogenerate from some script) the array with the help of printf "%q"
:
hardarray=('!@#\''\' "space space")
printf "%q" "$(declare -p hardarray | cut -d= -f2-)" # put the output in .env file
# then add in your .env file:
hardarray=\(\[0\]=\"\!@#\\\\\\\\\"\ \[1\]=\"space\ space\"\)
# then later read the array in your script:
declare -a hardarray="$hardarray"
I believe passing multiline strings via env_file in docker-compose is impossible. I would just advise to generate it from a shell script (but sadly, this adds another stage to the build process).
Upvotes: 5