How to Install Podman as a Rootless Docker Alternative on RHEL 7
Podman is a daemonless, rootless container engine developed by Red Hat that is fully compatible with the OCI (Open Container Initiative) standard and largely compatible with the Docker CLI. Unlike Docker, Podman does not require a long-running background daemon running as root, which significantly reduces the attack surface on production servers. Each user can run containers entirely within their own namespace without any elevated privileges. While Podman is the default container tool on RHEL 8 and later, it can be installed on RHEL 7 from the extras or EPEL repositories. This tutorial covers installation, rootless configuration, basic container operations, Docker CLI compatibility, and running containers as persistent systemd services.
Prerequisites
- RHEL 7.6 or later with a valid Red Hat subscription (for the extras repo) or EPEL enabled
- Kernel 3.10 or later (standard on RHEL 7)
- Root access to install packages and configure subuid/subgid
- A non-root user account that will run rootless containers
shadow-utils4.1.5.1-13 or later (providesnewuidmap/newgidmap)
Step 1: Enable the Required Repositories
Podman is available in the RHEL 7 extras channel. If you have a valid subscription, enable extras:
sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
If you are using CentOS 7 or do not have a subscription, install from EPEL:
sudo yum install -y epel-release
Step 2: Install Podman and Supporting Packages
sudo yum install -y podman slirp4netns fuse-overlayfs shadow-utils
Package roles:
- podman — the main container engine
- slirp4netns — user-space networking for rootless containers
- fuse-overlayfs — user-space overlay filesystem required for rootless storage
- shadow-utils — provides
newuidmapandnewgidmapfor user namespace mapping
Verify the installation:
podman --version
Step 3: Configure subuid and subgid for Rootless Operation
Rootless containers use Linux user namespaces. Each user account needs a range of subordinate UIDs and GIDs allocated in /etc/subuid and /etc/subgid. These ranges allow the container’s internal root (UID 0) to map to an unprivileged UID on the host.
Check whether entries already exist for your user:
grep $(whoami) /etc/subuid /etc/subgid
If no entries exist, add them (replace appuser with your actual username):
sudo usermod --add-subuids 100000-165535 appuser
sudo usermod --add-subgids 100000-165535 appuser
Verify:
cat /etc/subuid
cat /etc/subgid
You should see a line like: appuser:100000:65536
Step 4: Configure Rootless Storage
Switch to the non-root user and initialise the Podman storage configuration. Podman will create its storage config automatically on first run, but you can force it to use fuse-overlayfs explicitly:
su - appuser
mkdir -p ~/.config/containers
cat > ~/.config/containers/storage.conf <<'EOF'
[storage]
driver = "overlay"
[storage.options]
mount_program = "/usr/bin/fuse-overlayfs"
EOF
Step 5: Pull and Run Your First Rootless Container
All the following commands are run as the non-root user:
# Pull an image from Docker Hub
podman pull nginx:alpine
# Run a container (rootless, no sudo needed)
podman run -d --name myweb -p 8080:80 nginx:alpine
# Verify it is running
podman ps
# Test the web server
curl http://localhost:8080
Note that rootless containers cannot bind to ports below 1024 by default. Use ports 1024 and above, or configure net.ipv4.ip_unprivileged_port_start on the host if needed:
# Allow unprivileged bind to port 80 (as root)
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80
# Make persistent
echo "net.ipv4.ip_unprivileged_port_start=80"
| sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl -p /etc/sysctl.d/99-podman-ports.conf
Step 6: Common Podman Commands
# List running containers
podman ps
# List all containers including stopped
podman ps -a
# View container logs
podman logs myweb
# Stop a container
podman stop myweb
# Remove a container
podman rm myweb
# Remove an image
podman rmi nginx:alpine
# List all local images
podman images
# Inspect a container
podman inspect myweb
# Execute a command inside a running container
podman exec -it myweb /bin/sh
# Copy files to/from a container
podman cp /tmp/index.html myweb:/usr/share/nginx/html/
# Build an image from a Containerfile (identical to Dockerfile syntax)
podman build -t myapp:1.0 /path/to/context
Step 7: Docker CLI Compatibility
Podman’s CLI is designed to be a drop-in replacement for Docker. You can create an alias so that any script or muscle memory that types docker transparently calls podman:
# Add to ~/.bashrc
echo "alias docker=podman" >> ~/.bashrc
source ~/.bashrc
# Now these work exactly as expected
docker ps
docker run --rm hello-world
For system-wide compatibility, create a wrapper script:
sudo tee /usr/local/bin/docker <<'EOF'
#!/bin/bash
exec podman "$@"
EOF
sudo chmod +x /usr/local/bin/docker
Note that Podman does not have a daemon listening on a socket by default, so tools that use the Docker socket (/var/run/docker.sock) directly — such as Portainer or Docker Compose — will need to use the Podman socket instead. You can activate the Podman socket service on a per-user basis:
systemctl --user enable --now podman.socket
# The socket path will be
ls /run/user/$(id -u)/podman/podman.sock
Step 8: Create Persistent systemd Services from Containers
Podman can generate systemd unit files from running containers, enabling containers to start at boot and be managed with systemctl. This is the recommended approach for rootless containers on RHEL 7:
# First, create the container you want to persist
podman run -d --name myweb
-p 8080:80
--restart=on-failure
nginx:alpine
# Generate the systemd unit file
mkdir -p ~/.config/systemd/user/
podman generate systemd --name myweb --files --new
--restart-policy=on-failure
-t 10
# Move the generated file to the user systemd directory
mv container-myweb.service ~/.config/systemd/user/
# Reload the systemd user daemon and enable the service
systemctl --user daemon-reload
systemctl --user enable --now container-myweb.service
# Check status
systemctl --user status container-myweb.service
To ensure the user’s systemd services keep running after the user logs out (required for a server that should persist services across sessions), enable lingering for the user:
sudo loginctl enable-linger appuser
Conclusion
Podman offers a compelling, security-focused alternative to Docker on RHEL 7. Its rootless architecture means that a compromised container process cannot escalate privileges to root on the host — a significant security improvement over the traditional Docker daemon model. Because Podman’s CLI mirrors Docker’s nearly completely, the learning curve for teams already using Docker is minimal: pull images the same way, run containers the same way, and build images using the exact same Dockerfile syntax. With podman generate systemd, containers integrate cleanly into the systemd service model that RHEL administrators already know, providing reliable auto-start, restart policies, and service management through standard tooling.