Init Container for Database Migration

Use a Kubernetes init container to run database migrations before the main application starts, ensuring the schema is always up to date when new pods are created.

Patterns

Detailed Explanation

Init Containers for Migrations

Init containers run before the main application containers and must complete successfully before the pod starts. This makes them ideal for running database migrations, schema updates, or other one-time setup tasks.

Key Configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-with-migration
  labels:
    app: "web"
spec:
  replicas: 3
  template:
    spec:
      initContainers:
        - name: migrate
          image: my-app:latest
          command: ["npm", "run", "migrate"]
          env:
            - name: DATABASE_URL
              value: "postgres://admin:changeme@postgres:5432/mydb"
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"
      containers:
        - name: web
          image: my-app:latest
          ports:
            - name: http
              containerPort: 3000
          env:
            - name: DATABASE_URL
              value: "postgres://admin:changeme@postgres:5432/mydb"

How Init Containers Work

  1. When a pod is created, Kubernetes runs init containers sequentially (one at a time)
  2. Each init container must exit with code 0 before the next one starts
  3. If an init container fails, Kubernetes restarts it according to the pod's restartPolicy
  4. Only after all init containers succeed do the main containers start
  5. Init containers do not have readiness or liveness probes

Migration Safety

When running migrations with multiple replicas, only one migration should run at a time. Strategies:

  • Advisory locks: Use database-level advisory locks in your migration tool (e.g., Prisma, Flyway, Alembic)
  • Leader election: Use a Kubernetes Job for migrations instead of init containers
  • Deployment strategy: Set maxSurge: 1 and maxUnavailable: 0 so only one pod at a time goes through the init phase

Common Init Container Uses

  • Database migrations and schema updates
  • Waiting for dependent services to be ready
  • Downloading configuration files from external sources
  • Generating configuration from templates
  • Setting file permissions on mounted volumes

Use Case

Running database migrations, schema updates, or other setup tasks automatically before application pods start. Ensures the database schema is always in sync with the deployed code version.

Try It — K8s Pod Spec Builder

Open full tool