Red Hat Enterprise Linux Container Ecosystem Transition

The architectural shift within Red Hat Enterprise Linux (RHEL) regarding containerization represents a fundamental change in how system resources are managed and how applications are deployed. In RHEL 9, Red Hat has completely removed the Docker container engine and the associated docker command from the official distribution. This is not merely a branding change but a strategic move toward a daemonless, rootless architecture centered around Podman. For administrators and developers accustomed to a Docker-based workflow, this transition involves moving from a monolithic daemon model to a modular toolset. While the command-line interface remains largely compatible, the underlying execution environment changes how permissions, networking, and service persistence are handled. The integration of the Open Container Initiative (OCI) image format ensures that the transition does not require rebuilding every application, as Podman supports the same image standards as Docker.

The Architectural Divergence of Docker and Podman

The primary distinction between Docker and Podman lies in the management of the container lifecycle. Docker relies on a client-server architecture where a persistent background process, the Docker Daemon (dockerd), manages all container activities. In this model, the Docker CLI acts as a remote control for the daemon, which typically runs with root privileges. If the daemon crashes, all managed containers may be affected, and the daemon itself represents a single point of failure and a potential security vulnerability due to its root-level access.

Podman utilizes a daemonless architecture. When a user executes a command via the Podman CLI, the process interacts directly with the container runtimes without an intermediate daemon. This removes the central point of failure and allows for a more secure execution model.

The structural differences are detailed in the following table:

Feature Docker Podman
Daemon Required (dockerd) None
Root Required Yes (default) No (rootless default)
Docker Compose Native support Via podman-compose or socket
systemd Integration Limited Native (Quadlet)
Pod Support No Yes
Image Format Docker/OCI Docker/OCI

The lack of a daemon allows Podman to integrate natively with Linux security features. Because there is no central root process managing the containers, Podman can leverage user namespaces to run containers as unprivileged users. This rootless capability ensures that even if a container is compromised, the attacker does not gain root access to the host operating system, significantly reducing the attack surface of the infrastructure.

The Red Hat Container Toolset

Red Hat provides a comprehensive suite of command-line tools that replace the monolithic functionality of Docker. Instead of one tool doing everything, the functionality is split across specialized utilities.

  • Podman: This is the primary tool for the direct management of pods and container images. It handles the common lifecycle commands such as run, stop, start, ps, attach, and exec.

  • buildah: This utility is dedicated to the construction, pushing, and signing of container images. By separating the build process from the runtime process, buildah allows for more granular control over how images are created.

  • skopeo: This tool focuses on the movement of images. It can copy, verify, delete, and sign images between different storage backends, such as moving an image from a remote registry directly to local container storage without needing to pull it through a daemon first.

  • runc: This provides the low-level container execution and construction capabilities used by both Podman and buildah. It is the industry-standard runtime that ensures OCI compliance.

  • crun: This is a highly configurable runtime designed to improve the flexibility, control, and security of rootless containers.

Transitioning from Docker to Podman on RHEL 9

For systems where Docker was previously installed or for users migrating from other distributions, a systematic approach to migration is required to ensure that no data is lost and that system stability is maintained.

Removing Existing Docker Installations

If Docker is currently installed on a RHEL system, it must be fully decommissioned to avoid conflicts with the Podman toolset. The process begins with the cessation of all Docker services.

The following commands stop and disable the Docker daemon and its socket:

bash sudo systemctl stop docker docker.socket sudo systemctl disable docker docker.socket

Once the services are inactive, the Docker packages must be purged from the system. This includes the community edition, the CLI, the containerd runtime, and the compose plugin:

bash sudo dnf remove -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

To prevent conflicts and clean up the filesystem, the Docker data directory should be moved. It is recommended to back up this data before removal:

bash sudo mv /var/lib/docker /var/lib/docker.backup

Installing Podman and Container Tools

The installation of the replacement toolset is streamlined through the container-tools meta-package. This package ensures that Podman, Buildah, and Skopeo are installed in a compatible version set.

The installation command is as follows:

bash sudo dnf install -y container-tools

For users who require a seamless transition for their existing scripts and muscle memory, Red Hat provides a compatibility package. The podman-docker package installs a symlink at /usr/bin/docker that points directly to the Podman binary. It also provides a Docker-compatible man page, allowing the user to execute docker commands while the system actually runs Podman.

The installation of the compatibility package is performed via:

bash sudo dnf install -y podman-docker

Alternatively, a shell-level alias can be created for a specific user:

bash echo 'alias docker=podman' >> ~/.bashrc source ~/.bashrc

Data and Image Migration Strategies

Moving actual workloads from a Docker environment to a Podman environment requires the migration of images and persistent volumes.

Migrating Container Images

Container images can be migrated using standard OCI export/import methods or via high-performance tools like Skopeo.

To move images using tar archives, the user first saves the image on the old Docker system:

bash docker save my-app:latest -o my-app.tar docker save my-db:latest -o my-db.tar

These archives are then transferred to the RHEL system and loaded into Podman:

bash podman load -i my-app.tar podman load -i my-db.tar

For a more efficient transfer that avoids intermediate files, Skopeo can copy images directly between storage backends:

