Managing Secret Configuration: Secure Docker Environments
Stop hardcoding passwords! Learn how to use .env files and Docker Compose to manage sensitive data securely in your containerized projects.

Previously in this course, we explored connecting a web app to a database and multi-container networking. While those lessons taught us how to make services talk to each other, they left us with a dangerous habit: hardcoding database passwords directly into our docker-compose.yml files.
In this lesson, we shift from convenience to security. We’ll implement a standard practice for handling sensitive data, ensuring your secrets stay out of your version control system while remaining easily accessible to your containers.
The Problem with Hardcoding Secrets
When you define a database password in a docker-compose.yml file, that file becomes a liability. If you push that file to a public or even a shared private repository, anyone with access can compromise your database.
Beyond security, hardcoding makes your configuration rigid. You want to use one password for development, another for staging, and a complex, randomly generated one for production. You need a way to decouple the configuration structure (the YAML) from the sensitive values (the secrets).
Managing Secret Configuration with .env Files

Docker Compose has built-in support for .env files. When you run docker compose up, Docker automatically looks for a file named .env in the same directory as your docker-compose.yml and makes those variables available for variable substitution within the Compose file.
Step 1: Create the .env file
Create a file named .env in your project root. This file uses a simple KEY=VALUE format. Add your sensitive data here:
TEXT# .env file DB_USER=admin DB_PASSWORD=super-secret-password-123
Crucial: Add .env to your .gitignore file immediately. You never want this file to enter your Git history.
Step 2: Reference variables in Compose
Now, modify your docker-compose.yml to reference these variables using the ${VARIABLE_NAME} syntax.
YAMLservices: db: image: postgres:15 environment: POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD}
When Docker Compose parses this file, it replaces ${DB_USER} with admin and ${DB_PASSWORD} with super-secret-password-123 at runtime.
Moving Beyond Simple Variables
While .env files are excellent for local development and basic setups, they are just the first step in a professional security workflow. As you scale, you may need to look into more robust solutions.
For instance, managing secrets securely in CI/CD pipelines ensures your build process doesn't leak credentials, while Docker BuildKit secrets are specifically designed to prevent sensitive keys from being burned into your image layers during the build process. If you eventually move to orchestrators like Kubernetes, you'll eventually adopt dedicated secret management tools to handle rotation and centralized access.
Hands-on Exercise
- Create a
.envfile in your project directory with a customMYSQL_ROOT_PASSWORD. - Update your
docker-compose.ymlto use this variable for the database service. - Run
docker compose up -d. - Run
docker inspect <container_id>and look at theEnvsection. Verify that the variable name appears, but note that this is for visibility; your goal is to ensure the source of truth is externalized.
Common Pitfalls
- Committing the .env file: This is the #1 security failure. Always use a
.env.examplefile (containing keys with empty values) for documentation, and ignore the actual.envfile. - Variable Scope: Remember that these variables are injected into the container's environment. If your application code expects a specific variable name, ensure the key in your
.envfile matches what your application expects to read. - Shell Conflicts: If you export variables in your shell (e.g.,
export DB_USER=admin), these take precedence over values defined in your.envfile. This can lead to confusing "why isn't my change taking effect" bugs.
FAQ
Q: Can I use different .env files for different environments?
A: Yes, you can specify a custom file using the --env-file flag: docker compose --env-file .env.production up.
Q: Are environment variables secure inside the container? A: They are visible to any process running inside that container. For high-security production environments, consider using Docker Secrets (Swarm) or volume-mounting sensitive files rather than passing them as environment variables.
Q: What if I have a variable with a $ character?
A: Use a double $$ to escape it, or Docker Compose will attempt to interpret it as a variable reference.
Recap
By using .env files, we've decoupled our configuration from our code. We now have a clean, repeatable way to inject secrets into our services without risking exposure in version control. You've learned how to define these variables, reference them in Compose, and protect your repository.
Up next: We will consolidate our project by finalizing the directory structure and unifying our configuration into a professional-grade docker-compose.yml file.
Work with me

VPS Server Setup, Deployment & Hardening
Get your app live on a fast, secure server — properly configured, hardened, and deployment-ready. No more wrestling with the command line.

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.


