Podman can run containers directly, bypassing the need for a Docker daemon.
Let’s see Podman in action. Suppose we want to run a simple Nginx web server.
podman run -d --name my-nginx -p 8080:80 nginx
This command does a few things:
-d: Runs the container in detached mode, so it’s a background process.--name my-nginx: Assigns a human-readable name to the container.-p 8080:80: Maps port 8080 on your host machine to port 80 inside the container.nginx: Specifies the image to use. If you don’t have it locally, Podman will pull it from Docker Hub (or another configured registry).
After running this, you can check its status:
podman ps
And then access your Nginx server by navigating to http://localhost:8080 in your web browser.
To stop and remove the container:
podman stop my-nginx
podman rm my-nginx
This podman run command is essentially building a container image on the fly (if it doesn’t exist) and then launching an instance of that image as a running process. The key difference from Docker is that there’s no central dockerd process managing everything. Instead, podman interacts directly with the Linux kernel’s containerization features (namespaces and cgroups) and uses a storage driver (like overlayfs) to manage the container’s filesystem. Each container effectively runs as a child process of the podman command itself, with its own isolated environment.
Podman’s architecture is designed for security and flexibility. Since there’s no root daemon, containers can be run as non-root users. This is a significant security advantage, as it limits the potential damage if a container is compromised. Podman achieves this by using user namespaces, which map UIDs and GIDs within the container to different, unprivileged UIDs and GIDs on the host.
The core of Podman’s functionality lies in its ability to manage container lifecycles and images. It uses conmon (container monitor) as a low-level helper process to manage the container’s runtime. conmon is responsible for starting, stopping, and monitoring the container process, reporting its status back to podman. For storage, Podman uses a layered filesystem approach, typically overlayfs, where the container’s writable layer is placed on top of the read-only image layers. This allows for efficient image sharing and reduces disk space usage.
When you run podman run, Podman orchestrates the creation of the necessary namespaces (PID, network, mount, UTS, IPC, user), sets up the cgroup limits, mounts the container’s root filesystem, and then executes the specified command within that isolated environment. It leverages runc (or a similar OCI-compliant runtime) under the hood to actually start the container process according to the Open Container Initiative (OCI) specifications.
A common point of confusion is how Podman handles networking. By default, Podman creates a "slirp4netns" network stack for rootless containers, which provides NAT-like networking. For rootful containers, it typically uses CNI (Container Network Interface) plugins, often defaulting to a bridge network named podman0. You can create and manage these networks using commands like podman network create and podman network ls.
The most surprising thing about Podman is how seamlessly it integrates with systemd for managing containerized services. You can generate systemd unit files for your containers directly with podman generate systemd, allowing your containers to be managed like any other system service, including automatic restarts, dependencies, and logging integration with journald. This makes it incredibly powerful for deploying persistent applications without a dedicated orchestration system.
The next step in understanding Podman is exploring how to build your own container images using podman build and a Containerfile.