Docker is clearly the de facto choice for containerization. But Podman vs Docker debate has been gaining traction in recent months.
If you are a regular reader of our content, then you probably have seen our Docker media server guide, Docker Traefik guide, and other relevant content.
But there's a (not so) new kid on the block who also does containerization, only better!
About a year ago I transitioned my server from using Docker to Podman and haven't looked back. There were some bumps along the way but now I couldn't be happier with the choice. [Read: Ultimate Docker to Podman Migration Guide: It’s NOT difficult]
Let's compare Docker vs Podman, see the differences between them. Is Podman a good alternative to Docker? Let's find out.
Table of Contents
Switching from Docker to Podman
When I started my self-hosting journey I had never even heard of containers; let alone Docker, Podman, or otherwise. I began, like many, using simple Snaps to get started but eventually got frustrated with their limitations. Naturally, I moved on to running applications on bare metal and then virtual machines. From this foundation, I learned about containers and their advantages. [Read: What is Docker: Docker vs VirtualBox, Home Server with Docker]
When I began, I was so excited to see how easily and effortlessly one could start a container and instantly try out a new piece of software. This was great until the first time my VPS got hacked.
F&*%!
I can't say exactly where the attack came from or what vulnerability was exploited, but I knew at that point that security needed to be a top priority.
From there, I began rebuilding my server and took a dive into both how Docker worked and how it integrated into the operating system itself. Along the way, I realized that running Docker containers was not anything like running applications directly on a server.
Quick Take on Containers
It's 2022 and containers have been all the rage for the past few years. This is especially true if you are into the self-hosting space.
In fact, you will find that nearly every application recommended is generally containerized and those who recommend another approach are often shunned. The reason for this is partly the same reason containers were created in the first place: to prevent developers from reaching for the "but it runs on MY machine!" trope.
In this sense, containers were never intended to be production-ready systems. However, allowing developers to create easily replicated run-time environments has had wonderful trickle-down effects for self-hosting. The primary benefit is that the maintainer of the container image installs the correct dependencies and some default settings. While there are many more benefits, I intend to keep this article light and mostly high-level.
What is Podman?
In short, Podman is a program for running and managing containers in much the same way as Docker. Podman acts as a front-end for a container runtime back-end which does the heavy lifting in the background. You can think of this as interacting with a website (front-end), while the web server does the actual work on the back-end.
Have a look at this quick introduction from Red Hat Developer:
Podman has Security at its Foundation
The concept for Podman actually started from the ideas that Linux containers (LXC) and Docker originally brought to the table. However, the developers of Podman quickly realized that if we are to run containers in a production environment, the security of the containers and their underlying operating system is paramount.
Red Hat, the main company behind Podman, is known as one of the most security-minded Linux companies. This is great for developers, production environments, and especially individuals like us self-hosters. Many people don't realize just how extensive a topic Linux security truly is.
Podman Follows the OCI Standard
The good news is that in 2015, Docker created the Open Container Initiative (OCI) which set out to implement a standardized way of defining, creating, running, and managing containers. This standard for containerizing applications has lead to an open source, collective set of tools for containers. For the average user, this doesn't mean much. However, it's this OCI structure that has helped develop new tools like Kubernetes and Podman.
Podman follows the OCI standard and has been designed since its inception to be a close replacement to Docker. However, the underlying technology differs greatly from Docker. Fortunately, you don't need to be an expert in any of the underlying aspects of Podman to start enjoying the myriad of benefits included.
Future of Podman
One last piece I wanted to touch on is the future of Podman. Nobody wants to invest time in learning a new tool, transitioning to it, only to have it deprecated and be left behind. Fear not friend. Podman is supported by a large company, and moreover, works with concepts that can lead you to a more powerful tool like Kubernetes if that is of interest to you. While full-blown Kubernetes is far beyond the needs of most self-hosters, there are great in-betweens like minikube and k3's.
In fact, Kubernetes has dropped support for the Docker runtime earlier this year to focus on better support of other container runtimes. Is that an indication that Docker is dying and people are starting to move away from it? Not quite. I see it as a maturing of the ecosystem: Docker is being left to do what it's good at - development.
Podman vs Kubernetes
Kubernetes is a container orchestration software while Podman is a container runtime management software. The biggest difference here is that Kubernetes is designed to run a cluster of servers, and automatically adjust the numbers of containers, load balance, etc. Podman on the other hand is designed to run containers individually.
However, Podman can be used as a stepping stone for Kubernetes as it can also create Kubernetes-compliant YAML files which could be transferred to a Kubernetes cluster.
Podman vs Docker Swarm
It's true there are tools like Docker swarm available, but in my experience, it isn't all that well supported and is stretching the limits of what Docker is good at. With that, let's look at a high-level view of some differences between Docker and Podman and why I ultimately decided to switch.
Be the 1 in 200,000. Help us sustain what we do.You will gain benefits such as Deployarr access, discord roles, exclusive content, ad-free browsing, and more.🔥 Holiday Sale! 25% Off Platinum Membership$399.99$299.99 (ends December 31).Join the Geek Army (starting from just $1.67/month)
Podman vs Docker Comparison
The following list isn't comprehensive and, like all software development, these days is likely to change on a regular basis. I'm not an expert or a professional working in the field; just an enthusiast who likes to tinker in a relatively secure environment!
1. Rootless by design
One of the biggest security issues with Docker is that, by default, it is run as a root
user.
The main concern when running any program as the root
user lies in potential vulnerabilities. If a vulnerability is found in the software run by root
, the attacker has instant access to the entire system. While you may think this is rare or unlikely to happen to you, know that software vulnerabilities are found very regularly.
This is not to say that Podman does not have issues as well. The main difference is that when your container system can be run as a non-root user, an attacker exploiting a vulnerability would only have as much access as the non-root user.
Podman easily runs rootless and requires effectively zero configuration to get started. Simply run an image and you will see that the root user inside of the container will just be your non-root user outside of the container. One confusing piece of this is that a Podman container running as a non-root user will run within the user namespace. That probably means nothing to you, so let's give a quick example:
Rootless Example
Let's take MariaDB for example which runs as the MySQL user inside the container. However, once we are outside the container, we can see that the files are owned by an arbitrary user:
The huge benefit here is that if your MariaDB container were somehow compromised, the attacker only has access to the few files mounted within the container. And, if they got access to the mysql
account, they would be user 100988 (in the example above) on the host system - also no access beyond the files previously mentioned.
This extends further: Many poorly crafted containers run their process as the root user within the container. In a rootless environment, the root user inside the container is mapped to the user running Podman outside of the container. This keeps the security of the host system intact, even with a compromised container environment.
These are admittedly contrived examples, but give a basic example of how damage by a malicious container can be limited on the host machine.
Remarks: Podman's Rootless Mode is Better than Docker's
I must mention that Docker does now offer a rootless mode as well. However, reading the documents carefully shows that it has its own limitations. There is a bit more setup involved, but it's not impossible to use. The biggest issue for me is that by running rootless, you are no longer able to use AppArmor. More on this later...
I go back to one of the points I made earlier. I appreciate how Podman starts with secure practices by default, and lets you open them if needed. Running a program as a non-root user is a basic Linux fundamental that our container runtime should follow as well.
2. SELinux
SELinux (and to an extent AppArmor) is a module that adds significant extra security to Linux systems. If you've read some of my previous articles you'll know I'm a fan of it and highly recommend adding it to your system.
The foundation of SELinux is built upon basic Access Control Lists (ACL - think of the usual rwxr-x---
permission system) security, and adds a fine-grained approach to separating the user, process, and files to which each can access. In truth, SELinux goes much deeper than what I've described as it applies to the entire system. While some find it very difficult to understand and use, it is a VERY powerful tool for adding a layer of security to your server.
The good news is Podman ships ready-to-use with SELinux in "Enforcing" mode. It comes with some nice, user-friendly policies that help you to enforce good security practices without having to learn the entire SELinux ecosystem.
There is indeed an SELinux module for Docker, but it is a bit more complicated to setup and not well-documented.
How does SELinux work?
Processes within a container are limited to only having access to the files within the container or those that we mount into the container. This is the normal behavior of all container systems (including Docker and LXC) and one of the added security benefits of containerization in general.
When running Podman containers with SELinux enabled on the host system, there are additional security layers added. For example, the files a container has access to are also given a "label" by SELinux. This ensure that any process outside of the container is also unable to access these files.
While this can be a bit of a pain for things like log files that you might want to ingest with another program, you can adjust your SELinux policy to allow access by specific processes to specific files.
To provide security between containers, SELinux sets different SELinux categories for each container. Now we are getting into a more advanced aspect of SELinux which I will not dive into further.
Additionally, if a process were to break out of a container, SELinux is providing an added layer of security to the rest of your system.
What about AppArmor for Docker?
Docker does indeed provide a default AppArmor profile for its Docker containers which appears to work relatively well. You also have the ability to create fine-grained security policies for containers but you will also have to learn the AppArmor syntax and write your own policies.
As mentioned above, AppArmor does not work with rootless Docker. It also does not keep the separation between containers. More on this from a biased resource.
Remarks: Podman has Better SELinux Support than Docker
The comparison of AppArmor vs SELinux isn't the focus of this article, but at their base, they have different values. I prefer how SELinux gives processes the least possible permissions and allows you to open them as needed. I find AppArmor to be the opposite and generally too liberal with its policies.
3. Daemonless
Sticking with the theme of Podman-Docker security, one of the primary "selling" points of Podman is the fact that it runs "daemonless". To the average user this likely means very little, but from a security standpoint it means a LOT. Without getting overly detailed, I'll give a quick rundown on why this is important.
The Docker Daemon
The Docker daemon is run as a systemd
service. In fact, most services running on your server or desktop are run as daemons. One big difference with the Docker daemon is that it has nearly unrestricted access to the host system. If, for example, a container were improperly configured, it wouldn't be hard for a malicious container to gain access to the entire host system.
The Docker daemon is fairly secure by default, but there are numerous reports of users misconfiguring Docker in a way that leaves them exposed to attacks from the outside network. I find this especially true and highly concerning in the copy-paste world of online tutorials.
The fact that Docker uses a daemon for its core functionality is not a bad thing in and of itself. But it should be noted that the way the Docker daemon is designed to run on the host makes it a HUGE target with many ways to compromise it. If improperly configured, the Docker daemon can be accessed from the machine (by the root
user, sudoers
, or users put into the docker
group), from outside the machine (via an unsecured TCP port), and from containers (via mounting the Docker socket).
Moreover, all containers are run as the same user and under the same parent process. This approach makes it much more difficult to trace actions regarding containers. See below for an example of this point.
Two prominent images that often make use of the exposed Docker socket are Traefik and Portainer. While I believe their images are generally safe and can be trusted, bugs do occur and nobody is immune to mistakes.
In addition, we are seeing more "easy all-in-one" containers that use the Docker socket to run additional containers for you. Easy? Yes. Dangerous? Extremely. [Read: 20 Docker Security Best Practices, including Docker Socket Proxy]
When you look at this approach from a higher level perspective, the Docker daemon breaks some of the basic security that is fundamental to Linux.
Daemonless Podman
By not running all of Podman as a system-wide systemd
service, Podman can be run by multiple users, on the same system, securely. On top of that, when a container is run, each process is forked and run separately. From a security perspective, this allows better isolation and easy auditing of individual processes and containers.
This also means we no longer have a single point of failure and don't need to expose the daemon socket to containers.
Quick Demonstration
First, let me say that I am not a security expert or a pentester, etc. However, I have had servers hacked and did my best to limit the damage and learn to trace the issues. The following is a basic demonstration showing some of the above concerns about how Docker runs. Note that I am using standard containers and not ones with potential security issues.
In this scenario, I will run both Docker (v20.10.17) and Podman (v3.4.4) on a fresh Ubuntu 22.04 server. Docker was installed from the Docker Repository and Podman from the Ubuntu Universe repo. Note that Podman is actually a major version behind here!
I am simply running four nginx:alpine
containers, two via Docker and two via Podman. I am running one each as a separate user to demonstrate the visibility of running processes on the host machine.
First, as my user (kit
), we can see that I have an nginx
container running with Docker, listening on port 8080:
Next, we will see if a second user (badguy
) can see what the first user (kit
) has started.
Uh oh, looks like he has full visibility and access. Anyways, let's run a second instance as badguy
on port 8091.
Next, I will repeat the same steps as above with Podman. First my user kit
running an nginx
container on port 7070:
Now, as badguy
, I cannot see what containers another user is running. Let's start the final nginx
container listening on port 7071:
All is well, but imagine there was an issue with one of the containers. Trying to trace which container the issue stemmed from, which user started it, or if it came from an out-of-network source would be MUCH more challenging with Docker than with Podman.
Let's demonstrate with the lsof
command:
lsof
command is sort of like ls
, but instead of listing files and directories, it lists processes and devices. I used the -i
switch with lsof
to simply determine which processes were running "internet" services. I also used -c ^ssh
to exclude anything regarding the ssh
command to simplify the output on screen.So we can see all 4 nginx
containers listening on their respective ports (last four lines). However, if you look closely, all Docker processes are owned by root
.
When we look at the containers started under Podman, we can see which user actually created the processes, which command was used, and can trace the source easier.
Finally, we can see that the processes are running in the user namespaces (as seen by the high number in the far left column) under Podman, instead of the systemd+
user under Docker. This goes back to our point about rootless containers earlier.
Remarks: Daemonless Podman is More Secure than Daemonized Docker
When learning Linux, we are taught to never run things as the root
user; create a user and add them to the sudoers
group. By giving unfettered access to our system via the Docker daemon, we run a huge security risk and must rely on individual maintainers, Docker, and others to provide good security policies.
Daemonless is a big layer of security that further separates containers from the host operating system.
4. Firewall Compatibility
An important aspect of any server is a good firewall. This allows us a good level of security to stop the majority of attacks from the wider internet. A firewall should be clear, easy to manage, and of course effective at only allowing what we want, and blocking the rest.
Podman and Docker both have different approaches to how they integrate into firewalls. For this example, I will be using the same Ubuntu 22.04 server as above for both Docker and Podman.
Docker and Firewalls
By default, Docker modifies your firewall for you to ensure you have access to the containers you are running. While this can be a great feature while you are developing an application, it can be a nightmare for newer users who aren't used to iptables
. In a production environment, this will lead to some very unexpected surprises. Let me explain.
When you use a standard docker run command:
sudo docker run -d -p 8000:80 nginx:alpine
Rules are added to your iptables
to open port 8000 in your firewall. This can be misleading as it inserts the rules BEFORE your normal firewall rules like those created with ufw
.
Even with UFW active (only port 22 for SSH allowed as shown below), the web server is still reachable!
If you want a container only accessible on the host, an alternative is to never run containers with such an open port declaration. So instead you could use:
sudo docker run -d -p 127.0.0.1:8000:80 nginx:alpine
This will work however it also limits our ability to do more advanced networking like forwards, fine-grained access, etc. More critically, if you are using a tool like fail2ban or CrowdSec, the blocked addresses are added after the Docker rules, thereby rendering fail2ban
useless!
Podman and Firewalls
Podman's approach is to create internal networks so that you can talk to your containers, but not modify outward-facing rules. To me, this should be the default behavior for all container runtimes:
podman run -d -p 8000:80 nginx:alpine
The firewall is correctly blocking the webserver address.
Simple as that. Now I can use my firewall as expected and block, allow, forward, whatever as I would expect without Podman interfering.
Remarks: Unlike Docker, Podman Respects Firewalls by Default
I believe each piece of software should handle what we ask it to do. The firewall should handle all connections, and my container runtime should handle the containers. I don't want either of them doing the job of the other.
5. Pods
In their simplest form, pods are just collections of containers. However, the beauty of pods lies primarily in their networking.
With Docker, when you want containers to "talk" to one another, they must reside in the same Docker network. Then, you can reach other containers by their container names. This works well, but what if we could simplify it even more?
When placing multiple containers into the same pod, they talk to each other natively as if there were run on the same machine. In the above drawing, containers could communicate by using localhost:3306
for example. For me this greatly simplifies the container stacks that include a database, redis
instance, application, etc.
When I want to publish a port outside, I simply publish a pod's port, and that is all that's accessible from the outside.
Like the other topics I've touched on above, this is only a small example of what's possible with pods, but to me, it is their strongest point. You can also set resource limits, labels, shared volumes, etc. See the Podman pod docs for more.
Be the 1 in 200,000. Help us sustain what we do.You will gain benefits such as Deployarr access, discord roles, exclusive content, ad-free browsing, and more.🔥 Holiday Sale! 25% Off Platinum Membership$399.99$299.99 (ends December 31).Join the Geek Army (starting from just $1.67/month)
Remarks: Podman Pods Simplifies Grouping and Inter-Container Networking
While Docker has networks, Podman has both networks and pods. I appreciate how I can reserve "networks" for connecting pods or more complex connections, and keep pods for simple inter-container networking.
6. Docker Monolith vs. Podman Tools
Up to this point, I've done my best to keep the topics relatively light and easy to digest - features that would directly affect you, the user. However, I want to introduce one intermediate/advanced level topic at the end which, I believe, is crucial to the underlying architecture of the Docker vs Podman comparison.
One very fundamental difference between Docker and Podman is that Docker is built as a monolithic software, while Podman is a set of open and interchangeable tools. That's probably a big statement to digest, so let's dig a bit deeper and follow it up with a concrete example.
The Docker Ecosystem
Docker's software model is to do a bit of everything. In fact, many self-hosters now refer to Docker as though it were practically a stand-alone operating system itself. The base operating system upon which Docker is installed is unimportant. This fact alone shows that Docker has its tentacles in every aspect of what makes up a Linux system.
If well implemented, this can be an effective way to keep consistency throughout an ecosystem. However, Docker is becoming a different beast altogether and starting to put features behind paywalls.
Podman Tools - Buildah, Skopeo, and more
As I mentioned earlier in this article, Podman acts as a front-end for running containers. With this in mind, it should be noted that Podman alone is not a direct substitute for Docker. Up to this point, I've been using the term "Podman" in a general sense.
The reality is that in this case, "Podman" is actually a set of different tools used for different container functions. Specifically, Podman also utilizes a program called Buildah for building OCI compliant containers, and Skopeo for managing container images.
These and a multitude of other tools are all based upon the aforementioned OCI standards. This is beneficial for the greater community as it allows for different tools to take shape, all while being compatible and interchangeable. This is something I truly appreciate about Podman. The structure is more open and, I believe, allows Podman to better integrate into the Linux ecosystem instead of building on top of it.
But here we are back to one of my original discoveries. Docker was started as a way to develop applications. And now, there are better tools for running and orchestrating containers. That's all quite high level, so let's look at something more digestible.
Example of Running/Orchestration with Docker and Podman
One feature of Docker that I always appreciated was its "restart" declaration. I like how it can be fine tuned to restart a crashed container for example. Podman is notably missing this feature, but there is perhaps a better way to enable effectively the same behavior: systemd
.
If you have used just about any Linux distribution lately, you'll have come across systemd
at some point. It is the service that runs (for the most part) all other standard background services, including Docker. Podman allows you to create user-services based upon pods and/or containers.
Once that service is added, it behaves like any other systemd
service and can be tweaked in many different ways. The main downside here is the extra step required to create the same policy that is part of your docker run
command or docker-compose
files.
On the other hand, systemd
is already well-designed to handle container startup order, dependency checking, and even automatic container updates.
Remarks: Compared to Docker, Podman Offers Better Container Running and Orchestration
Podman's use of systemd
, along with easy integration into an auditing system, are features that I believe truly sets Podman apart from Docker. It shows that Podman (smartly) leverages well-established Linux tools and simply incorporates containers into Linux.
Summary of Podman Docker Differences
Feature | Podman | Docker |
---|---|---|
Rootless Mode | +1.0 | +0.5 |
SELinux Support | +1.0 | +0.5 |
Daemonless vs Daemon | +1.0 | 0 |
Firewall Compatibility | +1.0 | 0 |
Pods vs Networking | +1.0 | +0.5 |
Podman Tools vs Docker Monolith | +1.0 | 0 |
Total | 6.0 | 1.5 |
Reasons to pick Docker over Podman
Docker is clearly the most popular, well-known, and well-documented container software on the internet. You can find countless articles which leverage Docker and walk you through its system step-by-step. You're looking at the OG here.
This is also true when compared to Podman. Many of Podman's advances have come in the most recent versions, while distribution repositories still have older versions of both Podman and podman-compose
.
Docker is also fantastic for developing software - the other headaches you might encounter are mostly abstracted away.
It works on both Windows and Mac in the form of their desktop apps. It should be noted however that for both Windows and Mac, Docker does not run natively and instead runs in a Linux VM.
Reasons to pick Podman over Docker
Podman is built upon the foundation that Docker created. It is designed from the ground up to be more secure and robust for managing containers in a production environment.
It is also just as easy/difficult to learn as Docker, and thus, nearly every tutorial you see with regards to Docker can be replicated by replacing the word docker
with podman
.
Podman presents itself as a quick and easy way to get into containers but also opens the door for further investigation into projects like k3s, minikube, and Kubernetes.
FAQs
Will Podman replace Docker?
I think the Podman vs Docker argument will ultimately be an individual decision. Podman is primarily being pushed by Red Hat, while Docker is its own entity. For the time being, Docker will exist heavily in the development sector as it is heavily used in development pipelines, although that is changing. I see Podman as a more specialized alternative to Docker than a replacement.
Is Podman safer than Docker?
This is a subjective question; a Docker setup CAN be as secure as a Podman setup. The main difference is that I believe Podman to have better security policies out of the box. If you are simply running a home server with nothing exposed to the internet, there is little difference between the two. I however, prefer the added Linux integration Podman offers like auditing and better SELinux support.
Is Podman compatible with Docker?
If you are interested in trying out Podman, according to the developers, you can simply set alias docker=podman
in your terminal and run the same docker
commands you are used to, but now they will use Podman instead. All of your docker-compose
files and Dockerfiles
are compatible with Podman, sometimes requiring minor tweaks.
Does Kubernetes use Podman?
Kubernetes does not use Podman, but both use similar tool-sets all within the OCI standards. Kubernetes is a container orchestration software while Podman is a container runtime management software, as explained previously in this Docker-Podman comparison.
Concluding Remarks: Podman or Docker Which is Better?
Both Podman and Docker are excellent and revolutionary in their own way. In its infancy, Podman was, at best, an awkward outsider with more challenges than benefits. When I started using it a year ago, most things mostly worked. But now I must say that even in this short period of time, I've seen the development blossom and stabilize into a fantastic tool that I feel much more comfortable running.
As I was first learning Docker, I felt a bit like I was learning the Linux CLI all over again. There were so many pieces to the ecosystem that I needed to learn and understand to allow fully functional applications.
On the other hand, by default, Podman follows good Linux practices and doesn't require workarounds and entire posts dedicated to security (like using a socket-proxy or needing to modify your firewall rules). In some ways, Podman feels like I am falling back to using VMs to run applications.
But I see this as a completely positive point: Podman balances both the benefits of containers and VMs without compromising on either.
I see a clear choice when comparing Docker vs Podman for containers. Now that I've made the switch to Podman, I won't be going back to Docker anytime soon. If you are ready to switch check out my Docker to Podman migration guide.