✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Migration Job Containers

Migration Job Containers enable seamless data transfer between environments using Docker, ensuring reliability and scalability in containerized workflows

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.