whiteweb.security / guides / docker-compose.yml exposed
docker-compose.yml / docker-compose.override.yml High severity ~5 min read

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 .env file 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:

grep for credentials in docker-compose.ymlbash
# 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) or ALTER 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_KEY or 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.

nginx — block compose files/etc/nginx/sites-enabled/…
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):

docker-compose.yml — use variable referencesdocker-compose.yml
services: db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_PASSWORD: ${MYSQL_PASSWORD}
.env file — keep this outside the web root.env
MYSQL_ROOT_PASSWORD=strongrandomvalue MYSQL_PASSWORD=anotherstrongvalue

Option B — Docker secrets (more secure, better for Swarm/production):

create a Docker secret from a filebash
# 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.