4

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?

1 Answer 1

5

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).

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! This works when I declare the array as a single-line string MYARRAY="( hello world )" but does not work when it is multiline like in my code above. It needs to be multiline because it's huge and also needs to be commented. Can I use your approach with a multiline array / string?
You have to check, docker has un-intuitive comment parsing. So something like... edited. I don't think you can put multiline in env_file alltogether. Best solution - just generate .env file with declare -p from a bash script before running docker... Ach no, For example if the value is surrounded by quotes (as is often the case of shell variables), the quotes are included in the value passed to Compose. - so you have to remove the quotes and I believe it's impossible to put multiline variables in an .env_file.
Tried your update thanks... It still doesn't work. The multiline is the real problem. I also tried to use `foo ` at the end of each line but that didn't help. I'll look into the docker manual, maybe this isn't possible :( Thanks again
This probably isn't possible... sorry for wasting your time!
Just checked the docker-compose repo and looks like multiline strings in .env isn't supported - the engine only reads the first line!! :-(
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.