skip to Main Content

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

2

Answers


  1. Chosen as BEST ANSWER

    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
    
    secrets:
      my_secret:
        file: ./my_secret.txt
    

    The only change is that I now override the ENTRYPOINT directive from the Dockerfile and execute a compose-entrypoint.sh file instead.

    The magic happens in the compose-entrypoint.sh file (yes I know it could be MUCH more error proofed but this very simple file is demonstrating well how it's working):

    #!/bin/sh
    
    export Swagger__Authentication__ClientSecret=$(cat $(echo $Swagger__Authentication__ClientSecret_FILE))
    source ./entrypoint.sh
    

    It is

    1. Getting the value of the Swagger__Authentication__ClientSecret_FILE environment variable which is actually a file path
    2. Read the content of this file
    3. Set a Swagger__Authentication__ClientSecret environment variable with the content read from the file
    4. Call the entrypoint.sh file that is the original file called in the Dockerfile

    At the end of my Dockerfile I just had to copy the two bash files and make them executable

    COPY ./docker/entrypoint.sh ./entrypoint.sh
    RUN chmod +x ./entrypoint.sh
    
    COPY ./docker/compose-entrypoint.sh ./compose-entrypoint.sh
    RUN chmod +x ./compose-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.


  2. Let’s examine your first example (the one that works). You execute this command : cat /run/secrets/my_secret and you get result My super secret.

    The cat command reads a file at the provided path and print its content. Thus, your command reads the file at /run/secrets/my_secret and print its content which is My super secret.

    Now, let’s examine the second one. You execute this command echo $Swagger_Authentication_ClientSecret and get this result /run/secrets/my_secret.

    $Swagger_Authentication_ClientSecret is the value saved in the variable Swagger_Authentication_ClientSecret. You did set this variable in the environment of your container to be /run/secrets/my_secret. You execute echo with this value as parameter. echo simply prints the value given as parameter. Your command then print the value stored in your variable.

    What you want is to print the content of the file whose path is the value stored in your variable. To do so, just replace echo with cat in your second command

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search