Cloud Native 8 min read

Migrating Docker Compose Stacks to Kubernetes with Kompose

This article explains how to transition containerized applications from Docker Compose to Kubernetes using the Kompose tool, covering code examples, generated manifests, volume handling, ingress considerations, and best‑practice recommendations for production deployments.

DevOps Cloud Academy
DevOps Cloud Academy
DevOps Cloud Academy
Migrating Docker Compose Stacks to Kubernetes with Kompose

Running your codebase in a containerized environment is common, but making it production‑ready often requires moving from Docker Compose to a more robust orchestration platform like Kubernetes.

Docker‑Compose

Docker‑Compose is a tool that defines and runs multi‑container Docker applications using a YAML file, allowing developers to build, configure, and launch the entire stack—including databases, back‑ends, front‑ends, and workers—with a single command.

Kubernetes

Kubernetes manages resources through declarative configuration files. Below is a typical Deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

The challenge is converting an existing Docker‑Compose stack into equivalent Kubernetes manifests.

Kompose

Kompose is an open‑source utility that helps users familiar with Docker‑Compose migrate to Kubernetes by converting Compose files into Kubernetes objects.

Example docker-compose.yaml used in the article:

version: "3.3"
services:
  # Traefik
  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=$ACME_EMAIL"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
    volumes:
      - "./traefik:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  # Database
  db:
    image: postgres:9.4
    container_name: "odoo-database"
    environment:
      - POSTGRES_PASSWORD=$POSTGRES_PASSWORD
      - POSTGRES_USER=$POSTGRES_USER
    volumes:
      - ./postgresql:/var/lib/postgresql/data
    restart: always

  # Odoo
  odoo10:
    image: odoo:10.0
    container_name: "odoo-10"
    depends_on:
      - db
    volumes:
      - ./odoo-10/addons:/mnt/extra-addons
      - ./odoo-10/etc:/etc/odoo
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.odoo.rule=Host(`$ODOO_URL`)"
      - "traefik.http.routers.odoo.entrypoints=websecure"
      - "traefik.http.routers.odoo.tls.certresolver=myresolver"

  # PGAdmin
  pgadmin:
    image: dpage/pgadmin4:4.25
    container_name: pgadmin4
    environment:
      - [email protected]
      - PGADMIN_DEFAULT_PASSWORD=odoo
      - PGADMIN_LISTEN_PORT=80
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.pgadmin.rule=Host(`$PGA_URL`)"
      - "traefik.http.routers.pgadmin.entrypoints=websecure"
      - "traefik.http.routers.pgadmin.tls.certresolver=myresolver"

Running kompose convert generates a set of ready‑to‑deploy Kubernetes manifests, but the output often contains placeholders that must be manually filled (e.g., URLs for Traefik routing).

metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.26.1 (HEAD)
    traefik.enable: "true"
    traefik.http.routers.odoo.entrypoints: websecure
    traefik.http.routers.odoo.rule: Host(``) # <-- fill in
    traefik.http.routers.odoo.tls.certresolver: myresolver

Limitations of Kompose include the lack of automatic Persistent Volume (PV) generation; users must create PersistentVolumeClaims (PVCs) and corresponding PVs manually. Without them, pods will fail with errors such as:

pod has unbound immediate PersistentVolumeClaims

Ingress handling is another area where Kompose falls short. Kubernetes typically uses an Ingress Controller to expose services externally. Kompose does not generate Ingress resources, so users often resort to NodePort services, which can cause port conflicts when multiple stacks use the same ports (e.g., 443).

Conclusion

Kompose simplifies the initial conversion of Docker‑Compose files to Kubernetes manifests, saving time during proof‑of‑concept phases. However, the generated configurations require careful review, completion of missing fields, and additional resources (PVCs, Ingress) before production deployment. Directly embedding Kompose into CI/CD pipelines without manual validation is not advisable, and managing a Kubernetes cluster demands solid expertise to avoid operational issues.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerKubernetesDevOpscontainerizationKompose
DevOps Cloud Academy
Written by

DevOps Cloud Academy

Exploring industry DevOps practices and technical expertise.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.