Install Podman on Linux: Rootless Containers as a Docker Alternative
What is Podman #
Podman runs OCI containers without a background daemon and, by default, as a normal user. Its CLI mirrors Docker, so docker run becomes podman run and the same images from Docker Hub or Amazon ECR work unchanged.
Install #
On Ubuntu or Debian:
sudo apt update
sudo apt install -y podman
podman --version
On Fedora and RHEL: sudo dnf install -y podman. On macOS and Windows use brew install podman or the Podman Desktop installer, then podman machine init && podman machine start, because containers need a Linux VM there.
Run a container #
podman run --rm hello-world
podman run -d --name web -p 8080:80 docker.io/library/nginx:stable
curl http://localhost:8080
podman ps
podman logs web
podman stop web && podman rm web
Podman asks which registry to use for short names, so write the full name (docker.io/library/nginx) in scripts. Ports below 1024 need sysctl net.ipv4.ip_unprivileged_port_start=80 when running rootless.
Rootless and why it matters #
A rootless container runs as your user, mapped through user namespaces: root inside the container is an unprivileged user on the host. A container escape does not give root access to the machine. Check it:
podman run --rm alpine id
podman unshare cat /proc/self/uid_map
Docker compatibility #
alias docker=podman
Most commands work as they are. For Compose files install podman-compose or the docker-compose binary and point it to the Podman socket:
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker compose up -d
Build images #
cat > Containerfile <<'DOC'
FROM docker.io/library/alpine:3.20
RUN apk add --no-cache curl
CMD ["curl", "--version"]
DOC
podman build -t mycurl .
podman run --rm mycurl
A Containerfile is a Dockerfile with another name; podman build reads both.
Pods and Kubernetes YAML #
A pod groups containers that share a network namespace, like in Kubernetes:
podman pod create --name app -p 8080:80
podman run -d --pod app --name web docker.io/library/nginx:stable
podman generate kube app > app.yaml
podman play kube app.yaml
generate kube produces Kubernetes YAML you can later apply to a cluster, and play kube runs it locally.
Run a container as a systemd service #
Quadlet describes a container in a unit file:
[Container]
Image=docker.io/library/nginx:stable
PublishPort=8080:80
[Install]
WantedBy=default.targetsystemctl --user daemon-reload
systemctl --user start web
loginctl enable-linger $USER # keep it running after you log out
Podman or Docker or Rancher Desktop #
Podman fits servers and CI where you want rootless and no daemon. For a desktop with Kubernetes included, Rancher Desktop is simpler. The image formats are the same, so you can mix them.