Docker Compose Profile Service Not Starting: Check depends_on and Activation
If a Docker Compose service with profiles does not start, first confirm that its profile is active. Then check every depends_on edge: Compose does not automatically activate a dependency that belongs only to a different profile, so the resulting model can be invalid even though the YAML parses.
The reliable debugging order is config --services, config --quiet, then up with the exact profile set used by the application.
Understand what a profile changes
Profiles apply to services. A service without profiles is always enabled; a profiled service is ignored unless an active profile matches or you explicitly target that service. Other top-level Compose elements are not switched off by profiles.
This small file has two independent optional groups:
services: web: image: nginx:alpine
db: image: postgres environment: POSTGRES_PASSWORD: example
adminer: image: adminer profiles: [debug] depends_on: - db
test-runner: image: alpine profiles: [test] command: ['sh', '-c', 'echo tests']
coverage: image: alpine profiles: [test] depends_on: - test-runner command: ['sh', '-c', 'echo coverage']docker compose --profile debug up includes web, db, and adminer. docker compose --profile test up includes web, db, test-runner, and coverage. A command without --profile starts only the services without a profile.
Fix a dependency in another profile
This is the failure pattern:
services: debug-shell: image: alpine profiles: [debug] depends_on: - test-runner
test-runner: image: alpine profiles: [test]With only debug active, debug-shell is selected but test-runner is ignored. Compose cannot satisfy the dependency and reports an invalid model. Docker’s profiles reference describes this as a profile mismatch; depends_on does not magically enable a service in a different inactive profile.
Choose the fix that matches the intended lifecycle:
-
Put both services in the same profile when they are one optional feature.
-
Enable both profiles when the dependency is intentionally shared:
Terminal window docker compose --profile debug --profile test up -
Remove the profile from a dependency that should always exist, such as a database used by every local mode.
Do not add every profile to every service as a blanket fix. That makes optional services start unexpectedly and hides the dependency contract.
Verify the active model before starting containers
docker compose config parses, resolves, and renders the actual model that Docker Engine will receive. Use it with the same working directory and environment file as your real command:
# Baseline: services without a profile.docker compose config --services
# Debug model: profile services now included.docker compose --profile debug config --services
# Validate the dependency graph without printing the full YAML.docker compose --profile debug config --quiet
# See the profile names declared by this project.docker compose config --profilesIf debug-shell appears in config --services but test-runner does not, the profile set is wrong. If config --quiet fails, fix the model before pulling images or debugging container logs.
The config command also resolves interpolation and paths. This makes it useful for CI, where COMPOSE_PROFILES, --env-file, and the working directory can differ from a local shell.
Activate profiles consistently in CI
Use one activation contract for local commands and automation. Docker supports repeated --profile flags and the COMPOSE_PROFILES environment variable:
COMPOSE_PROFILES=debug,test docker compose config --quietCOMPOSE_PROFILES=debug,test docker compose up -dIf a command-line --profile is present, it takes precedence over the related environment setting. Put the profile selection next to the command that needs it instead of relying on a developer’s persistent shell environment.
An explicit service target also activates that service’s profile:
docker compose run --rm coverageThat shortcut does not repair a dependency in a different profile. If the selected service depends on another profiled service, activate the shared profile or target a model where the dependency is always enabled.
Keep profiles separate from Compose file merging
Profiles change which services are in one Compose model. They are not the same as -f overrides or include modules:
- Use profiles for optional services such as debugging, testing, or local observability.
- Use
-fwhen a second file should override or extend a base model. - Use
includewhen a module should retain its own path and environment context.
Combining these features is valid, but debug them in layers: first render the merged files, then enable the profiles, then start the selected services.
FAQ
Q: Why is my profile service missing from docker compose config --services?
A: Its profile is inactive. Add --profile name or set COMPOSE_PROFILES for that command. A service without profiles is always included.
Q: Does depends_on activate a dependency’s profile?
A: Only when the dependency is eligible in the active model. A service in a different inactive profile is ignored, which can make the dependency graph invalid. Enable both profiles or give the services a shared lifecycle profile.
Q: Why does targeting a service still produce a profile error?
A: Explicitly targeting a service activates its own profile, not every unrelated profile in its dependency chain. Check the rendered model and activate the dependency’s profile when needed.
References:
Docker Docs: docker compose config
Report a typo or broken link, or suggest a related topic.