In AWS ECS, when SECRET is defined in the ECS task definition, the $SECRET variable ends up in the container as a json string.
SECRET={"secret1":"value1","secret2":"value2"}
I'm able to parse out and export the json string to individual environment variables when I run this command directly in the container using this command:
eval export $(echo "$SECRET" | jq -r 'to_entries|map("\"\(.key)=\(.value|tostring)\"")|.[]' )
But, the variables don't get set properly when I run the same command from the 'entrypoint.sh' script, on container run, when the container starts.
["entrypoint.sh"]
["entrypoint.sh"]
#!/usr/bin/env bash
if [ $# -gt 0 ];then
## If we passed a command in docker run, run it
exec "$@"
else
eval export $(echo "$SECRET" | jq -r 'to_entries|map("\"\(.key)=\(.value|tostring)\"")|.[]' )
"${BUILD_DIR}"/run.sh
fi
Is it possible to parse the json string and export environment variables in an entrypoint script so that the show up in printenv
?
Any guidance would be appreciated.
CodePudding user response:
I tried to reproduce this problem but your code appears to work just fine. With the following Dockerfile:
FROM ubuntu:20.04
RUN apt-get update; apt-get -y install jq; apt-get clean all
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
And a slightly modified entrypoint.sh
:
#!/usr/bin/env bash
if [ $# -gt 0 ];then
## If we passed a command in docker run, run it
exec "$@"
elif [ -n "$SECRET" ]; then
eval export $(echo "$SECRET" | jq -r 'to_entries|map("\"\(.key)=\(.value|tostring)\"")|.[]' )
fi
echo "Extracted environment variables:"
env | grep '^secret'
If I run it like this:
docker build -t myimage .
docker run --rm -e 'SECRET={"secret1":"value1","secret2":"value2"}'
myimage
I get this output:
Extracted environment variables:
secret2=value3
secret1=value1
Your code seems to correctly extract and export to the environment the
variables encoded in the SECRET
variable.
CodePudding user response:
The sort of complex variable manipulation you're describing is hard to do in a shell script, but much more straightforward in other languages. There's really only two requirements around an entrypoint wrapper script: it must be executable given the language runtime and libraries in the image, and it must execute the command passed to it as parameters.
So you could imagine writing a Python entrypoint wrapper script, for example. Modifying os.environ
modifies the environment in the same way as the shell export
built-in; os.execvp()
replaces the current process with a new one, like the shell exec
built-in. If you're doing this already then you can use the standard json
library for JSON parsing.
This leads to a script like:
#!/usr/bin/env python3
# entrypoint.py
import json
import os
# Set arbitrary environment variables from a JSON-encoded
# $SECRET environment variable
if 'SECRET' in os.environ:
for k, v in json.loads(os.environ['SECRET']).items():
os.environ[k] = v
# Get the command to run from command-line arguments
cmd = sys.argv[1:]
if len(cmd) == 0:
cmd = [os.path.join(os.environ['BUILD_DIR']), "run.sh"]
# Replace this script with that command.
os.execvp(cmd[0], cmd)
So long as your image already has a Python interpreter and you mark this script as executable, you can use it as an ENTRYPOINT ["./entrypoint.py"]
the same way you do your existing shell script.