- Podman manages containers and pods without a central daemon, with almost full compatibility with the commands Docker and native support for rootless containers.
- Pods group several containers that share a network, IP address, and optionally, volumes, facilitating patterns such as sidecars and multi-container applications.
- Podman allows you to create complex networks, volumes, and pods, integrate podman-compose, and generate Kubernetes manifests for easy migration to clusters.
- Tools like Podman Desktop and good security practices, resource cleanup, and CI/CD automation complete an ecosystem suitable for development and production.
If you work with containers and come from the Docker world, you've probably heard about Podman and its features lately. Containers and pods as a modern alternativeIt's not just "another Docker," but a tool designed to be lighter, more secure, and much better integrated with the ecosystem. Linux and Kubernetes, both on servers and development teams.
Throughout this guide, we'll take a step-by-step look at what Podman containers are, how they're organized into pods, what differentiates Podman from Docker, how to manage them from the command line, and also what role tools like [insert tool names here] play. podman-compose and Podman Desktop in the lifecycle of real-world applications. The idea is that by the end you'll have a clear and practical understanding of how to use Podman in your daily life.
What is Podman and how is it different from Docker?
Podman is an open-source tool for creating and managing containers and pods. on Linux systems, maintained primarily by Red Hat and distributed under the Apache license, which means that all its components can be used without problems in commercial environments. Although it originated on Linux, it can also be used on macOS and Windows (via WSL2 or Podman Desktop).
At a functional level, Podman fulfills the same objective as Docker: run OCI containers easilyIt uses a command-line interface almost identical to Docker's, to the point that it's common to define the alias alias docker=podman to reuse scripts without modifying them. However, internally the architecture is different, and this is where the important advantages come in.
The first key difference is that Podman is “daemonless”That is, it doesn't depend on a central daemon controlling all the containers. Each command you run creates its own processes, and there's no persistent service like dockerdThis typically translates into lower resource consumption, a simpler security model, and more seamless integration with system tools such as systemd.
Another very relevant aspect is that Podman natively supports rootless containersallowing users without administrator privileges to run containers without needing to grant access to a socket rootThis reduces the attack surface and makes it especially attractive in multi-user servers or enterprise environments with strong permission control.
Finally, Podman incorporates the pod concept from the start, directly inspired by Kubernetes. This means you can group several containers that share a network and storage without needing to resort to an external orchestrator or tools such as docker-composealthough there is also podman-compose for those who prefer that declarative approach.
What is a pod and how does it work in Podman?
The term The word "pod" comes from the Kubernetes world and refers to a "pod" of containers. that share certain resources. In Kubernetes and also in Podman, a pod can be understood as a logical unit that groups one or more containers that work together very closely.
Inside a pod, All containers share a single IP address. and a set of network namespaces and, optionally, storage volumes. This means they can communicate with each other using localhost o 127.0.0.1as if they were different processes within the same machine, although from the outside the pod is seen as a single entity accessible by a specific IP and ports.
In practice, this is very useful for implementing patterns such as sidecar containers or applications where several services are tightly coupled. For example, an nginx web server in one container and a PHP-FPM in another They can live in the same pod, sharing IP and communicating via localhostbut keeping their processes and life cycles separate.
When you create a pod with Podman, it introduces a special container called infra containerThis container, based by default on the image localhost/podman-pause (or similar such as) k8s.gcr.io/pause), it does little more than “sleep”, but its function is vital: it is responsible for maintaining the pod's namespaces and serving as an anchor for the rest of the containers that connect to that pod.
Each container, whether inside a pod or not, has a monitoring process called commonThis small C program is responsible for monitoring the container, managing its input/output, and enabling tools like Podman. connect, attach, or collect the status from the container at any time.
Managing pods with the podman pod command
In Podman, everything related to pods is handled using the subcommand podman podFrom here you can create pods, list their status, add containers, control their lifecycle, or delete them when you no longer need them.
podman pod create --name pod1
podman pod ps
ID, name, status These are the basic columns you will see when listing pods; they are accompanied by the identifier of the associated infra container.
To add a new container to an existing pod, simply add a new container To connect a pod, you specify the pod you want to connect it to when you create it. A typical example would be something like:
podman run -dt --pod pod1 --name web nginx
With this command, We created a container based on the nginx image and associated it with the pod pod1When this main container starts, the pod goes into the "Running" state, since there are active processes inside it.
podman ps -a --pod
At the output we will see columns like CONTAINER ID, IMAGE, STATUS and a POD column that indicates the pod ID or name. The pod IDs shown here match those seen in podman pod pswhich makes it easier to cross-reference information between both views.
Pod lifecycle, logs, and detailed information
One of the great things about pods is that We can manage all your containers at once.Although you still have the option to stop, start, or restart containers individually, operating on the entire pod greatly simplifies the management of composite applications.
podman pod pause NOMBRE_O_ID_DEL_POD
podman pod unpause NOMBRE_O_ID_DEL_POD
podman pod stop NOMBRE_O_ID_DEL_POD
podman pod start NOMBRE_O_ID_DEL_POD
And if we need to restart them directly, there is also podman pod restart to restart the set pod container in a single step.
podman pod inspect NOMBRE_O_ID_DEL_POD
As for logsWhen there is only one main container in the pod, it's simple: we can get the output with a simple podman logs about that containerHowever, if the pod contains multiple containers, we must specify which one we want the logs from using the parameter -c:
podman pod logs -c NOMBRE_DEL_CONTENEDOR NOMBRE_O_ID_DEL_POD
To see the processes running within all the containers of a pod, we also have commands that group that information, allowing us to do a kind of “distributed ps across all containers of the same podThis is very practical when debugging errors in multi-container applications.
Removing pods and their relationship to containers
When deleting pods, it's key to remember that Deleting a pod deletes all the containers it contains.Therefore, Podman requires that the pod be stopped before it can be safely deleted, preventing the accidental deletion of running containers.
podman pod rm NOMBRE_O_ID_DEL_POD
podman pod rm -f NOMBRE_O_ID_DEL_POD
When we accumulate many pods, it can be helpful to clean them up all at once. There are commands designed to remove them. all pods stopped or even all pods in the system, both detainees and active, usually combining options such as -a or using specific “prune” subcommands depending on the Podman version.
Network and ports in the containers of a pod
In the network plane, a pod behaves as a unit: All containers in the pod share the same IP addressThat IP address is the one assigned to the pod as a whole and connects to the network we specify when creating it.
In rootful environments, if we don't specify anything, the pod connects to the default red bridge from Podman. In contrast, in rootless environments the standard option is the network slirp4netns, which allows services to be exposed to the host without requiring elevated privileges.
When we want to showcase a service to the outside world, we must carry out the port mapping during pod creationThis is done using the options -p o --publish, indicating the host port and the internal pod port:
podman pod create --name webpod -p 8080:80
podman run -dt --pod webpod --name nginx docker.io/library/nginx
With this, any request to the host's IP address on port 8080 will reach port 80 of the pod, and from there to the nginx container. It's important to note that There can only be one service listening on each port we mapTherefore, we will not be able to have two containers in the same pod offering services on the same outward-mapped internal port.
Communication between containers within the same pod is done simply using localhost o 127.0.0.1This means that if a container within the pod offers an HTTP service on port 80, another container can access it with a URL like this: http://127.0.0.1:80 without worrying about IPs or hostnames.
Storage and shared volumes in pods
Although each container can have its own storage, it is very common that Containers within the same pod share part of the file systemespecially when one container generates data that another must serve or process.
When we create the pod, we can define mount points that will be visible from all containers within it. These mounts can be volumes managed by Podman or direct mounts of host directories (bind mounts), depending on whether we prefer to delegate the physical path to Podman or control it ourselves.
A very instructive example is that of a pod called pod5 which exposes a web server on port 8082 of the host. In that pod we have two containers:
- A main container
webbased on nginx, which builds a shared volume in/usr/share/nginx/html, its DocumentRoot. This container is responsible for serving the web. - An auxiliary container
sidecarwhose mission is to periodically modify the fileindex.htmlwithin the same volume, for example every second, generating dynamic content or messages that change.
To do this, we create the pod specifying both the port and the volume, and then add both containers, mounting the same volume on the appropriate paths. podman volume we can manage these volumes, and with podman volume inspect see where the route is physically located on the host (for example, something like ~/.local/share/containers/storage/volumes/NOMBRE/_data in rootless environments).
If we prefer to use bind mounts instead of volumes, when creating the container we can directly mount a directory on the host, adding the option :z when we work with SELinux so that security contexts are automatically adjusted and there are no access problems from the container.
Containers with Podman: basic everyday commands
If you've never worked with Podman (or Docker), the first thing to understand is that Containers are a form of lightweight virtualizationThey do not recreate hardware not a new kernel, but they apply namespaces, cgroups and other kernel techniques to isolate processes, sharing the same kernel as the host system.
In front of the Virtual machines Unlike traditional containers, containers typically consume fewer resources, start up much faster, and allow for higher densities, resulting in more efficient deployments. Tools like LXC/LXD focus on "complete" system containers, while Podman (and Docker) focus on minimalist containers for running specific services , the databasesweb servers or email applications.
podman run -dt -p 8080:80/tcp docker.io/library/httpd
In this case, Podman attempts to download the image. docker.io/library/httpd if it does not exist locally (saving it in paths like ~/.local/share/containers/storage (for rootless users), creates the container and starts it in the background (-dt (indicates detach mode and pseudo-TTY). The port 8080 from the host it redirects to 80/tcp from the container, so we can open the browser in 127.0.0.1:8080 and we'll see the default Apache page.
podman ps
And if we also want to see those who are detained, we add the option -aIn the output we will see columns such as CONTAINER ID, IMAGE, COMMAND, STATUS, PORTS and NAME, where the name is usually a human-readable alias (for example xenodochial_newton or one that we have put in).
podman stop NOMBRE_O_ID
podman start NOMBRE_O_ID
And get rid of them when they are no longer needed with:
podman rm NOMBRE_O_ID
To manage local images, we have commands such as:
podman image list
which shows us repository, tag, ID, size and creation date, and with others like podman image prune to clean up images that are no longer in use.
Data volumes and persistence in Podman
The images are designed to be immutable and contain just enough for the service Boot, But work data (websites, databases, user files) They need to be stored somewhere that will survive the disposal of containers.
This is where volumes come in, allowing a host directory to be mounted inside the container. Imagine we want to store the content of a website served by Apache; the image expects to find it in /usr/local/apache2/htdocsWe can create a volume called www with:
podman volume create www
and then throw the container like this:
podman run -dt --name apache -p 8080:80 -v www:/usr/local/apache2/htdocs docker.io/library/httpd
With this, all files located on that volume will be served externally by Apache. Using:
podman volume inspect www
We can see that the volume is saved in a path like /home/USUARIO/.local/share/containers/storage/volumes/www/_dataSimply copy our website there to make it accessible from the container.
Container sets with podman-compose
When an application needs multiple services (for example, a WordPress site with its MariaDB database), defining and starting each container manually with podman run and its multiple parameters It can be quite cumbersome and prone to errors.
That's what it's for podman-composea tool that replicates the behavior of docker-compose using files docker-compose.yamlThere we declare services, networks and volumes, and then we let Podman take care of setting it all up together.
A typical example is a file where we define two services:
- Service
webwith imagedocker.io/library/wordpress, which exposes the host's port 8080 to internal port 80, mounts a volume for the web files, and obtains environment variables to connect to the database. - Service
dbwith imagedocker.io/library/mariadb:10.5, which exposes port 6603, mounts a volume for the database data and defines credentials and initial database.
Both services connect to the same network called wpnet and share declared volumes in the section volumesWhen running:
podman-compose up
The containers, the network, the volumes are created, and also, a pod that groups those containersA command podman ps later will show something similar to an infra container (for example 663f84f58792-infra) next to the containers wordpress_db_1 y wordpress_web_1.
If we list the pods with:
podman pod ls
We'll see an entry for that pod (for example, called wordpress) with its POD ID, status, and number of containers. From there we can to suddenly stop or start the entire assembly with podman pod stop y podman pod start, without worrying about whether they start in the correct order.
We will see the volumes associated with this stack with podman volume ls (for example wordpress_wordpress y wordpress_wpdbvol), and the images involved will appear in podman image ls (WordPress, MariaDB and the infra/pause image used for the pod).
Installing Podman on Linux, macOS, and Windows
Installing Podman nowadays is quite straightforward because Modern distributions already include it in their repositoriesIn Debian or Ubuntu-based systems, the typical sequence would be:
sudo apt update
sudo apt install -y podman
Other distributions like Fedora, CentOS Stream, or openSUSE use their own package managers (DNF, Zypper, etc.), but the idea is the same: install the package podman directly from the official repositories.
On macOS, being a system of UnixIntegration is also convenient. The most common way is to use Homebrew, running:
brew install podman
In parallel, there is Podman Desktop for those who prefer a graphical interfaceThis application installs and configures Podman under the hood and provides a GUI for managing containers, images, and pods without relying so heavily on other tools. terminal.
In Windows, the path almost always goes through WSL2 and a Linux distribution within that environment (like Ubuntu). Once you have WSL2 and the distro installed, you enter that Linux shell and follow the same installation steps as in a classic distro. Podman Desktop can also be used on Windows, but it will still require the underlying WSL2 subsystem for everything to function correctly.
To verify that the installation was successful, simply run:
podman --version
and confirm that it returns a version number and not a command not found error.
Network and pod management from the CLI
In addition to container-centric subcommands, Podman has a network API very similar to Docker's. podman network ls We can see the available networks (default bridge, slirp4netns in rootless mode, custom networks, etc.).
podman network create mi_red
podman run -d --network mi_red nginx
This allows different groups of containers to have independent networks, with different isolation policies and rules, which is useful in advanced development environments or in deployments with multiple applications on the same machine.
The relationship between networks and pods is very flexible: when creating a pod we can specify which network it connects to, how its ports are advertised, and what access policies applywhich fits very well with the way in which migration to Kubernetes scenarios is later carried out.
Integration with Kubernetes and YAML generation
One of Podman's strengths is that The world of local development brings the world of Kubernetes much closer to that of local development.Although you don't need a cluster to work with pods on your machine, if you ever decide to make the switch, you can reuse much of what you already have.
podman generate kube MI_POD > mi_pod.yaml
That file mi_pod.yaml It can serve directly as a basis for deploying the same application on a real Kubernetes cluster, adjusting as needed. We can also go in the opposite direction and Create Podman resources from a K8s manifesto through:
podman kube play mi_pod.yaml
This bridge makes it very natural to start with Podman in development or staging environments, and later move the same workloads to Kubernetes without redoing the entire configuration from scratch.
Podman Desktop: graphical interface, debugging and ecosystem
For those who prefer to avoid so many commands or want a visual experience with their containers, Podman Desktop is a cross-platform, open-source GUI which integrates with Podman and, in many cases, also with Kubernetes.
From this interface you can create, start, stop, restart and inspect containers With a couple of clicks, you can view your logs in real time, check CPU, memory and disk usage, and open an interactive terminal inside a container to debug problems or run specific commands.
One of its most convenient features is the image building wizard. Instead of struggling with options in the CLI, Podman Desktop lets you step by step guide in the selection of base images, dependencies, and configurations, even allowing multi-stage builds to reduce the final image size and improve performance.
The tool also offers an integrated view for Kubernetes resources such as pods, deployments, and services. This makes it possible monitor a cluster, check the status of applications, and adjust resource limits without leaving the same application, which is ideal in cloud native development environments.
In addition, Podman Desktop has an ecosystem of plugins and compatibility with many extensions originally designed for Docker Desktop, making it easier to transition from one platform to the other for teams that were already very used to working graphically.
Best practices, security, and automation with Podman
To get the most out of Podman, it's advisable to follow a series of best practices, especially in environments where security and performance matter. One of the most highly recommended is Use rootless containers whenever possibleby running Podman as a normal user and avoiding granting more privileges than strictly necessary.
Another very useful habit is take advantage of Docker CLI compatibilityIf you already have a lot of scripts and pipelines that call dockerYou can define an alias:
alias docker=podman
and continue using the exact same commands as before, but delegating to Podman underneath. This greatly simplifies gradual migrations in development or CI/CD teams where changing all the scripts at once would be a nightmare.
Regarding space management, it's advisable to periodically clean up unused resources. Commands such as:
podman image prune
podman container prune
They remove images and containers that are no longer in use, helping to prevent the host storage from becoming filled with debris of old tests and deployments.
Finally, in business environments it is interesting to integrate Podman with CI/CD tools, configuration management, and security solutionsBeing open source and supporting OCI standards, it fits very well into pipelines with GitHub Actions, GitLab CI, Jenkins and similar tools, allowing you to build, sign and deploy images without depending on Docker.
With all of the above in mind, Podman becomes a very solid option both for those already using Docker and for those just starting out in the world of containers, offering a combination of security, compatibility, Kubernetes integration, and ease of use which makes it especially attractive for modern projects, development environments, and production deployments.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.