Overview
If you see the error "depends_on condition is not supported in Compose v3", your compose file uses the v3 format where conditional depends_on was removed. You have three practical paths:
- Use modern Docker Compose (Compose Specification) and the long
depends_onsyntax withconditionplushealthcheck. - Stay on v3 and handle readiness in the dependent service (wait scripts / app-level retries).
- Switch to
version: "2.4"if you do not rely on Swarm-only features and want the classic behavior.
The safest long-term approach is to use healthchecks and app-level retries; start order alone does not guarantee readiness.
Quickstart (choose one path)
- Check your CLI:
docker compose version(modern v2 plugin) ordocker-compose version(legacy v1).
- Pick a migration pattern:
- A) Compose Spec with
depends_on.condition+healthcheck(recommended). - B) v3 + explicit wait in the dependent container.
- C) Use
version: "2.4"+conditionif you are not using Swarmdeploy:.
- A) Compose Spec with
- Test with
docker compose up --buildand verify the dependent starts only after the dependency is healthy.
Minimal working example (Compose Spec with condition)
This works with modern Docker Compose that implements the Compose Specification. Omit the version field and use a healthcheck on the dependency.
autoupdate: false
services:
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 2s
timeout: 3s
retries: 10
web:
image: alpine:3.20
depends_on:
redis:
condition: service_healthy
command: ["sh", "-c", "echo 'Redis is healthy, starting web'; sleep 2"]
Notes:
webwill be started only afterredisreports healthy.- Healthchecks run inside the dependency container.
Option B: Stay on v3 and wait explicitly
In Compose v3, depends_on only controls start order, not health. Add a readiness loop in the dependent service.
version: "3.9"
services:
redis:
image: redis:7-alpine
web:
# use redis image so redis-cli is available for a simple wait
image: redis:7-alpine
depends_on:
- redis
command: ["sh", "-c", "until redis-cli -h redis ping; do sleep 1; done; echo 'Ready';"]
Tips:
- Replace the loop with your service-specific probe (e.g., HTTP 200 check, DB driver retry).
- Prefer app-level retry logic over shell loops when possible.
Option C: Use version 2.4 with condition
If you are not deploying to Swarm and want the classic behavior, set version: "2.4" and use condition.
version: "2.4"
services:
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 2s
timeout: 3s
retries: 10
web:
image: alpine:3.20
depends_on:
redis:
condition: service_healthy
command: ["sh", "-c", "echo 'Redis is healthy, starting web'; sleep 2"]
Caveats:
- Remove
deploy:(Swarm-only) blocks if you move to 2.4; they are not supported outside Swarm.
Migration steps from a failing v3 file
- Identify Swarm usage:
- If you have
deploy:keys, you were targeting Swarm. Either keep v3 and use Option B, or split files (one for Swarm, one for local dev).
- If you have
- If you do not use Swarm:
- Prefer Option A (Compose Spec) by removing the
versionline and using longdepends_onwithconditionandhealthcheck.
- Prefer Option A (Compose Spec) by removing the
- Add real healthchecks:
- Implement a robust
healthcheckon the dependency (database ping, HTTP endpoint, or a custom script that validates readiness, not just port open).
- Implement a robust
- Test restarts:
- Stop and start the dependency (
docker compose restart redis) to confirm your app can handle temporary dependency loss.
- Stop and start the dependency (
Choosing an approach
| Approach | Use when | Pros | Cons |
|---|---|---|---|
| Compose Spec + condition | You run modern Docker Compose (v2) | Simple; declarative; integrates with healthchecks | Requires recent CLI; only gates initial start |
| v3 + wait loop | You must keep v3 and can modify the dependent image | Works everywhere; explicit | Extra scripting; easy to get wrong; maintenance |
| 2.4 + condition | You do not use Swarm deploy: | Familiar behavior; minimal changes | Older file version; not for Swarm configs |
Pitfalls
- Start order is not readiness. A container can be "started" while the service is still booting.
- Healthchecks must test true readiness (e.g., perform a lightweight real query, not only a TCP connect).
depends_ondoes not manage restarts of dependents if a dependency becomes unhealthy later. Your app must handle retries.- Fixed
sleepdelays are brittle and slow. Prefer positive checks (healthchecks or retries) over timeouts. - Mixing Swarm (
deploy:) with non-Swarm features in one file leads to portability issues.
Performance notes
- Keep healthchecks cheap: short commands, low intervals (1–5s), low timeouts (1–3s), and a bounded number of retries.
- Avoid excessive retries that delay startup by minutes; tune for typical boot times with a modest buffer.
- Prefer app-level exponential backoff for dependency connections to avoid tight loops.
- Do not run heavy binaries in minimal images solely for waiting; if needed, create a small purpose-built image or multi-stage build.
Tiny FAQ
Q: Why is
depends_on.conditionrejected in v3? A: v3 targeted Swarm and removed this feature. Use healthchecks and app-level readiness or switch versions/spec.Q: Does
depends_onguarantee my app will work after the dependency restarts? A: No. It only affects initial start. Implement retries and handle transient failures in your application.Q: Can I just add
sleep 10? A: It may mask issues and slow deployments. Prefer explicit readiness checks (healthchecks or retry loops).Q: How do I know if my Compose supports the Compose Spec conditions? A: Use the modern
docker composeCLI (v2). Test with a small file using the longdepends_onsyntax and a healthcheck.Q: Is removing the
versionfield OK? A: Yes for modern Compose. The Compose Specification does not requireversion:; the tooling detects supported features.