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 startCheck status:
podman infoBuilding and Running Containers
All your familiar Docker commands work, but with podman:
podman build -t myapp:dev .
podman run -p 8080:80 myapp:devPushing 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:devPodman even includes a Docker socket compatibility layer, so tools expecting docker.sock still work.
Podman Compose
For local dev stacks:
podman-compose upThis 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.targetDeploy it:
sudo cp myapp.container /etc/containers/systemd/
systemctl --user daemon-reload
systemctl --user enable --now myapp.serviceNow 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-readyEnable common addons:
microk8s enable dns storage ingress observabilityDeploying 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-configNow 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:
- 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