Intro
Docker Compose profiles let teams define optional services in one compose file and activate them only when needed. A profile is a label attached to a service, and you enable that label with the --profile flag or the COMPOSE_PROFILES environment variable. This is useful for running a full development stack with debugging tools, or for splitting production services from maintenance jobs.
However, profiles introduce a class of configuration mistakes that are easy to make and sometimes hard to notice. A service silently not starting because its profile was not activated is a common cause of confusing outages. Misplaced profile definitions, typos in profile names, or forgotten profile flags in CI pipelines can lead to missing databases, absent background workers, or broken one-off tasks.
This guide covers the most frequent Docker Compose profile configuration mistakes, how to detect them, how to recover, and how to prevent them from happening again. Every section includes a concrete command and the expected output, so you can verify your environment immediately.
How Docker Compose Profiles Work
Before looking at mistakes, let's clarify the correct syntax. In a compose file, the profiles key is placed under a service definition, not at the top level:
version: "3.9"
services:
app:
image: nginx:1.25
ports:
- "8080:80"
debug-tools:
image: busybox:1.36
profiles: ["debug"]
command: tail -f /dev/null
Here app has no profiles, so it is always started. The debug-tools service belongs to the debug profile. To start it, you must explicitly enable the profile:
docker compose --profile debug up -d
Or set the environment variable:
export COMPOSE_PROFILES=debug
docker compose up -d
To check which services are enabled for a given profile without starting anything, use:
docker compose --profile debug config --services
Expected output:
app
debug-tools
If you run docker compose config --services without any profile, only app appears. This is the first place mistakes hide: the file is valid, but the active set of services is smaller than expected.
Common Profile Configuration Mistakes
1. Forgetting to Activate a Required Profile
A developer defines a db profile for the database service and expects it to be running after docker compose up -d. But without --profile db, the database container never starts. The application then fails to connect.
Why it happens: The compose file looks correct, and the developer may not realize that profiles are opt-in. The service is omitted silently.
How to detect: List the services that would be started:
docker compose config --services
If the database is missing, compare with the full service list:
docker compose config --profiles
This shows all profiles defined. Expected output for a file with db and debug profiles:
db
debug
How to recover: Activate the missing profile and start again:
docker compose --profile db up -d
How to prevent: Define a default profile in the compose file using the COMPOSE_PROFILES environment variable in a .env file, or document the required profile in the project README. For automated environments, set the profile in the CI pipeline or in a wrapper script.
2. Putting profiles at the Wrong Level
A common syntax mistake is placing profiles under the top-level services key or at the root of the file:
services:
profiles: ["debug"] # wrong
app:
image: nginx
When you run docker compose config, you may see an error like:
services.profiles must be a mapping
Or the file may be accepted but the profile is ignored, leading to the service always starting.
Why it happens: Misunderstanding the YAML structure or copy-pasting from an incorrect example.
How to detect: Validate the compose file:
docker compose config
Look for warnings or unexpected service definitions. Also check with docker compose config --profiles to see if the profile is recognized.
How to recover: Move the profiles key inside the intended service definition:
services:
app:
image: nginx
profiles: ["debug"]
How to prevent: Use a linter or a YAML schema validation in your editor. Many editors highlight structural errors in compose files.
3. Typos in Profile Names
A service is assigned to profile debug, but you activate --profile dbug. The service does not start, and the mistake is not obvious because the command succeeds without error.
Why it happens: Manual typing or inconsistent naming across scripts.
How to detect: Compare the active profile with the profiles defined in the file:
docker compose config --profiles
# shows available profiles
docker compose config --services --profile dbug
# shows only services in dbug, if any
How to recover: Activate the correct profile name:
docker compose --profile debug up -d
How to prevent: Use a single source of truth for profile names, such as a Makefile target or a shell script that contains the profile list, and avoid typing them manually.
4. Profiles in Override Files Not Merging as Expected
Compose supports multiple files, like docker-compose.yml and docker-compose.override.yml. Profiles in an override file can add or remove profiles from the base service. If the override file is not loaded, the profile may be missing.
Why it happens: The override file is not present, or the command does not include the -f flag to load the correct files.
How to detect: Run docker compose config and inspect which services have profiles. You can also use docker compose config --profiles to list all profiles.
How to recover: Ensure the override file is loaded:
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d
How to prevent: Explicitly list all compose files in your commands, or use a wrapper script. Avoid relying on implicit file discovery when multiple files exist.
5. Profile Activation in CI/CD Pipelines
A CI pipeline runs docker compose up -d without the required profile, and tests fail because supporting services are missing.
Why it happens: The profile flag is not part of the pipeline configuration, or the environment variable is not set in the runner.
How to detect: Add a step to the pipeline that prints the active services:
docker compose config --services
How to recover: Update the pipeline to set the profile:
export COMPOSE_PROFILES=test
docker compose up -d
How to prevent: Store the profile in a .env file used by the pipeline, and review the .env file as part of code changes.
Verification and Diagnostics
After any change to profiles, verify the effective configuration and the running containers.
Effective Configuration
Run docker compose config to see the final merged YAML. Check for unexpected profile assignments or missing services. Use --services to list the services that would be started with the current profiles.
Example:
docker compose --profile debug config --services
Expected output includes both the always-on service and the debug service:
app
debug-tools
Container Status
After starting the stack, confirm that the expected containers are running:
docker compose ps
Look for the desired services and their state. If a service is not running, check its logs:
docker compose logs <service-name>
Debugging Profile Activation
If you suspect a profile was not activated, use the --profiles flag to see all profiles defined in the file:
docker compose config --profiles
Then manually check which services belong to each profile by examining the YAML or using:
docker compose config | grep -A2 -B2 'profiles:'
This shows the context around each profiles key.
Failure Modes and Recovery
Profiles can fail in ways that are not immediately obvious. Here are specific failure modes and how to recover.
Missing Database Service
Symptom: Application cannot connect to database.
Check:
docker compose config --services
If the database service is absent, activate its profile:
docker compose --profile db up -d
Verify:
docker compose ps
The database container should now be listed and healthy.
Background Worker Not Processing Jobs
Symptom: Queue grows but no jobs are processed.
Check whether the worker service has a profile and is not started:
docker compose config --services
Start the worker with its profile:
docker compose --profile worker up -d
Check logs to confirm processing:
docker compose logs -f worker
One-off Maintenance Task Did Not Run
A service intended for a one-off task, like database migration, is defined with a profile but the profile was not activated when running docker compose run.
Correct command:
docker compose --profile migrate run migrate
Without the profile, docker compose run migrate fails with "no such service: migrate".
Rolling Back a Profile Change
If a profile change causes problems, revert to the previous compose file. The simplest rollback is to restore the previous version from version control:
git checkout -- docker-compose.yml
Then restart the stack:
docker compose down
docker compose up -d
If you need to temporarily disable a profile without changing the file, you can set COMPOSE_PROFILES to an empty string:
export COMPOSE_PROFILES=
docker compose up -d
This starts only the services without profile assignments.
Operations Checklist for Profile Changes
Use this checklist before and after changing profiles in a compose file.
Before changing:
- [ ] Identify the service(s) affected by the profile change.
- [ ] Note the current active profiles (
COMPOSE_PROFILESor--profileflags in use). - [ ] Confirm the compose file is valid:
docker compose config. - [ ] Record the current running containers:
docker compose ps.
After changing:
- [ ] Validate the new configuration:
docker compose config --services. - [ ] Start the stack with the intended profiles.
- [ ] Check that all expected services are running:
docker compose ps. - [ ] Verify application functionality (e.g., database connection, worker processing).
- [ ] Update documentation or scripts that reference profiles.
Owner and review frequency: assign an owner (e.g., DevOps engineer) to approve profile changes in the compose file, and review profile usage monthly or whenever the deployment environment changes.
Conclusion
Docker Compose profiles are a powerful way to manage optional services, but they must be used carefully. The most common mistakes are forgetting to activate a profile, misplacing the profiles key, and using inconsistent profile names. These mistakes lead to services not starting, which can be difficult to diagnose because the compose file itself is valid.
By following the verification steps in this guide, you can quickly identify missing profiles and recover. The key commands to remember are docker compose config --services to see what would start, docker compose config --profiles to list available profiles, and docker compose ps to check actual running containers.
Prevent future mistakes by standardizing profile names, documenting required profiles, and using environment variables in CI/CD. Always validate the effective configuration before deploying, and include profile checks in your operational runbooks.
With these practices, you can use Docker Compose profiles safely and avoid the silent failures that disrupt development and production environments.