Generally yes. Compose secrets are delivered as files that only the services you name can read, while environment variables are visible to every process in the container and often end up in logs. Neither is a vault, so protect the source file and the host as well.
How Compose secrets work
Docker's documentation says a secret is defined in the top level secrets element, with its value taken from a file or from an environment variable on the machine running Compose. Compose bind mounts each secret as a single file at the path run slash secrets slash the secret name, on Linux containers. A service gets access only if it lists the secret in its own secrets attribute, so access is granted per service.
Why files beat variables
The same page gives the reasons.
| Concern | Environment variable | Secret file |
|---|---|---|
| Visible to all processes in the container | Often yes | Controlled by file permissions |
| Easy to leak in debug logs | Yes | Less likely |
| Access tracking | Hard | Per service grant |
| Needs app support | No | App must read a file path |
Variables also persist in the image when set with ENV, and show in docker inspect. Docker's reference says ARG values appear in docker history, so never pass secrets that way.
Steps to migrate
- List every variable in your compose file and env files that holds a credential.
- Move each to a file outside version control, or to an environment variable on the build or deploy host.
- Declare it under the top level secrets element and attach it to only the service that needs it.
- Change the application to read the file. Many popular images support a variable that holds the path to a file instead of the value itself, so check the image docs.
- Remove the old variable from the compose file, the env file and shell history.
- Rotate the credential, since the old value was exposed in plain text.
Build time secrets
Compose docs mention using an environment sourced secret for build secrets, such as a package registry token. Build secrets should be consumed through a secret mount during the build, not through build arguments. See build secrets without leaking into layers.
What still can go wrong
Anyone who can read the secret file on the host can read the secret. A compromised app that can open its own secret file can send it out. Secrets files in a repository defeat the purpose, and scanning for committed secrets still matters. For production clusters, use the secret management your orchestrator provides and your cloud's key management, rather than local files.
Quick check
Do secrets work on Windows containers in Compose?
The documentation says the file mount behavior applies to Linux containers only. Check platform notes if you run Windows.
Is an env file safer than inline variables?
It keeps values out of the compose file, but the values still end up as environment variables in the container. A secret file is a stronger fit.
Safeguard
Safeguard does SBOM and dependency scanning, and its policies and gates can run in CI so a bad image does not reach production. You can try a free scan before deciding anything.
Sources
Last reviewed: 19 October 2026.