My docker-compose.yml got exposed. What should I do?
docker-compose.yml and docker-compose.override.yml describe the full configuration of your containerised application — including every environment variable passed to each service. In practice, this almost always includes database passwords, API keys, SMTP credentials, and other secrets in plain text.
Read the environment: sections carefully and rotate every credential you find.
The environment: block in a compose file is where credentials live. Check every service in the file — database containers, caches, mail servers, and application services all commonly have secrets here.
// the 60-second version
- Check all
environment:blocks for passwords, tokens and keys. - Rotate every exposed credential immediately.
- Remove the file from the web root.
- Move secrets to a
.envfile that is not web-accessible — or use Docker secrets.
01Identify all credentials in the file
Open the compose file and look at every environment: block. Common credential patterns include:
# search for common credential variable names grep -iE "(password|secret|token|key|auth|api_key|db_pass|smtp_pass)" docker-compose.yml # also check .override file if it exists grep -iE "(password|secret|token|key)" docker-compose.override.yml 2>/dev/null
Pay special attention to: MYSQL_ROOT_PASSWORD, POSTGRES_PASSWORD, REDIS_PASSWORD, SMTP_PASSWORD, SECRET_KEY, API_KEY, and any custom application variables. Also note any private Docker registry credentials in image: fields.
02Rotate every exposed credential
For each credential found, rotate it in the relevant service before updating the compose file:
- Database passwords — connect as admin and run
ALTER USER 'user'@'%' IDENTIFIED BY 'newpassword';(MySQL) orALTER USER username PASSWORD 'newpassword';(Postgres). Update the compose file after. - API keys / tokens — go to the issuing service's dashboard and revoke the old key, generate a new one.
- SMTP credentials — change the password in your email provider's settings.
- Application secrets — regenerate any
SECRET_KEY,APP_KEYor similar values. Note that changing these may invalidate existing sessions or signed tokens.
If your compose file references a private Docker image and the registry credentials are embedded, an attacker may have pulled your private images. Check your registry's pull logs.
03Remove the file from the web root
A compose file should never be in a web-accessible directory. It belongs at the root of your project, above the document root, or in a deployment directory that the web server cannot serve.
location ~* /docker-compose[^/]*\.ya?ml$ { deny all; return 404; }
04Move secrets out of the compose file
The long-term fix is to stop putting secrets inline in compose files. There are two common approaches:
Option A — reference a .env file (simple, common):
services:
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD=strongrandomvalue MYSQL_PASSWORD=anotherstrongvalue
Option B — Docker secrets (more secure, better for Swarm/production):
# create the secret echo "strongrandompassword" | docker secret create db_password - # reference it in compose # services.db.secrets: [db_password]
Was this guide useful?
These playbooks are free to read and share. If a heads-up ever saved you a bad week, you can say thanks — or jump into the other guides.