Init Containers
Init containers run and finish before the main containers start, handling setup work.
spec:
initContainers:
- name: <name>
image: <image>
containers:
- name: <name>
image: <image>An init container is a special container that runs to completion before the app containers start. If it fails, Kubernetes restarts it until it succeeds.
What they are good for
- Waiting for a database or another service to become reachable.
- Running a one-time database migration or schema setup.
- Downloading or generating files the main app needs.
- Setting file permissions on a shared volume.
How they run
Init containers run one at a time, in order. Only when the last one finishes do the regular containers begin. This guarantees your setup is done before the app boots.
Example
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ['sh', '-c', 'until nc -z db 5432; do echo waiting; sleep 2; done']
containers:
- name: app
image: myapp:1.0
ports:
- containerPort: 8080When to use it
- An init container waits for a database to become reachable before the main application container starts, preventing connection errors on boot.
- A security-focused team uses an init container to fetch secrets from HashiCorp Vault and write them to a shared volume, keeping secrets out of environment variables.
- A migration init container applies database schema changes before the new application version starts, ensuring the schema is always compatible on startup.
More examples
Wait-for-db init container
Polls the postgres service port in a loop inside an init container and only exits (success) once the database is reachable.
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command:
- sh
- -c
- |
until nc -z postgres-svc 5432; do
echo "Waiting for postgres..."
sleep 2
done
containers:
- name: app
image: myapp:1.0Fetch secret into shared volume
Uses a Vault init container to write a secret to a shared emptyDir volume, which the main app reads at runtime.
spec:
initContainers:
- name: fetch-secret
image: vault:1.15
command:
- sh
- -c
- vault read -field=password secret/db > /vault/secret/db_pass
volumeMounts:
- name: secret-vol
mountPath: /vault/secret
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: secret-vol
mountPath: /run/secrets
volumes:
- name: secret-vol
emptyDir: {}Multiple ordered init containers
Defines two init containers that run sequentially: the DB migration completes first, then the cache seeder runs, before the app starts.
spec:
initContainers:
- name: migrate-db
image: myapp-migrations:1.0
command: ["./run-migrations.sh"]
- name: seed-cache
image: myapp-seeder:1.0
command: ["./seed-redis.sh"]
containers:
- name: app
image: myapp:1.0
Discussion