Understand depends_on in Docker Compose
Razvan Ludosanu
Founder, learnbackend.dev
Published: 1/31/2024
The short answer
In Docker Compose, depends_on field is used to express the dependencies between the services of an application and specify the order in which these services should be started and stopped.
In this example, the api service depends on the database service. When using the docker compose up command, Compose will start the database service first, then start the api service:
version: '3'
services:
api:
build: .
depends_on:
- database
database:
image: postgres
Run in Warp
You can learn more about building applications running PostgreSQL with our article on how to launch PostgreSQL with Docker Compose.
Easily retrieve this syntax using Warp AI feature
If you’re using Warp as your terminal, you can easily retrieve this syntax using the Warp AI feature:
Entering docker compose depends_on in the AI question input will prompt a human-readable step by step guide including code snippets.
Controlling the services startup with conditions
By default, Compose only ensures that the services listed under the depends_on property are started before the dependent service. This means that Compose doesn't guarantee that these services are fully operational and ready to process requests, but only that their containers are running.
It is however possible to set conditions to define when one service should start or wait for another service to reach a specific state. These conditions are defined in the condition property and take three possible values: service_started, service_healthy, and service_completed_successfully.
The service_started condition
This condition is the default condition used by Compose and only checks whether the service's container has started, without verifying the service's internal state or health.
In this example, Compose will first start the database service, then start the api service once the database service's container has started.
version: '3'
services:
api:
build: .
depends_on:
database:
condition: service_started
database:
image: postgres
Run in Warp
The service_healthy condition
This condition is used to ensure not only that the service's container has started but also that the service inside the container has successfully passed a health check. It ensures that the service is fully operational and ready to accept requests.
It is often combined with the healthcheck property that allows developers to define a custom health check for a given service. You can learn more about this property by reading the official Compose documentation page.
In this example, Compose will first start the database service, execute the pg_isready command specified in the healthcheck.test property, and then start the api service if the value returned by the test command is 0.
version: '3'
services:
api:
build: .
depends_on:
database:
condition: service_healthy
database:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
Run in Warp
The service_completed_successfully condition
This condition is used to ensure that the service's container not only starts and runs, but also completes its execution successfully. It's useful in scenarios where the dependent service is a one-time job or task, such as a data migration script, and you want to make sure it finishes without errors before starting another service.
To use service_completed_successfully, you should ensure that the dependent service exits with a zero status code upon successful completion.
In this example, Compose will first start the database service, execute the pg_isready command specified in the healthcheck.test property, start the migration service if the value returned by the test command is 0, and finally start the api service if the exit status of the migration service's container is also 0.
version: '3'
services:
api:
build: .
depends_on:
database:
condition: service_healthy
migration:
condition: service_completed_successfully
database:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
migration:
image: migration-tool
Run in Warp
Restarting services manually
When set to true, the restart property allows you to automatically restart the dependent service whenever you perform a manual restart or operation using the docker compose command.
It's important to note that this setting doesn't affect the automated restart policy defined in the service itself that is typically managed by the container runtime when the container exits unexpectedly.
In this example, Compose will restart the api service if the database service is manually restarted using the docker compose restart command. But it won't be restarted if the database service crashes and is restarted due to the always restart policy.
version: '3'
services:
api:
build: .
depends_on:
database:
restart: true
database:
image: postgres
restart: always
Run in Warp
You can learn more about the restart command by reading the official Docker documentation page.
Depending on external services
The depends_on property only works for services defined within the same compose.yaml file. If your application relies on external services, like a database hosted on a remote server, you'll need to implement custom retry logic in your application to handle dependencies gracefully.
Using wait-for scripts
One way to achieve this is to use a "wait-for" script, that will periodically check if the external service is available before proceeding with your application's startup.
For example, the following script will check every 3 seconds if the status code of the HTTP response sent by the service's /health endpoint located at 127.0.0.1:8080 is 200. It will then exit with a value of 0 if successfully connected to the service or with a value of 1 after 5 unsuccessful attempts.
#!/bin/bash
HOST="127.0.0.1"
PORT="8080"
MAX_ATTEMPTS=5
DELAY_BETWEEN_ATTEMPS=3
attempt=1
while true; do
test=$(curl -s -I "$HOST:$PORT/health" | head -n 1 | cut -b 10-12)
if [ "$test" == 200 ]; then
exit 0
fi
sleep "$DELAY_BETWEEN_ATTEMPS"
attempt=$((attempt + 1))
if [ "$attempt" -gt "$MAX_ATTEMPTS" ]; then
exit 1
fi
done
Run in Warp
This script can then be packaged into a standalone image running on a lightweight distribution such as Alpine Linux, and executed using the service_completed_successfully condition as demonstrated in the following example:
version: '3'
services:
website:
build: .
depends_on:
api:
condition: service_completed_successfully
api:
image: wait-for-api
Run in Warp
The depends_on vs link properties
While the depends_on property is used to express the dependencies between the services of an application, the links property is used to establish network communication between containers, which can be particularly useful for microservices architectures.
It allows one container to access services provided by another container using a specific alias, but doesn't whatsoever guarantee the availability or readiness of these services.
Written by
Razvan Ludosanu
Founder, learnbackend.dev
Filed Under
Related Articles
Override the Container Entrypoint With docker run
Learn how to override and customize the entrypoint of a Docker container using the docker run command.
The Dockerfile ARG Instruction
Learn how to define and set build-time variables for Docker images using the ARG instruction and the --build-arg flag.
Start a Docker Container
Learn how to start a new Docker container from an image in both the foreground and the background using the docker-run command.
Stop All Docker Containers
How to gracefully shutdown running containers and forcefully kill unresponsive containers with signals in Docker using the docker-stop and docker-kill commands.
Use An .env File In Docker
Learn how to write and use .env files in Docker to populate the environment of containers on startup.
Run SSH In Docker
Learn how to launch and connect to a containerized SSH server in Docker using password-based authentication and SSH keys.
Launch MySQL Using Docker Compose
Learn how to launch a MySQL container in Docker Compose.
Execute in a Docker Container
Learn how to execute one or multiple commands in a Docker container using the docker exec command.
Expose Docker Container Ports
Learn how to publish and expose Docker container ports using the docker run command and Dockerfiles.
Restart Containers In Docker Compose
Learn how to restart and rebuild one or more containers in Docker Compose.
Output Logs in Docker Compose
Learn how to output, monitor, customize and filter the logs of the containers related to one or more services in Docker Compose
Rename A Docker Image
Learn how to rename Docker images locally and remotely using the docker tag command.