From Docker Desktop to Podman Desktop — and Why Quadlets Led Me to Kubernetes — hero banner

April 15, 2025·3 min read

Like many developers, I started with Docker Desktop because it “just worked.” But over time, the licensing changes, resource usage, and the need for better security led me to explore Podman Desktop.

This article is both a migration guide and a story of discovery: how I replaced Docker Desktop with Podman, experimented with Quadlets for container management, and ultimately landed on Kubernetes (MicroK8s) for orchestration.


Part 1 — Migrating from Docker Desktop to Podman Desktop

Why leave Docker Desktop?

  • Licensing & cost: Docker Desktop moved to a paid licensing model for enterprises.
  • Resource usage: On Windows/macOS, Docker runs a hidden VM; Podman Desktop is lighter.
  • Security: Podman supports rootless containers, running as your own user.
  • OCI-first: Podman works with OCI registries like ACR out of the box.

For my daily dev flow, Podman Desktop became a drop-in replacement.

Installing Podman Desktop

On macOS or Windows:

brew install podman-desktop
# or download from https://podman-desktop.io/

Initialize the Podman VM (“machine”):

podman machine init
podman machine start

Check status:

podman info

Building and Running Containers

All your familiar Docker commands work, but with podman:

podman build -t myapp:dev .
podman run -p 8080:80 myapp:dev

Pushing to Azure Container Registry (ACR):

podman login myazurecontainergistry.azurecr.io
podman tag myapp:dev myazurecontainergistry.azurecr.io/myapp:dev
podman push myazurecontainergistry.azurecr.io/myapp:dev

Podman even includes a Docker socket compatibility layer, so tools expecting docker.sock still work.

Podman Compose

For local dev stacks:

podman-compose up

This reads docker-compose.yml the same way as Docker. Perfect for multi-service Angular/.NET stacks.


Part 2 — Discovering Podman Quadlets

At some point, I wanted containers to auto-start at boot and be managed like system services. That’s where Podman Quadlets come in.

Quadlets let you describe containers in .container files that systemd understands.

Example: myapp.container

[Unit]
Description=My App Container

[Container]
Image=myazurecontainergistry.azurecr.io/myapp:latest
Network=host
Volume=/data:/app/data
AutoUpdate=registry

[Install]
WantedBy=default.target

Deploy it:

sudo cp myapp.container /etc/containers/systemd/
systemctl --user daemon-reload
systemctl --user enable --now myapp.service

Now the container runs at boot, restarts on failure, and updates when you push new tags.

Pros of Quadlets:

  • Great for single-node setups (edge servers, dev machines).
  • Integrates tightly with systemd.
  • Simple config, no extra orchestrator needed.

Cons:

  • No scheduling or scaling beyond one node.
  • Updating multiple apps at once gets messy.
  • Secrets/config management is manual.

Quadlets gave me a taste of container-as-service, but also highlighted the limits.


Part 3 — Why Quadlets Pushed Me to Kubernetes (MicroK8s)

Running one or two containers with Quadlets is fine. But as soon as I had:

  • Multiple APIs (an-application API, Identity, etc.)
  • Redis/RabbitMQ backing services
  • Ingress/TLS requirements
  • Persistent Volumes

…I realized I was re-implementing Kubernetes-lite.

Enter MicroK8s — Canonical’s lightweight Kubernetes.

Installing MicroK8s

sudo snap install microk8s --classic
microk8s status --wait-ready

Enable common addons:

microk8s enable dns storage ingress observability

Deploying with Helm

Instead of writing individual manifests by hand, I packaged my services with Helm charts.

Example deployment (Helm values-driven):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: an-application-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: an-application-api
  template:
    metadata:
      labels:
        app: an-application-api
    spec:
      containers:
      - name: an-application-api
        image: myazurecontainergistry.azurecr.io/an-application-api:1.0.0
        ports:
        - containerPort: 5000
        volumeMounts:
        - mountPath: /config
          name: config
      volumes:
      - name: config
        configMap:
          name: an-application-api-config

Now I had scaling, rolling updates, TLS ingress, and persistent volumes handled by Kubernetes instead of by hand.


Part 4 — Comparing the Approaches

Feature Docker Desktop Podman Desktop Podman Quadlets MicroK8s (Kubernetes)
Rootless security
Resource usage Heavy Light Light Moderate
Multi-service dev stack ✅ (Compose) ✅ (Compose) ⚠️ Manual ✅ (Helm/Manifests)
Auto-start at boot ✅ (Deployments)
Scaling/HA
Secrets/Config mgmt Basic env vars Basic env vars Manual ✅ (ConfigMaps/Secrets)
Multi-node cluster

Final Thoughts

  • Podman Desktop is a great daily driver and replacement for Docker Desktop.
  • Quadlets are perfect for edge devices or simple single-node setups.
  • But as soon as you need scaling, persistence, or multiple microservices, Kubernetes is the natural next step.

For me, the progression was:

  1. Docker Desktop → 2. Podman Desktop → 3. Podman Quadlets → 4. MicroK8s with Helm.

Each step taught me something new about containers, orchestration, and the trade-offs between simplicity and power.


Written April 2025 — a reflection on my container journey and why Kubernetes ultimately won out, but not without Podman teaching me valuable lessons along the way.

Enjoyed this post? Give it a clap!

Comments