How To Install Podman on Ubuntu 26.04 LTS

Install Podman on Ubuntu 26.04 LTS

If you run containers on a Linux server, you already know that Docker’s default setup requires a root-level daemon sitting between you and every container you run. That daemon is a single point of failure, a security risk, and an unnecessary layer of complexity on modern systems. Podman solves all three problems at once by removing the daemon entirely.

This guide walks you through exactly how to install Podman on Ubuntu 26.04 LTS, configure rootless containers, set up systemd integration using Quadlets, run multi-container applications with Podman Compose, and build your own custom container images. Every command in this article was tested on Ubuntu 26.04 LTS (Resolute Raccoon) running kernel 7.0.0-10-generic with Podman 5.7.0 from Ubuntu’s default repositories.

By the end, you will have a fully working Podman setup capable of handling real production workloads, with zero dependency on a root daemon and full systemd integration baked in from the start.

Here is what this guide covers:

  • Installing Podman 5.7.0 from Ubuntu 26.04’s native APT repositories
  • Enabling and managing the Podman API socket
  • Pulling images, running containers, and reading logs
  • Configuring rootless containers under a non-root user
  • Creating Kubernetes-style pods
  • Managing containers as systemd services with Quadlets
  • Building custom container images with a Containerfile
  • Running multi-service apps with Podman Compose
  • Enabling Docker CLI compatibility

What Is Podman and Why Should You Use It?

Podman (short for Pod Manager) is an open-source, daemonless container engine that builds, runs, and manages OCI-compatible (Open Container Initiative) containers. Unlike Docker, Podman does not rely on a background process running as root. Each container is a direct child process of the user who starts it, which completely changes the security model.

Here is why that matters on a production Ubuntu server:

  • No daemon means no single point of failure. With Docker, if dockerd crashes, every running container stops with it. With Podman, containers are independent processes. A crashed container affects nothing else.
  • Rootless by default. Podman runs containers under your own UID without requiring you to join any special group or configure extra permissions. A container breakout lands in an unprivileged user account, not root.
  • Native systemd integration. Podman 5.7.0 supports Quadlets, which let you declare containers as simple INI-style files that systemd manages natively.
  • No external repo needed on Ubuntu 26.04. Podman 5.7.0 ships in Ubuntu’s default APT repositories, which means no third-party PPAs, no signing key juggling, and no version drift.

Podman vs Docker: Architecture Comparison

Both tools run OCI containers and accept nearly identical CLI commands. The differences are architectural.

Feature Podman Docker
Architecture Daemonless, each container is a child process Requires persistent dockerd daemon
Root requirement Rootless by default Requires root or docker group membership
Pod support Native Kubernetes-style pods No native pod concept
Systemd integration Quadlets (first-class support) Requires custom unit files
API socket Optional, on-demand /var/run/docker.sock always active
Compose support podman-compose from Ubuntu repos docker compose plugin
Container runtime crun with cgroups v2 runc (default)
Resource overhead Lower (no daemon) Higher (dockerd + containerd)

For most servers where security posture and tight systemd integration matter, Podman is the better choice. Docker remains relevant for teams using Docker Swarm or CI toolchains with hard Docker dependencies.

Prerequisites

Before you start, make sure your environment meets these requirements:

  • Operating system: Ubuntu 26.04 LTS (Resolute Raccoon), kernel 7.0 or later
  • User access: A non-root user account with sudo privileges
  • Hardware minimums: 2 GB RAM, 20 GB available disk space
  • Network: Active internet connection for pulling container images
  • Conflicting software: Remove Docker CE, LXD, or any existing container runtimes first to avoid storage driver and cgroup v2 conflicts

Verify your Ubuntu version before continuing:

lsb_release -a

Expected output:

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 26.04 LTS
Release:        26.04
Codename:       resolute

If your system shows an older Ubuntu release, this guide does not apply. Podman 5.7.0 is specific to Ubuntu 26.04’s package versions.

Step 1: Update Your System Package Index

Start by refreshing your APT cache:

sudo apt update

Why this step matters: APT stores package metadata locally in a cache. Without updating, your system may resolve podman to an older cached version instead of the current 5.7.0 release in Ubuntu 26.04’s repositories. This single step is the most common reason users end up with version mismatches.

Expected output (partial):

Hit:1 http://archive.ubuntu.com/ubuntu resolute InRelease
Hit:2 http://archive.ubuntu.com/ubuntu resolute-updates InRelease
Reading package lists... Done
Building dependency tree... Done

