Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 11 min read

Migrating Docker Compose to Kubernetes With AI Help

A practical walkthrough of converting a docker-compose.yml into clean Kubernetes manifests with AI drafting the boilerplate and you reviewing every line.

  • #kubernetes
  • #docker-compose
  • #migration
  • #ai

I inherited a docker-compose.yml that ran a six-service app perfectly well on one beefy VM, and a mandate to get it onto Kubernetes “this quarter.” Compose and Kubernetes look superficially similar — services, images, ports, volumes — but the mapping is full of small traps. Doing the conversion by hand is slow and error-prone. Doing it entirely with a one-shot tool gives you manifests you don’t understand. The approach that actually worked was a middle path: let an AI model draft the manifests service by service, and review each one like I would a junior engineer’s PR.

Why not just use kompose?

kompose convert exists and it’s a fine starting point. But it produces literal, naive output: every service becomes a Deployment plus a Service, host volumes become hostPath mounts, and depends_on is silently dropped because Kubernetes has no equivalent. You end up rewriting most of it anyway.

The reason I reach for an AI model instead is that it can reason about intent. When I tell it “this postgres service holds data,” it knows to suggest a StatefulSet with a PersistentVolumeClaim rather than a Deployment with an ephemeral mount. That contextual judgment is what saves real time. I still run kompose sometimes just to compare outputs.

Start by sharing the compose file, nothing else

The compose file is safe to share with the model — it’s declarative config. What I scrub first: any inline secrets, real passwords in environment: blocks, and private registry paths. The model never sees my cluster, my kubeconfig, or production credentials. Its job is to transform text I hand it.

My opening prompt:

Here is a docker-compose.yml. Convert each service to Kubernetes manifests. Use Deployments for stateless services and StatefulSets for anything with a named volume holding data. Generate a Service per workload, ConfigMaps for non-secret env, and leave a # TODO: secret comment wherever a value looks sensitive. Do not invent resource limits — leave them as TODOs.

That last sentence matters. Left alone, models confidently fabricate resources blocks with numbers pulled from nowhere. I want placeholders I fill in from real metrics, not guesses.

Map the concepts deliberately

Here is the translation table I keep in front of me while reviewing the model’s output:

ComposeKubernetes
service (stateless)Deployment + Service
service (with data volume)StatefulSet + PVC + headless Service
portsService ports / container containerPort
environmentConfigMap or Secret
volumes (named)PersistentVolumeClaim
depends_on(no equivalent — use readiness probes)
restart: alwaysdefault pod restart policy
networksNetworkPolicy if isolation matters

The depends_on row trips people up. Compose starts containers in order; Kubernetes does not. The model knows this and, when prompted, replaces ordering assumptions with proper readiness probes so dependent pods wait for their dependencies to actually be ready, not just started.

What a converted service looks like

For a stateless API service, the draft came back clean:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: "registry.example.com/api:1.4.0"
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: api-config
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
          # TODO: set resources from real metrics

The probe was a nice touch the model added on its own — but I verified the /healthz path actually exists, because models will happily invent a health endpoint that your app doesn’t serve.

Verify before anything touches a cluster

I never apply generated manifests directly. The review pipeline is entirely offline first:

# Syntactic + schema validation, no cluster needed
kubectl apply --dry-run=client -f manifests/

# Server-side dry run against a non-prod cluster
kubectl apply --dry-run=server -f manifests/ --namespace staging

Client-side dry-run catches malformed YAML and bad field names. Server-side dry-run runs the manifests through admission control and the API server’s validation without persisting anything — it catches the subtler problems like an invalid securityContext or a Service selecting no pods.

Pro Tip: Run kubectl apply --dry-run=server against staging, never prod, even though it doesn’t persist objects. Admission webhooks can have side effects, and you want the human-in-the-loop discipline of treating “talks to prod” as a line the AI workflow never crosses.

The things AI consistently gets wrong

After a dozen of these migrations, the recurring miss list is predictable, and it’s the whole reason a human reviews every file:

  • Shared volumes. Compose lets two services mount the same named volume. In Kubernetes, ReadWriteOnce PVCs can’t span nodes. The model needs reminding to use ReadWriteMany or rethink the design.
  • Localhost networking. Compose services on the same network reach each other on localhost when in the same pod, but separate pods use Service DNS names. Generated code sometimes keeps localhost references that quietly break.
  • .env files. Models tend to inline env values rather than splitting genuine secrets into a Secret object.

I treat the first pass as a draft, then go through it asking “does this actually match how the app talks to itself?”

Bring secrets in safely

The model leaves # TODO: secret markers; I fill them with a real secrets workflow, not by pasting values into a manifest. That usually means an external secrets operator pulling from a vault, so no plaintext credential ever lands in Git or in the model’s context.

Wrap up

Converting Compose to Kubernetes is mechanical enough that AI saves you hours, and judgment-heavy enough that you can’t fully automate it. Let the model draft Deployments, Services, and ConfigMaps; you decide what’s stateful, what’s secret, and what gets applied. The model never holds your kubeconfig, and nothing reaches the cluster without a human running the command.

Keep going with the Kubernetes & Helm category, reusable prompts, and the Kubernetes prompt pack. If you want a second set of eyes on the generated manifests, the code review dashboard catches the localhost-and-shared-volume mistakes before they ship.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.