DEV Community

kingyou
kingyou

Posted on

Practical Ways to Handle Multiple Secrets in Docker Compose—File-Style Without Swarm

Securing secrets in your Docker-based app is critical—but the official Docker "secrets" feature is tied to Swarm, and the popular *_FILE pattern isn't supported by every image. How can you manage API keys, passwords, and tokens securely and flexibly in plain Docker Compose setups? Let's break it down.

Scenario 1: Your Image Supports the *_FILE Pattern

Many official Docker images (like MySQL, Postgres, Redis) support environment variables such as DB_PASSWORD_FILE and API_TOKEN_FILE. This is the easiest and most secure way to mount secrets.

Steps:

  1. Create secret files:
   echo "db-password-here" > db_password.txt
   echo "api-token-here" > api_token.txt
Enter fullscreen mode Exit fullscreen mode
  1. Reference secrets in docker-compose.yml:
   version: '3.8'
   services:
     db:
       image: mysql
       secrets:
         - db_password
       environment:
         MYSQL_PASSWORD_FILE: /run/secrets/db_password

   secrets:
     db_password:
       file: ./db_password.txt
Enter fullscreen mode Exit fullscreen mode
  1. Access secrets: The image reads the secret from /run/secrets/db_password—no need for handling in your app code.

Scenario 2: Image Does NOT Support *_FILE

If your image doesn't support this pattern, secrets will be mounted as files at /run/secrets/<name>, but you need to inject them into environment variables yourself.

Steps:

  1. Same as above:

    Create secret files and reference them as Compose secrets.

  2. Add a wrapper entrypoint script:

    inject-secrets.sh:

   #!/bin/sh
   export DB_PASSWORD="$(cat /run/secrets/db_password)"
   export API_TOKEN="$(cat /run/secrets/api_token)"
   exec "$@"
Enter fullscreen mode Exit fullscreen mode

Be sure to copy this script into your image in the Dockerfile.

  1. Configure docker-compose:
   services:
     app:
       image: your-app-image
       secrets:
         - db_password
         - api_token
       entrypoint: ["/inject-secrets.sh"]
Enter fullscreen mode Exit fullscreen mode
  1. In your app: Use environment variables as normal, e.g., os.getenv("DB_PASSWORD").

Scenario 3: Using Plain Environment Variables in Compose

For local development or the simplest setup, you can skip secret files and inject environment variables via .env files, but security is lower since values are visible to anyone with access to Compose config.

Steps:

  1. Define secrets in a .env file:
   DB_PASSWORD=supersecret
   API_TOKEN=sometoken
Enter fullscreen mode Exit fullscreen mode
  1. Reference these in your Compose file:
   environment:
     - DB_PASSWORD
     - API_TOKEN
Enter fullscreen mode Exit fullscreen mode

Quick Tips & Best Practices

  • Never commit secret files or .env files to git.
  • For production, prefer secrets stored in files and injected with scripts.
  • Rotate secrets regularly and automate management via CI/CD.
  • Read the documentation of any image you use—search for *_FILE support.
  • Limit container access only to services that require the secrets.

Conclusion

Whether or not your Docker image supports *_FILE, you can always use mounted secret files in Compose and inject values as environment variables with a simple script. For the highest security, layer your approach with proper access controls, tooling, and automation!

Did you find this breakdown helpful? Share your secret management tips below! 🚢🔒

Top comments (0)