Init Container Patterns Kubernetes
Use init containers for dependency waiting, database migration, config generation, certificate fetching, and permission setup.
π‘ Quick Answer: Init containers run sequentially before app containers start. Use them for: waiting on dependencies (
wait-for-db), running database migrations, fetching certificates/configs, and setting file permissions on shared volumes.
The Problem
Applications often need prerequisites before starting: database must be reachable, migrations must run, config files must exist, TLS certificates must be fetched. Without init containers, you embed this logic in the application β mixing concerns and complicating the image.
The Solution
Pattern 1: Wait for Dependency
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ['sh', '-c']
args:
- |
until nc -z postgres-svc 5432; do
echo "Waiting for PostgreSQL..."
sleep 2
done
echo "PostgreSQL is ready"Pattern 2: Database Migration
initContainers:
- name: migrate
image: registry.example.com/my-app:1.5.0
command: ['./migrate', '--direction', 'up']
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: urlPattern 3: Fetch TLS Certificates
initContainers:
- name: fetch-certs
image: registry.example.com/cert-fetcher:1.0
command: ['sh', '-c']
args:
- |
vault read -field=certificate secret/tls/my-app > /certs/tls.crt
vault read -field=private_key secret/tls/my-app > /certs/tls.key
chmod 600 /certs/tls.key
volumeMounts:
- name: certs
mountPath: /certs
containers:
- name: app
volumeMounts:
- name: certs
mountPath: /etc/tls
readOnly: true
volumes:
- name: certs
emptyDir: {}Pattern 4: Fix Volume Permissions
initContainers:
- name: fix-permissions
image: busybox:1.36
command: ['sh', '-c', 'chown -R 1000:1000 /data']
securityContext:
runAsUser: 0
volumeMounts:
- name: data
mountPath: /datagraph LR
INIT1[Init 1:<br/>wait-for-db] -->|Success| INIT2[Init 2:<br/>migrate]
INIT2 -->|Success| INIT3[Init 3:<br/>fetch-certs]
INIT3 -->|Success| APP[App Container<br/>Starts]
INIT1 -->|Failure| RETRY1[Retry Init 1]
INIT2 -->|Failure| RETRY2[Retry Init 2]Common Issues
Init container stuck β pod stays in Init:0/3
The init container is failing or waiting indefinitely. Check logs:
kubectl logs my-pod -c wait-for-dbInit container canβt resolve DNS
Init containers run before the pod network is fully configured on some CNIs. Add a small sleep or use IP addresses instead of service names.
Best Practices
- Keep init containers lightweight β use
busyboxoralpine, not your full app image - One responsibility per init container β easier to debug when theyβre sequential
- Share data via emptyDir volumes β init containers write, app containers read
- Set resource requests on init containers β they count toward pod scheduling
- Use
restartPolicy: Alwayson init containers (K8s 1.29+ sidecar containers) for long-running helpers
Key Takeaways
- Init containers run sequentially, each must succeed before the next starts
- They share volumes with app containers via emptyDir or PVC
- Common patterns: dependency wait, migration, cert fetch, permission fix
- Init container resources count toward pod resource calculation
- K8s 1.29+ adds native sidecar containers (
restartPolicy: Alwayson init containers)

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
