Course contentsShow
← Docker, Kubernetes & CI/CD
Lesson 207 of 8023. Docker Orchestration and StorageFree lesson

Orchestrating Multi-Container Database Migrations

You will automate the execution of database schema migration scripts as a prerequisite step before starting the main application service.

In this lesson, you will learn how to automate your database schema updates so your application always starts with the correct data structure.

The Problem: The "Version Mismatch" Trap

In a multi-container environment, your application container and your database container are independent. If you deploy a new version of your app that expects a new users_email column, but the database hasn’t been updated yet, the application will crash on startup. We solve this by introducing an "Init Container" pattern or a pre-start migration step.

Orchestrating the Migration

The goal is to ensure the database schema is at the correct version before the application attempts to connect. While we have used depends_on to start services in a specific order, depends_on only checks if the container is running, not if the database is "ready" or if the schema is updated.

To handle this in a docker-compose.yml, we can define a dedicated migration service that runs a one-off task:

services:
  db:
    image: postgres:15
    # ... volume and network config ...

  migrate:
    image: my-app-migration-tool
    depends_on:
      db:
        condition: service_healthy
    command: ["./run-migrations.sh"]

  web:
    image: my-app:latest
    depends_on:
      migrate:
        condition: service_completed_successfully

Why this works

  1. service_healthy: Using the health checks we learned previously, we ensure the database is actually ready to accept queries.
  2. Dedicated Migration Container: By splitting the migration logic into a separate service, we can use a lightweight image containing only the tools needed to talk to the DB (like Flyway or Liquibase).
  3. service_completed_successfully: This acts as an orchestration gate. Docker Compose will wait for the migrate container to execute its script and exit with a success code (0) before it triggers the startup of your web application. This ensures that when your application code starts, the tables and columns it requires are guaranteed to exist.

Key Takeaway: By using depends_on with service_completed_successfully, you transform your migration scripts from a manual risk into an automated, reliable prerequisite of your deployment pipeline.