Podman has matured into a genuinely solid daemonless, rootless alternative to Docker, and most developers now have a real choice to make. Here’s a practical comparison, plus best practices that apply no matter which one you pick.
Docker vs Podman: The Core Difference
Docker runs a privileged background daemon that owns all your containers. Podman runs containers as regular child processes with no daemon, and supports rootless containers by default — meaningfully reducing the attack surface on a shared or security-sensitive machine.
# Podman: familiar Docker-compatible CLI, no daemon required podman run -d --name web -p 8080:80 nginx:alpine podman ps podman logs web # Most Docker commands work unchanged with Podman alias docker=podman
Rootless Containers
Running containers without root is one of Podman’s biggest security wins. It uses user namespaces to map container root to an unprivileged host user:
# Confirm you're running rootless
podman info --format '{{.Host.Security.Rootless}}'
# Rootless containers still need subuid/subgid ranges configured
grep $(whoami) /etc/subuid /etc/subgid
Writing a Solid Dockerfile (Works for Both Engines)
Regardless of which engine you use, these Dockerfile practices keep images small and builds fast:
# Use a minimal, pinned base image FROM python:3.12-slim AS base # Install dependencies in a separate layer so code changes don't bust the cache WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy application code last COPY . . # Run as a non-root user inside the container RUN useradd -m appuser USER appuser EXPOSE 8000 CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]
Multi-Stage Builds for Smaller Images
FROM golang:1.23 AS builder WORKDIR /src COPY . . RUN CGO_ENABLED=0 go build -o /app ./cmd/server FROM gcr.io/distroless/static-debian12 COPY --from=builder /app /app USER nonroot:nonroot ENTRYPOINT ["/app"]
Compose Files Work on Both
Podman supports Compose files via podman-compose or the built-in podman compose command, so existing docker-compose.yml files generally work unmodified:
services:
web:
build: .
ports:
- "8000:8000"
environment:
- LOG_LEVEL=info
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=devpassword
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Which Should You Pick?
Podman is the better default on Linux workstations and security-sensitive servers, especially anywhere rootless matters. Docker still has the edge on Windows/macOS developer experience via Docker Desktop, and broader third-party tooling assumes the Docker daemon exists. Many teams simply run Podman in CI/production and Docker Desktop on developer laptops — the Dockerfiles are portable either way.