I'm trying to use Secrets with Docker Compose
Here is my Docker Compose (only the relevant parts):
version: "3.8"
services:
My-Service:
build:
context: ./..
dockerfile: ./docker/Dockerfile
image: my-app/api
container_name: my-app-api
environment:
ASPNETCORE_ENVIRONMENT: Docker
ASPNETCORE_URLS: http://+:8080
Swagger__Authentication__ClientSecret_FILE: /run/secrets/my_secret
secrets:
- my_secret
ports:
- "50002:8080"
secrets:
my_secret:
file: ./my_secret.txt
I have a my_secret.txt
file containing a secret.
Then I create the image and run it
docker compose -f ./docker/compose.yaml -p my-app up -d --build
Inside the container, checking the /run/secrets/my_secret
file is here and has the correct value
sh-5.1$ cat /run/secrets/my_secret
My super secret
The only problem is that my Swagger__Authentication__ClientSecret_FILE
environment variable has the value of my file path instead of its content
sh-5.1$ echo $Swagger__Authentication__ClientSecret_FILE
/run/secrets/my_secret
So what am I doing wrong here? I think I'm doing exactly like the Docker documentation says, yet it doesn't work as intended. I honestly can't wrap my head around this.
Thanks for your answer(s).
Ok I finally got something working even if it's not as clean as I'd like.
My mistake was assuming that my environment variable Swagger__Authentication__ClientSecret_FILE
would "magically" have its value set to the content of my /run/secrets/my_secret
file but there's no such kind of automatic magic, it has to be manually set.
Here is my new Docker Compose file
version: "3.8"
services:
My-Service:
build:
context: ./..
dockerfile: ./docker/Dockerfile
image: my-app/api
container_name: my-app-api
environment:
ASPNETCORE_ENVIRONMENT: Docker
ASPNETCORE_URLS: http://+:8080
Swagger__Authentication__ClientSecret_FILE: /run/secrets/my_secret
secrets:
- my_secret
ports:
- "50002:8080"
entrypoint: ./compose-entrypoint.sh
volumes:
# $FINAL_WORKDIR is an environment variable set in the .env file with the path of the final WORKDIR set in the Dockerfile before executing the ENTRYPOINT
- "./compose-entrypoint.sh:$FINAL_WORKDIR/compose-entrypoint.sh:ro"
secrets:
my_secret:
file: ./my_secret.txt
The changes are:
ENTRYPOINT
directive from the Dockerfile
and execute a compose-entrypoint.sh
file insteadcompose-entrypoint.sh
file in a volume (as read-only with :ro
) so it can be executed as the entrypoint (make sure the file is executable on your host machine so it will be executable as well in your container)The logic to set the Swagger__Authentication__ClientSecret
environement variable I need happens in this compose-entrypoint.sh
file:
#!/bin/sh
export Swagger__Authentication__ClientSecret=$(cat $(echo $Swagger__Authentication__ClientSecret_FILE))
source ./entrypoint.sh
Note: I kept this file as simple as possible to better demonstrate the basis principle. However a better way is simply to copy how MySQL is doing (thanks to @xerx593 who shared the link in a comment)
This script is:
Swagger__Authentication__ClientSecret_FILE
environment variable which is actually a file pathSwagger__Authentication__ClientSecret
environment variable with the content read from the fileentrypoint.sh
file that is the original file called in the Dockerfile
At the end of my Dockerfile
I just had to copy the entrypoint-sh
bash file and make it executable
COPY ./docker/entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
Note that by default it is executing the entrypoint.sh
file which is NOT setting any additional environment variable. The compose-entrypoint.sh
file is executed only when using Docker Compose.
Hope this could clarify some obscure parts.