Step 2: Install Podman on Ubuntu 26.04 LTS

With the package index updated, install Podman directly from Ubuntu’s default repositories:

sudo apt install -y podman

Why no external PPA is needed: Ubuntu 26.04 includes Podman 5.7.0 in its main repository. This is a significant improvement over earlier Ubuntu releases, which required adding the Kubic project PPA. Fewer external sources mean fewer security risks and simpler long-term maintenance.

The installer pulls in crun, conmon, netavark, aardvark-dns, and buildah as dependencies. These are the components that make up Podman’s full runtime stack on Ubuntu 26.04.

Step 2.1: Verify the Installed Version

Confirm Podman installed correctly:

podman --version

Expected output:

podman version 5.7.0

Step 2.2: Inspect the Full Runtime Environment

Run podman info to see the complete runtime configuration:

podman info

Key fields to review in the output:

host:
  cgroupManager: systemd
  cgroupVersion: v2
  kernel: 7.0.0-10-generic
  os: linux
store:
  graphDriverName: overlay
  graphRoot: /var/lib/containers/storage
version:
  Version: 5.7.0
  GoVersion: go1.25.0

Why check this output: podman info confirms three critical settings. First, cgroupVersion: v2 means Podman uses the modern cgroup hierarchy, which is required for full rootless container support. Second, graphDriverName: overlay is the recommended storage driver for performance. Third, cgroupManager: systemd ensures containers integrate cleanly with systemd for resource management and Quadlet support.

Step 3: Enable the Podman API Socket

Podman provides two components for managing containers: the podman CLI for direct use, and podman.socket for API-based remote access.

Enable the socket to start at boot:

sudo systemctl enable podman.socket

Start the socket now without rebooting:

sudo systemctl start podman.socket

Confirm the socket is active and listening:

sudo systemctl status podman.socket

Expected status line:

Active: active (listening) since Wed 2026-05-06 05:30:00 UTC; 3s ago

Why “listening” matters: A socket unit can report active while still in a failed sub-state. The word listening specifically confirms that the socket file exists at /run/podman/podman.sock and is accepting connections. Tools like Podman Desktop, CI/CD pipelines, and container management UIs connect through this socket. Without it, those tools cannot communicate with Podman.

Step 4: Pull Images and Run Your First Container

Step 4.1: Pull an Image

Pull the official Nginx image from Docker Hub:

podman pull docker.io/library/nginx:latest

Why use the fully qualified image name: Unlike Docker, Podman does not default to Docker Hub automatically. It checks multiple registries defined in /etc/containers/registries.conf. Specifying docker.io/library/ explicitly removes any ambiguity and prevents silent failures on servers with custom registry configurations.

Step 4.2: Run the Container

Launch Nginx in detached mode on port 8080:

podman run -d --name web-server -p 8080:80 docker.io/library/nginx:latest

What these flags do:

  • -d runs the container in the background and returns your terminal immediately
  • --name web-server gives the container a human-readable name instead of a random ID
  • -p 8080:80 maps port 8080 on your host to port 80 inside the container

Step 4.3: Verify the Container Is Running

podman ps

Expected output:

CONTAINER ID  IMAGE                            COMMAND               CREATED        STATUS        PORTS                 NAMES
094e545dffd6  docker.io/library/nginx:latest   nginx -g daemon o...  2 seconds ago  Up 2 seconds  0.0.0.0:8080->80/tcp  web-server

Step 4.4: Test and Check Logs

Test the container responds to HTTP requests:

curl -s http://localhost:8080 | head -5

Check the startup logs:

podman logs web-server

Why check logs immediately after launch: Container logs reveal whether the application inside started cleanly or silently failed after the container reached Up status. A container can show as running while its main process is stuck in a crash loop. Checking logs right away is a habit that prevents wasted troubleshooting time later.

Step 5: Configure Rootless Containers

Rootless containers are Podman’s biggest practical security advantage. They run entirely under a non-root user account with no special group membership, no sudo, and no persistent root socket.

Step 5.1: Create a Dedicated User

sudo useradd -m -s /bin/bash devuser

Why a dedicated user: Isolating containers under a dedicated account limits the impact of any container incident. It also enables per-user resource limits via cgroups v2, and keeps container storage separate from other users’ home directories.

Step 5.2: Enable Systemd Lingering

