Zum Inhalt springen
EdgeServers
Blog

docker

From Docker Compose to Kubernetes — the migration that doesn't have to be painful

A staged migration playbook from docker-compose to Kubernetes, including the patterns that translate cleanly and the ones that need rethinking.

22. Mai 2026 · 9 min · von Sudhanshu K.

From Docker Compose to Kubernetes — the migration that doesn't have to be painful

Most "migrate from Compose to Kubernetes" guides skip the question of whether you should — and then they botch the how. They tell you to run kompose convert, push the YAML into a cluster, and call it done.

This is not that guide. The Compose-to-Kubernetes migration we walk customers through covers four real concerns: when to migrate, what to migrate first, what doesn't translate cleanly, and how to phase the cutover without an outage. We've done this enough times for managed Docker and Kubernetes customers to have strong opinions on each step.

When should you migrate?

Compose is fine. It's more than fine — it's the right tool for many production workloads. The dogma that "everything must be Kubernetes" is a 2018 take that hasn't aged well. We still run Compose in production for plenty of customers.

You should migrate when:

  • You need to run on more than ~3 nodes and the manual orchestration of docker compose up across them has become painful
  • You need autoscaling that Compose can't provide
  • You need finer-grained access control between services (NetworkPolicy)
  • You're integrating with a managed service mesh / service catalog
  • Your team is hitting the limits of Compose's single-host scheduling model

You should not migrate just because Kubernetes is fashionable. Honest assessment: a five-service Compose stack on a beefy VM, deployed via SSH and a git pull, will outlive most Kubernetes clusters with one-tenth the operational cost. If that's where you are and it works, don't migrate.

What stays the same

The good news is that 80% of a Compose stack translates directly:

ComposeKubernetes
services:Deployment (stateless) or StatefulSet (stateful)
image:spec.containers[].image
command: / entrypoint:spec.containers[].command/args
environment:env: (or envFrom: configMapRef)
volumes:volumeMounts + volumes (PVC for persistent)
ports:Service of type ClusterIP/LoadBalancer/NodePort
depends_on: (with condition: service_healthy)Init containers + readiness probes
networks:Default (everything in a namespace can talk) + NetworkPolicy if you want isolation
healthcheck:livenessProbe + readinessProbe

The naive kompose convert will get you a working draft of all of this. The output won't be production-quality, but it's a starting point.

What doesn't translate cleanly

The 20% that needs real thought:

1. depends_on semantics

Compose's depends_on: service_healthy means "don't start me until that service is healthy." Kubernetes doesn't have this concept directly — pods start in parallel, and your app needs to retry connections at runtime.

This is usually a code change, not a YAML change. If your app crashes when it can't reach the database on startup, you need to fix that. Pods will restart and eventually succeed, but a graceful "connection retry with backoff" is much cleaner than crash-loop-until-database-is-up.

The other option is an init container that polls until the dependency is reachable:

initContainers:
- name: wait-for-db
  image: busybox
  command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']

But this is a band-aid. Fix the app retry logic first.

2. volumes: for state

Compose volumes are simple: a named volume gets mounted at a path, persisted across container restarts on the same host. Kubernetes PVs / PVCs are not like this. They have access modes, storage classes, reclaim policies, and they're tied to the cluster's underlying storage system.

Critical distinction: ReadWriteOnce PVs can only be mounted by one node at a time. If your Compose service has 3 replicas all writing to a shared volume — common for an Nginx serving uploads in a shared directory — that pattern does not directly work in Kubernetes with most cloud-native block storage.

The options:

  • Move the shared state to object storage (S3, GCS, Azure Blob)
  • Use a ReadWriteMany-capable storage class (EFS, Filestore, Azure Files — slower and more expensive)
  • Move that piece of state to a real database/cache rather than the filesystem

Most "ah this volume just gets shared between replicas" patterns in Compose are actually bugs waiting to happen at scale. The Kubernetes migration is a good time to fix them.

3. network_mode: host and friends

Compose lets a container share the host network. Kubernetes has hostNetwork: true but using it removes most of the pod isolation benefits. If your Compose stack relies on host networking, audit why — usually it's accidental, sometimes there's a real reason (high-performance UDP workload, for instance). Replace with proper Service resources where possible.

4. restart: unless-stopped semantics

Compose's restart policy is per-container. Kubernetes is at the pod level (restartPolicy: Always is the default for Deployments, which is what you want). Mostly translates fine, but with one nuance: Kubernetes does exponential backoff between restarts after repeated failures (CrashLoopBackOff). Compose doesn't. A bug that causes a pod to crash on startup will start looking like a "Kubernetes isn't working" problem when actually it's a "your container is crashing" problem with backoff applied.

A staged migration plan

The pattern that works:

Stage 1: Lift-and-shift to managed Kubernetes (week 1-2)

  • Get a Kubernetes cluster provisioned on the target cloud (EKS, GKE, AKS, or DOKS)
  • Run kompose convert -f docker-compose.yml
  • Hand-edit the output for the gotchas above
  • Deploy to a staging namespace
  • Verify the application functions

This is the dumbest possible translation. Don't get fancy. Pods are running, the database is running, the application responds. Resist the temptation to introduce Istio, Argo CD, autoscaling, and 14 other things in the same week. One thing at a time.

Stage 2: Production parity (week 3-4)

  • Wire up your real container registry (not Docker Hub)
  • Add resource requests and limits based on observed Compose usage
  • Add NetworkPolicies for namespace isolation
  • Wire up monitoring (Prometheus + Grafana, or your existing observability stack)
  • Configure persistent storage properly (see above)
  • Run load tests; resolve OOMs and CPU throttling

This is where you fix the things that Compose was hiding. Compose has no notion of resource limits, so workloads have been sharing host resources opportunistically. In Kubernetes you have to be explicit, and the act of being explicit usually surfaces 2-3 misbehaving services.

Stage 3: Cutover (week 5)

  • Set up DNS with a 60-second TTL the week before
  • On cutover day, scale up Kubernetes-side, scale down Compose-side, flip DNS
  • Keep the Compose stack warm for 72 hours as a rollback option

If you're moving across clouds simultaneously (Compose-on-EC2 to GKE, say), you'll have a window where both stacks are running and you need to sync state between them. Treat this as a data migration problem, not a container orchestration problem.

Stage 4: Earn the Kubernetes features (months 2-6)

This is where you actually benefit from the migration. Now you add:

  • Horizontal Pod Autoscaling on the right services
  • GitOps pipeline (Argo CD)
  • Image signing and admission control
  • Pod Security Standards in restricted mode
  • Service mesh if your traffic patterns actually need one (most don't)

Each of these is a separate, focused project. Bundling them into "the migration" is how migrations fail.

What I tell customers who are still on the fence

A direct quote from a customer onboarding call a few weeks ago: "We have eight Compose services, on one big EC2 instance, deployed via a single bash script. Should we migrate?"

My answer: not yet. Their next painful moment will be when one of those services needs to scale independently, or they need to add a second region, or the bash script becomes the bottleneck for their deploy cadence. Then the migration pays off. Until then, Compose is doing its job and the operational simplicity is genuinely valuable.

When the time comes, you want to do the migration once, well, with a clear plan. We've done this enough times that we can usually compress a 3-month internal effort into a 4-6 week engagement. Reach out if you're at that point — we'll do a free assessment and tell you honestly if migrating now makes sense.

Sudhanshu K. is Principal Engineer at EdgeServers (RemotIQ Pty Ltd, ABN 91 682 628 128). He has migrated more Compose stacks to Kubernetes than he can count, and has talked roughly the same number of customers out of migrating because they didn't need to.