✦ For everyone, free.

Practical knowledge for real and everyday life

Home

6.2.3.2 Migration Job Containers

A focused guide to Migration Job Containers, connecting core concepts with practical Docker and container operations.

Migration job containers are a specific, common application of one-off containers, used to run database schema migrations as a discrete, isolated task that runs to completion and exits, typically before a new application version's service containers begin handling traffic.

Running a Migration as a One-Off Container

A migration is executed using the application's own image, ensuring the migration logic uses exactly the same dependencies and configuration the application itself relies on.

docker run --rm \
  -e DATABASE_URL=$DATABASE_URL \
  myapp:2.0 python manage.py migrate
Why Migrations Should Run Before New Service Containers Start

Running a migration as a distinct step before deploying new service containers ensures the database schema is in the expected state before application code that depends on that schema begins actually serving traffic.

docker run --rm myapp:2.0 python manage.py migrate
docker run -d --name myapp myapp:2.0

Running the migration first, and only proceeding to start the actual service afterward, avoids a window where the new application code might be running against a not-yet-migrated database schema.

Handling Migration Failure Before Deployment Proceeds

Because a migration container's exit code reflects whether the migration succeeded, a deployment pipeline can check this before proceeding, halting deployment entirely if the migration itself failed.

docker run --rm myapp:2.0 python manage.py migrate
if [ $? -ne 0 ]; then
  echo "Migration failed, aborting deployment"
  exit 1
fi
Why a Separate Migration Container Is Preferable to Running Migrations on Service Startup

Running migrations automatically every time a service container starts risks multiple replicas attempting to run the same migration concurrently; a single, dedicated migration container run once, before scaling up the actual service, avoids this race condition entirely.

docker run --rm myapp:2.0 python manage.py migrate
docker run -d --name myapp-1 myapp:2.0
docker run -d --name myapp-2 myapp:2.0
Why Migration Job Containers Matter

Treating database migrations as a distinct, one-off container task — run once, checked for success, completed before scaling up the actual service — is a reliable, well-established pattern for safely coordinating schema changes alongside application deployments.