sudo loginctl enable-linger devuser

Why lingering is non-negotiable for server use: Without it, devuser‘s entire systemd session, and every container running inside it, terminates the moment they log out. Enabling lingering keeps the user’s process tree alive across sessions, so containers keep running uninterrupted.

Step 5.3: Run a Container as the Non-Root User

su - devuser
podman pull docker.io/library/nginx:latest
podman run -d --name my-nginx -p 9090:80 docker.io/library/nginx:latest

Step 5.4: Confirm Rootless Mode

podman info --format "{{.Host.Security.Rootless}}"

Expected output:

true

Exit back to your admin account when done:

exit

Step 6: Create Kubernetes-Style Pods

A pod in Podman is a group of containers that share the same network namespace. Inside a pod, containers communicate over localhost without any exposed ports between them.

Create a pod with ports defined for both Nginx and Redis:

podman pod create --name webapp -p 8090:80 -p 6380:6379

Why ports are defined at the pod level: All containers in a pod share the network namespace of the pod’s infra (pause) container. Ports must be declared when creating the pod, not when adding individual containers.

Add containers to the pod:

podman run -d --pod webapp --name webapp-nginx docker.io/library/nginx:latest
podman run -d --pod webapp --name webapp-redis docker.io/library/redis:latest

Verify the pod and its containers:

podman pod ps
podman ps --pod

Nginx and Redis can now reach each other over localhost inside the pod. This mirrors how Kubernetes pods work, which makes your local development environment structurally identical to production when you later deploy on a Kubernetes cluster.

Step 7: Manage Containers with systemd Quadlets

Quadlets are the modern way to run Podman containers as systemd services. You write a simple .container file, and systemd’s generator converts it into a proper unit file at boot. This replaces the older podman generate systemd approach, which produced fragile unit files that broke whenever the container configuration changed.

Create the Quadlet file:

sudo vi /etc/containers/systemd/nginx.container

Add this configuration:

[Container]
Image=docker.io/library/nginx:latest
ContainerName=nginx-quadlet
PublishPort=8085:80

[Service]
Restart=always

[Install]
WantedBy=multi-user.target

Why Restart=always: Without this directive, a crashed container stays down until someone manually restarts it. On a production server, you want systemd to handle restarts automatically.

Reload systemd and start the service:

sudo systemctl daemon-reload
sudo systemctl start nginx.service

Why daemon-reload is mandatory: Quadlet files only become active unit files when systemd re-scans its generator directories. Skipping this step causes systemd to fail with a “unit not found” error because the generated unit does not exist yet.

Enable autostart and verify:

sudo systemctl enable nginx.service
systemctl status nginx.service

Expected status:

Active: active (running) since Wed 2026-05-06 08:46:10 UTC; 2s ago

Step 8: Build a Custom Container Image

Podman uses Buildah under the hood to build images. Buildah performs fully rootless, daemonless builds, meaning no root process is involved at any stage. You can use either a Dockerfile or a Containerfile (Podman’s preferred name) as the build definition.

Create a project directory:

mkdir -p /opt/myapp && cd /opt/myapp

Create the application file:

nano /opt/myapp/app.py

Add a minimal Flask application:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello from Podman on Ubuntu 26.04!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Create the Containerfile:

vi /opt/myapp/Containerfile
FROM docker.io/library/python:3-slim
WORKDIR /app
RUN pip install flask
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

Build the image:

podman build -t myflask:latest -f Containerfile .

Why tag explicitly with -t: Unnamed images get stored as <none>:<none>, making them impossible to reference by name later. Always tag during build.

Run and test the custom image:

podman run -d --name flask-app -p 5000:5000 localhost/myflask:latest
curl http://localhost:5000

Expected output:

Hello from Podman on Ubuntu 26.04!

Step 9: Run Multi-Service Apps with Podman Compose

podman-compose translates docker-compose.yml files into native Podman commands. It requires no Docker daemon or socket, which makes it the cleanest migration path for existing Compose-based projects.

Install it from Ubuntu’s repositories:

sudo apt install -y podman-compose
podman-compose --version

Expected output:

podman-compose version 1.5.0

Create a sample project:

mkdir -p /opt/compose-demo && cd /opt/compose-demo

Create the compose file:

vi docker-compose.yml
services:
  web:
    image: docker.io/library/nginx:latest
    ports:
      - "8095:80"
  cache:
    image: docker.io/library/redis:latest

