Skip to content

Phase 7: The Migration Project

Time: weeks 7-8. Goal: move your real Docker deployment. This is the capstone - and you can start sketching it from Phase 3 onward.

The recipe

A repeatable, step-by-step process for migrating a compose stack.

1. Inventory

List every compose service and classify it:

  • Stateless app - the easy bulk.
  • Stateful store - DBs, queues, caches. Each needs a deliberate decision.
  • One-off / cron task - becomes Jobs and CronJobs.
  • Infra you should NOT migrate - candidates for managed services instead.

2. Images

k8s pulls from a registry; there is no build: directive.

  • Confirm everything builds to a registry-pushed image.
  • Set up a registry path and an image tagging scheme. Never latest - k8s can't roll back what it can't distinguish, and cached latest tags cause "why is the old version running" mysteries.

3. Per stateless service: Deployment + Service

Compose constructBecomes
environment: / .envConfigMap (+ Secret for credentials)
depends_onReadiness probes + retry logic in the app
restart: alwaysNothing - controllers give you this for free
healthcheck:Liveness/readiness probes
service name DNSService (ClusterIP), usually the same name

depends_on deserves emphasis: k8s has no startup ordering, by design. Pods start whenever. Your app must tolerate its dependencies being briefly unavailable (retry on connect) and use readiness probes to avoid receiving traffic before it's ready. If your app crashes when the DB isn't up yet, fix the app, don't fight the platform.

4. Per stateful service: decide honestly

Two options per store:

  • In-cluster: StatefulSet + PVC. Fine for dev/test, defensible for prod if you know what you're doing.
  • Managed service outside the cluster: for production databases, the boring answer is usually right.

5. Networking

  • Compose service-name DNS maps almost 1:1 to k8s Services, so inter-service URLs often survive unchanged.
  • All published ports (-p) collapse into one Ingress with host/path rules.

6. Cron and one-offs

Host crontabs and docker run scripts become CronJobs and Jobs.

7. Cutover

  1. Run both stacks in parallel.
  2. Point a test domain at the k8s ingress.
  3. Validate everything against the test domain.
  4. Flip DNS.
  5. Keep the compose stack as rollback for a week before decommissioning.

On kompose

kompose auto-converts compose files to k8s manifests. Use it once as a cheat sheet to compare against your own work, but write the manifests by hand - the auto-generated output is mediocre and using it directly skips the learning this whole syllabus exists for.

What to defer

Service meshes (Istio), authoring operators/CRDs, multi-cluster, GitOps (ArgoCD/Flux) are all real, but they're layer two. GitOps is the first one worth adding once the migration is done: your manifests already live in git, ArgoCD just makes the cluster follow the repo.

Checkpoint (done = done)

  • Every compose service has a classified destination and a manifest.
  • The full stack runs on k8s in parallel with the old deployment.
  • You executed a cutover plan with a tested rollback path.

A VineLab lab. Released under the MIT License.