By Andrew Denner
Senior Software Developer and President of the Central Iowa Linux User’s Group
Welcome to an exploration of Podman, a powerful and versatile containerization tool that serves as a compelling alternative to Docker. As Linux users and enthusiasts, we are always on the lookout for tools that enhance our workflows, improve security, and offer flexibility. Podman does just that, and in this blog post, we’ll delve deep into its functionalities, compare it with Docker, and explore how it integrates with tools like Kubernetes, Docker Compose, and systemd.
I’ve been a Linux user since 2003, navigating through various distributions from Gentoo to CentOS and currently favoring Ubuntu for its convenience. As a Senior Software Developer and the President of the Central Iowa Linux User’s Group (CIALUG), I have a passion for exploring new technologies and sharing knowledge with the community.
Before we dive into Podman, let’s briefly revisit the Open Container Initiative (OCI). The OCI is an open governance structure formed under the Linux Foundation for the express purpose of creating open industry standards around container formats and runtimes. Docker was instrumental in starting this initiative, which aims to standardize container technology and promote interoperability among different tools.
Docker revolutionized containerization by bundling together various Linux kernel features such as namespaces, control groups, and network devices, making it easier to create, deploy, and run applications using containers. However, Docker operates as a client-server application, running a daemon (dockerd
) as root by default. This design has raised security concerns because if the Docker daemon is compromised, it could potentially lead to root access on the host system.
Podman (the POD Manager) addresses some of these security concerns by offering a daemonless and rootless containerization approach. Developed by Red Hat, Podman allows users to manage containers without the need for a background service or root privileges. It directly interacts with the runC container runtime, which is part of the OCI specifications.
One of the key differences between Podman and Docker is Podman’s ability to run in rootless mode. This means that containers can be run and managed by non-root users without granting them elevated permissions. In rootless mode, Podman uses user namespaces to map container UIDs and GIDs to unprivileged host UIDs and GIDs. For instance, the root user inside the container (UID 0) might correspond to an unprivileged user on the host system (e.g., UID 100000).
Docker relies on a daemon that runs with root privileges. While Docker supports rootless mode starting from version 20.10, it still traditionally depends on the daemon process. This architecture can pose security risks because any vulnerability in the Docker daemon could potentially be exploited to gain root access on the host system.
Podman is available for various Linux distributions, including Fedora, CentOS, Ubuntu, and Debian. Here’s how to install it on Ubuntu/Debian-based systems:
sudo apt update
sudo apt install podman
For other systems or more detailed instructions, refer to the Podman installation guide.
Let’s start by running a simple hello-world
container:
podman run --rm hello-world
This command pulls the hello-world
image from a container registry and runs it. The --rm
flag tells Podman to remove the container after it exits.
Podman is designed to be a drop-in replacement for Docker. You can create an alias or install a compatibility layer:
sudo apt install podman-docker
Now, you can use Docker commands, and they will be executed by Podman:
docker run --rm hello-world
To illustrate the security features, let’s attempt to mount a host directory into a container:
podman run --rm -it -v /etc:/host-etc ubuntu bash
Inside the container, try creating a file in /host-etc
:
touch /host-etc/testfile
You will receive a permission denied error because the container doesn’t have the necessary privileges, demonstrating Podman’s rootless security model.
When running rootless, binding to ports below 1024 requires additional configuration. However, you can expose higher ports without issues:
podman run -p 8080:80 nginx
This command runs an Nginx server inside a container and maps port 80 inside the container to port 8080 on the host.
To bind to ports below 1024, you can use network capabilities
or run Podman with elevated privileges (not recommended for general use):
sudo podman run -p 80:80 nginx
Podman can run Kubernetes YAML files directly using the play kube
command. This allows you to test and develop Kubernetes applications locally without setting up a full Kubernetes cluster.
Create a wordpress.yaml
file with the following content:
apiVersion: v1
kind: Pod
metadata:
name: wordpress-pod
spec:
containers:
- name: wordpress
image: wordpress
ports:
- containerPort: 80
hostPort: 8080
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: examplepassword
- name: MYSQL_DATABASE
value: wordpress
Run the pod using Podman:
podman play kube wordpress.yaml
This command will create and start the containers defined in the YAML file.
List running pods:
podman pod ps
Stop a pod:
podman pod stop wordpress-pod
Remove a pod:
podman pod rm wordpress-pod
Podman supports Docker Compose files via the podman-compose
tool. This allows you to run setups defined in docker-compose.yaml
files without modification.
Podman-Compose can be installed using pip
:
pip install podman-compose
Alternatively, it may be available in your distribution’s repositories.
Given a docker-compose.yaml
file, you can start your services with:
podman-compose up
Suppose you have a docker-compose.yaml
file for a web application with multiple services (e.g., frontend, backend, database). Podman-Compose will parse this file and create the necessary pods and containers.
While Podman-Compose aims to be compatible with Docker Compose, there may be some differences and limitations. Be sure to test your setup thoroughly.
Podman can generate systemd unit files that enable you to manage containers as system services. This is particularly useful for services that need to start automatically on boot or require supervision.
Start by creating and running a container:
podman run -d --name mywebapp -p 8080:80 nginx
Generate the systemd unit file:
podman generate systemd --name mywebapp --files --new
This command creates a container-mywebapp.service
file.
Copy the service file to the systemd directory:
sudo cp container-mywebapp.service /etc/systemd/system/
Reload systemd to recognize the new service:
sudo systemctl daemon-reload
Enable and start the service:
sudo systemctl enable container-mywebapp
sudo systemctl start container-mywebapp
Now, your container will start automatically on boot and can be managed using systemctl commands.
Security-Enhanced Linux (SELinux) is a security architecture integrated into the Linux kernel that provides mandatory access control (MAC). It was developed by the NSA and released to the open-source community. SELinux helps to enforce security policies that limit what resources users and processes can access.
When running containers on an SELinux-enabled system, you may encounter permission issues due to the strict access controls. Podman can handle SELinux contexts using the --security-opt
flag and volume options.
When mounting volumes, use the :z
or :Z
options to modify the SELinux labels:
:z
– shared content among multiple containers.:Z
– private content for the container.Example:
podman run -v /mydata:/data:Z myimage
You can inspect a container’s security context using:
podman inspect --format '\{\{\.ProcessLabel\}\}' mycontainer
Podman is excellent for setting up development environments without installing all dependencies on your host system. For example, you can run a container with Node.js and mount your project directory:
podman run --rm -it -v "$(pwd)":/app -w /app node:14 bash
Podman can build images from a Dockerfile
using the build
command:
podman build -t myimage .
This uses the same syntax and process as Docker, ensuring compatibility.
If you encounter issues where a container cannot access mounted volumes, it’s likely due to SELinux contexts. Ensure you use the correct volume mount options (:Z
or :z
).
Running rootless containers may have networking limitations, such as binding to privileged ports or interacting with certain network interfaces. You may need additional configuration or to run the container as root in these cases.
While Podman is designed for Linux, there are ways to run it on macOS and Windows, typically via virtualization or compatibility layers. The experience may not be as seamless as Docker Desktop, but solutions like Podman Machine can help.
Podman offers a robust, secure, and flexible alternative to Docker, particularly appealing for users and organizations concerned with security and looking for a daemonless containerization solution. Its compatibility with Docker commands and integration with tools like Kubernetes, Docker Compose, and systemd make it a powerful tool in the container ecosystem.
While there may be some rough edges and a learning curve, especially when dealing with SELinux and rootless configurations, the benefits in security and flexibility are well worth the effort.
The Central Iowa Linux User’s Group (CIALUG) meets on the third Wednesday of each month at 7 PM. We welcome Linux enthusiasts of all levels to join us for discussions, presentations, and networking. Visit cialug.org for more information and meeting details.
Connect with me on social media and visit my blog at denner.co for more insights into Linux, containerization, and open-source technologies.
By embracing tools like Podman, we continue to advance the open-source ecosystem, promoting security, flexibility, and innovation. Happy containerizing!
This post is created from a presentation I originally gave to the St Louis Linux Users Group My slide deck and Video