Docker Compose — Wait Strategies
Beyond Docker health checks, you may need application-level wait strategies for dependencies that take time to initialize.
Strategy Comparison
| Strategy | Level | Complexity | Reliability |
|---|---|---|---|
depends_on |
Container | Low | Low |
condition: service_healthy |
Docker | Medium | High |
| wait-for-it / dockerize | Script | Medium | High |
| Application retry logic | App | High | Highest |
wait-for-it Script
A popular shell script that waits for a TCP port:
services:
api:
image: myapi:latest
command: >
sh -c "
/wait-for-it.sh db:5432 --timeout=60 --strict &&
node server.js
"
depends_on:
- db
dockerize
Similar approach with the dockerize utility:
services:
api:
image: myapi:latest
command: >
dockerize
-wait tcp://db:5432
-wait tcp://cache:6379
-timeout 60s
node server.js
Application-Level Retry
The most robust approach — build retry logic into your application:
Node.js with retry:
async function connectWithRetry(maxRetries = 10) {
for (let i = 0; i < maxRetries; i++) {
try {
await db.connect();
console.log('Database connected!');
return;
} catch (err) {
console.log(`Retry ${i + 1}/${maxRetries}...`);
await new Promise(r => setTimeout(r, 2000));
}
}
throw new Error('Failed to connect after retries');
}
Python with tenacity:
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(wait=wait_exponential(min=1, max=30), stop=stop_after_attempt(10))
def connect_db():
return psycopg2.connect("host=db dbname=mydb")
Recommended Pattern
Combine multiple strategies:
services:
api:
image: myapi:latest
depends_on:
db:
condition: service_healthy # Docker-level wait
# Plus: application has retry logic built in
This gives you defense in depth — Docker handles the initial wait, and your app handles edge cases.
Init Containers Pattern
Use a separate service for one-time setup:
services:
db-init:
image: myapp:latest
command: npm run db:migrate
depends_on:
db:
condition: service_healthy
api:
image: myapp:latest
depends_on:
db-init:
condition: service_completed_successfully
Summary
| Strategy | Best For |
|---|---|
condition: service_healthy |
Most cases |
| wait-for-it | Legacy images without healthcheck |
| App retry logic | Production robustness |
| Init containers | One-time setup tasks |
Quick Reference
| Item | Detail |
|---|---|
| service_healthy | Best Docker-level strategy |
| wait-for-it | TCP port wait script |
| dockerize | Multi-dependency TCP wait |
| App retry | Most robust, defense in depth |
| Init container | service_completed_successfully |