service "web" refers to undefined secret db_password: invalid compose project
— the service lists db_password under secrets:, and the file has
no top-level secrets: section that says where that secret comes from. Declare
it, here as a file, and the project starts.
Add a top-level secrets: block with db_password: and a
file: line pointing at a file that holds the value. The service then reads it
at /run/secrets/db_password.
The error
PS> docker compose -p fix10-cs-p3 config
service "web" refers to undefined secret db_password: invalid compose project
docker compose -p fix10-cs-p3 up printed the same line and exited with code
1 before creating a network or a container. The file:
services:
web:
image: alpine
command: ["cat", "/run/secrets/db_password"]
secrets:
- db_password
Why it happens
A secret in Compose has two halves. The service's secrets: list only says
which secrets the container gets; the top-level secrets: section says where
each one's value comes from. The service names db_password, and with no
top-level entry for it Compose has no value to mount, so it rejects the whole project.
Configs work the same way and give the same kind of message. A second file that listed both an undefined secret and an undefined config under one service stopped on the config:
PS> docker compose -p fix10-cs-pa config
service "web" refers to undefined config app_config: invalid compose project
For that one, add a top-level configs: entry named app_config.
With app_config defined and the secret still missing, the same file stopped
on the secret line shown above, so fix one and expect the next.
The fix
services:
web:
image: alpine
command: ["cat", "/run/secrets/db_password"]
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txt
PS> docker compose -p fix10-cs-p3 up
...
Attaching to web-1
Container fix10-cs-p3-web-1 Starting
web-1 | not-a-real-password-123
Container fix10-cs-p3-web-1 Started
...
db_password.txt sits next to compose.yaml and holds the value;
the container printed it from /run/secrets/db_password, so the secret was
mounted. The value here is a test string. For a real one, keep the file out of Git.
How it was reproduced
One alpine service that runs cat /run/secrets/db_password and
lists db_password under its secrets:, with no top-level
secrets: section, checked with docker compose config and started
with docker compose up from Windows PowerShell 5.1; a second file added an
undefined config, and a third defined that config but not the secret. Docker Compose v5.7.0, Docker Engine 29.9.3, Docker Desktop 4.99.0
on Windows (version 10.0.26300). The project names fix10-cs-p3,
fix10-cs-pa and fix10-cs-pb are this test's own; the started project was removed with docker compose down -v.
Frequently asked
- What does 'refers to undefined secret' mean in Docker Compose?
- A service lists a secret under its secrets: key, and the file has no top-level secrets: section that defines that name. Compose rejects the project before it creates anything.
- How do I define a secret in docker-compose.yml?
- Add a top-level secrets: section with the secret's name and a file: line, for example db_password: with file: ./db_password.txt. The container then reads it at /run/secrets/db_password.
- Does an undefined config give the same error?
- It gives the same kind of message with the word config: service "web" refers to undefined config app_config: invalid compose project. Define it under a top-level configs: section.
More decoded errors in the Fixes category. The same mistake with a named volume is Docker Compose: refers to undefined volume.