• Modern UX

    Edit and navigate faster in the terminal with Warp's IDE-like input editor.

  • Warp AI

    AI suggests what commands to run and learns from your documentation.

  • Agent Mode

    Delegate tasks to AI and use natural language on the command line.

  • Warp Drive

    Save and share interactive notebooks, workflows, and environment variables.

  • All Features

Understand depends_on in Docker Compose

Thumbnail for Razvan LudosanuRazvan Ludosanu

Razvan Ludosanu

Founder, learnbackend.dev

Published: 1/31/2024

About Terminus

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:

Thumbnail for

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

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

Thumbnail for Razvan LudosanuRazvan Ludosanu

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.

Docker

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.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

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.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

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.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Use An .env File In Docker

Learn how to write and use .env files in Docker to populate the environment of containers on startup.

Docker

Run SSH In Docker

Learn how to launch and connect to a containerized SSH server in Docker using password-based authentication and SSH keys.

Docker
Thumbnail for Gabriel ManricksGabriel Manricks

Launch MySQL Using Docker Compose

Learn how to launch a MySQL container in Docker Compose.

DockerSQL

Execute in a Docker Container

Learn how to execute one or multiple commands in a Docker container using the docker exec command.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Expose Docker Container Ports

Learn how to publish and expose Docker container ports using the docker run command and Dockerfiles.

Docker

Restart Containers In Docker Compose

Learn how to restart and rebuild one or more containers in Docker Compose.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

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

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Rename A Docker Image

Learn how to rename Docker images locally and remotely using the docker tag command.

Docker

Trusted by hundreds of thousands of professional developers

Download Warp to get started

Download for Mac
Thumbnail for null