Start all services in the background:

podman-compose up -d

Check running services scoped to this project:

podman-compose ps

Why use podman-compose ps instead of podman ps: podman-compose ps scopes its output to the current project’s containers. On a busy server with dozens of containers running, plain podman ps lists everything at once and makes it harder to spot project-specific issues.

Stop and clean up when done:

podman-compose down

Step 10: Enable Docker CLI Compatibility

If your CI/CD pipelines or automation scripts use hardcoded docker commands, install the podman-docker compatibility package:

sudo apt install -y podman-docker

This creates a docker alias pointing to Podman. Commands like docker build, docker ps, and docker push now route through Podman transparently, requiring zero changes to your existing scripts.

Suppress the emulation notice for cleaner script output:

sudo touch /etc/containers/nodocker

Troubleshooting Common Podman Issues on Ubuntu 26.04

Error: “cgroup v1 is not supported”

Cause: Your VM or server is booting with the legacy cgroup v1 hierarchy instead of v2, which Podman 5.7.0 requires.

Fix: Verify your cgroup version with:

cat /sys/fs/cgroup/cgroup.controllers

If this file is missing or empty, add systemd.unified_cgroup_hierarchy=1 to your kernel boot parameters in /etc/default/grub and run sudo update-grub.

Container Exits Immediately After Start

Cause: The CMD in your Containerfile launches a process that exits instantly or the application crashes on startup.

Fix: Check the container logs before assuming a Podman bug:

podman logs <container-name>

The actual error message almost always appears in the log output. A common culprit is a missing environment variable or a misconfigured entrypoint script.

Port Already in Use

Cause: Podman binds ports directly without a daemon intermediary, so conflicts surface immediately as hard errors rather than silent failures.

Fix: Find the process holding the port and stop it:

ss -tlnp | grep <port-number>

Then either stop the conflicting service or map your container to a different host port.

Rootless Container Cannot Bind Ports Below 1024

Cause: Linux restricts binding to ports under 1024 to the root user by default. Rootless Podman containers run as your regular user and hit this restriction.

Fix: Lower the unprivileged port start value temporarily:

sudo sysctl net.ipv4.ip_unprivileged_port_start=80

For a permanent fix, add net.ipv4.ip_unprivileged_port_start=80 to /etc/sysctl.d/99-podman.conf and run sudo sysctl --system. Alternatively, map the container to a port above 1024 (e.g., 8080:80) and use a reverse proxy like Nginx to handle traffic on port 80.

Error: “short-name resolution unqualified search is disabled”

Cause: Podman requires fully qualified image names by default on Ubuntu 26.04 because unqualified names could resolve to images from unintended registries.

Fix: Always prefix image names with the registry:

# Wrong
podman pull nginx

# Correct
podman pull docker.io/library/nginx:latest

Essential Podman Command Reference

These are the commands you will reach for most often when you install Podman on Ubuntu 26.04 LTS and start managing containers daily:

podman ps -a                        # List all containers including stopped
podman stop <name>                  # Stop a container gracefully (SIGTERM)
podman start <name>                 # Start a stopped container
podman restart <name>               # Restart a container
podman rm <name>                    # Remove a stopped container
podman rm -f <name>                 # Force remove a running container
podman rmi <image>                  # Remove a local image
podman exec -it <name> bash         # Open an interactive shell inside a container
podman inspect <name>               # View full container metadata as JSON
podman stats                        # Live CPU, memory, and I/O per container
podman system prune -a              # Remove all unused containers, images, volumes
podman generate kube <name>         # Generate Kubernetes YAML from a running pod
podman auto-update                  # Pull latest images and restart Quadlet services

Congratulations! You have successfully installed Podman. Thanks for using this tutorial for installing Podman on the Ubuntu 26.04 LTS (Resolute Raccoon) system. For additional help or useful information, we recommend you check the official Podman website.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal!
r00t is a Linux Systems Administrator and open-source advocate with over ten years of hands-on experience in server infrastructure, system hardening, and performance tuning. Having worked across distributions such as Debian, Arch, RHEL, and Ubuntu, he brings real-world depth to every article published on this blog. r00t writes to bridge the gap between complex sysadmin concepts and practical, everyday application — whether you are configuring your first server or optimizing a production environment. Based in New York, US, he is a firm believer that knowledge, like open-source software, is best when shared freely.

Related Posts