Reputation: 2595
The problem: I'd like to use imgproxy in my project, but I need some way to generate a signing key when the containers are first run. I then need to share that key between two containers: imgproxy, which accepts it in an environment variable, and my server application, where I could read it from wherever needed. The key needs to be unique and random for each deployment. It would be great to avoid having to run any additional commands before docker-compose up
to generate these keys.
What I considered so far:
docker-compose.yml
to add it there.Anyway, what's the best/correct way to approach this? This feels like a popular use case, so surely there has to be something I missed?
Upvotes: 1
Views: 1116
Reputation: 160013
The best way to handle this is to create the secret externally; in Compose, perhaps in a .env
file. This will translate well to other environments and doesn't require changing code at all. This also works well with secrets that require some user intervention to set up (for example, signing a TLS certificate), it will survive a docker-compose down
, and it works even if you split the two halves of the application into separate environments.
If these considerations don't matter to you, and it's really important that the startup be autonomous, you could put the secret into a shared file. Decide that one of the containers is "first". Write a script that runs at startup time that generates the secret:
#!/bin/sh
# Create a random token if it doesn't already exist
if [ ! -f /secrets/token ]; then
dd if=/dev/random bs=48 count=1 | base64 > /secrets/token
fi
# Read back the token into an environment variable
SECRET_TOKEN=$(cat /secrets/token)
# Run the main container process
exec "$@"
In your Dockerfile, COPY
this script in and make it be the image's ENTRYPOINT
. This must use JSON-array syntax, ENTRYPOINT ["entrypoint.sh"]
. If you're launching your application via ENTRYPOINT
, move that command into CMD
instead (or combine a split ENTRYPOINT
/CMD
into CMD
).
Now in your Compose setup, you need to create a volume and share it between the two containers.
version: '3.8'
volumes:
secrets: # empty
services:
imgproxy:
image: ...
volumes:
- secrets:/secrets # matches the path in the entrypoint script
server:
image: ...
volumes:
- secrets:/secrets # could be a different path
(In particular if you're considering eventually running this application on Kubernetes, this approach won't work well. Of the volume types Kubernetes supports, few can be mounted into multiple containers at the same time. There is a native Kubernetes Secret object that's intended for this use, but that then gets back to the original pattern of "create the secret separately".)
Upvotes: 1