bash skopeo copy docker-daemon:my-app:latest containers-storage:my-app:latest

Migrating Persistent Volumes

Docker volumes are typically stored in /var/lib/docker/volumes/. Migrating these requires exporting the data from the Docker mount point and importing it into a Podman-managed volume.

First, identify the mount point of the Docker volume:

bash docker volume inspect my-data --format '{{.Mountpoint}}'

The data is then compressed into a tar archive:

bash sudo tar czf volume-backup.tar.gz -C /var/lib/docker/volumes/my-data/_data .

On the target RHEL system, a new Podman volume is created, and the data is restored:

bash podman volume create my-data mntPoint=$(podman volume inspect my-data --format '{{.Mountpoint}}') podman unshare tar xzf volume-backup.tar.gz -C "$mntPoint"

The use of podman unshare is critical here, as it allows the user to map the UID/GID of the archive to the correct subordinate UID on the host, maintaining the integrity of rootless permissions.

Configuring Docker Compose for Podman

While Docker has native support for Compose, Podman handles multi-container orchestration through podman-compose or by utilizing the Podman socket to interface with existing Compose tools.

To install podman-compose, the following command is used:

bash pip3 install --user podman-compose

Most existing docker-compose.yml files work without modification, as podman-compose translates the YAML specifications into Podman commands.

Bootable Containers and RHEL Base Images

A significant advancement in the RHEL ecosystem is the introduction of bootable containers. These merge containerization technology with full operating system deployment. Bootable containers use the OCI image format to package a full kernel and hardware support into a minimal image file.

This approach allows for the creation of deployable system images from standard RHEL Docker base images. These containers support multiple disk image formats, including:

  • raw
  • qcow
  • iso
  • vmdk
  • ami

This flexibility allows for atomic updates. A user can update a system by deploying a new container image and rebooting, ensuring a consistent state across the environment. If an update fails, the system can be rolled back to a previous image.

The foundation of these bootable containers are the RHEL Docker base images. These are provided in two main variants:

  1. RHEL base images: Full images providing a complete environment.
  2. Universal Base Images (UBI): Minimal, redistributable images designed for application deployment.

Critical Post-Migration Configuration and Troubleshooting

The transition from a root-daemon model to a rootless-daemonless model introduces several technical hurdles that must be addressed during the verification phase.

SELinux Enforcement

Docker on RHEL often operated with SELinux in permissive mode to avoid permission errors. Podman, however, enforces SELinux by default. This ensures that containers are confined to their expected security contexts. Users may encounter "Permission Denied" errors if their volume mounts are not correctly labeled for SELinux.

Rootless Port Binding

In Linux, binding to ports below 1024 is restricted to the root user. Because Podman runs as rootless by default, unprivileged users cannot bind to standard ports like 80 or 443. To resolve this, the system administrator must lower the unprivileged port start threshold:

bash sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80

User Namespace and UID Mapping

Files created by the root user inside a rootless container are not owned by the host's root user. Instead, they are owned by subordinate UIDs mapped to the user who started the container. This requires a conceptual shift in how host-volume permissions are managed.

Networking and the docker0 Bridge

Docker relies on a virtual bridge named docker0 for container networking. Podman does not use the docker0 bridge. Any legacy scripts that specifically reference the docker0 interface will fail and must be updated to reflect Podman's networking model.

Service Persistence and Linger

Rootless containers are tied to the user's session. Normally, when a user logs out, the system terminates the user's processes, including running containers. To ensure that containers survive user logout and start automatically at boot, the loginctl enable-linger command must be executed for that specific user.

Verification and Validation

Following the migration, a rigorous verification process is necessary to ensure the environment is fully operational.

The following checklist should be executed:

  • Check migrated images:
    bash podman images

  • Verify migrated volumes:
    bash podman volume ls

  • Confirm running containers:
    bash podman ps

  • Verify enabled systemd services:
    bash systemctl --user list-unit-files | grep web.service

  • Test network connectivity:
    bash podman run --rm docker.io/library/alpine ping -c 1 google.com

Analysis of the Migration Outcome

The transition from Docker to Podman on RHEL 9 is an evolution toward a more secure and modular architecture. The primary impact for the user is the elimination of the daemon, which removes a critical security vulnerability and a single point of failure. The adoption of the OCI image format ensures that the vast ecosystem of existing Docker images remains usable.

The most significant challenges in this migration are not found in the command-line syntax, which remains nearly identical, but in the underlying Linux security and networking layers. The shift to rootless containers requires a deeper understanding of SELinux, UID mapping, and port restrictions. However, the benefit is a system that is fundamentally more secure and better integrated with the Linux kernel's native capabilities.

The addition of bootable containers further extends this utility, turning container images into a mechanism for full OS deployment. This merges the speed of containerization with the reliability of a traditional OS, allowing for atomic updates and effortless rollbacks. Ultimately, the move to Podman represents a shift from "container-as-a-service" (via the Docker daemon) to "container-as-a-process," aligning the container lifecycle with standard Linux process management.

Sources

  1. oneuptime.com
  2. qiita.com
  3. nixfaq.org

Related Posts