Podman on SLES 16: Installation, Storage, and First Rootless Container (2026 Guide)
Quick one-liner: Install Podman on SLES 16 from the installation DVD, set up shared multi-user storage on a dedicated disk, and run your first rootless container — no Docker required.
(This guide targets SLES 16. The concepts apply to SLES 15 as well, but I've only verified the steps on SLES 16.)
Why This Matters
Docker isn't the only container runtime. On SUSE Linux Enterprise Server, SLES ships Podman as the native container tool through its official Containers module — and it has genuine advantages over Docker.
The biggest one: rootless by default.
With Docker, the daemon runs as root. That means a container escape could give an attacker root access to your host. Podman runs containers under your regular user account — no root daemon, no single point of failure.
There's also no daemon at all. Podman is daemonless — each container runs as a direct child process. Simpler, more secure, easier to debug.
If you're in an enterprise environment running SLES, Podman is the natural fit. It's supported by SUSE, available on the installation DVD, and doesn't require third-party repositories. This guide gets you from a fresh SLES install to running your first container.
Prerequisites
- SLES 16 (minimal or server installation)
- DVD repository enabled (see Add a DVD as a Local Zypper Repository) — or an active SCC subscription
- Two virtual disks (recommended): 40 GB for the OS, 20 GB for container storage
- 15-20 minutes
Why Two Disks?
Before we start — if you're setting this up on a VM, add a second virtual disk.
Container images accumulate fast. A few images later, your root partition fills up and everything breaks. Keeping container storage on a separate disk means:
- Container data is isolated from the OS
- You can resize or wipe container storage without touching the OS
- Backups are simpler — back up the container disk separately
This is a production best practice worth building into your habits from day one.
Step 1: Mount the Second Disk
If you added a second disk, set it up before installing Podman.
Find the disk:
$ lsblk
On this VM the layout looks like:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 1024M 0 rom
vda 254:0 0 40G 0 disk
├─vda1 254:1 0 8M 0 part
├─vda2 254:2 0 38G 0 part /var
│ /usr/local
│ /opt
│ /home
│ /srv
│ /root
│ /boot/grub2/i386-pc
│ /boot/grub2/x86_64-efi
│ /.snapshots
│ /
└─vda3 254:3 0 2G 0 part [SWAP]
vdb 254:16 0 20G 0 disk
vda (40 GB) is the OS disk. vdb (20 GB) is the dedicated disk for container storage.
Format vdb with XFS (SLES default):
$ sudo mkfs.xfs /dev/vdb
Create the mount point:
$ sudo mkdir -p /var/lib/containers
Add to /etc/fstab for persistence:
$ echo '/dev/vdb /var/lib/containers xfs defaults 0 0' | sudo tee -a /etc/fstab
Mount everything from fstab and verify:
$ sudo mount -a
$ df -Th /var/lib/containers
Step 2: Install Podman
Podman ships on the SLES 16 installation DVD. Enable the DVD repository and install:
$ sudo zypper mr -e SLES
$ sudo zypper install -y podman fuse-overlayfs
Verify:
$ podman --version
podman version 5.4.2
Step 3: Set Up Shared Multi-User Storage
This is where most guides stop — they just say "install and go." But in a real environment, multiple people will run rootless containers. Each user's container images and layers are stored separately (rootless Podman stores everything under each user's home directory by default). If you don't plan for this, each user's ~/.local fills up their own home partition independently and unpredictably.
Here is how I like to set up Podman in an enterprise environment. Each user gets their own isolated space on a shared disk, and access is controlled through a group:
As root (or sudo):
Create the shared storage directory and the podman group:
$ sudo mkdir -p /var/lib/containers/storage
$ sudo groupadd podman
$ sudo chown root:podman /var/lib/containers/storage
$ sudo chmod 2775 /var/lib/containers/storage
The 2775 permission is important — the setgid bit means any subdirectory created inside /var/lib/containers/storage automatically inherits the podman group. That keeps things consistent as you add users.
Add users who should have container access:
$ sudo usermod -aG podman sysadmin
Why Subordinate UIDs Matter
In rootless mode, container processes run in their own user namespace. Their UIDs get remapped to different UIDs on your host. This is a Linux kernel feature (user_namespaces(7)) and works identically for both rootless Docker and rootless Podman. The mapping looks like this:
| Inside container | On your host |
|---|---|
| UID 0 (root) | Your user UID (e.g. 1000) |
| UID 1 | subuid_start |
| UID N | subuid_start + N - 1 |
The subuid_start is defined in /etc/subuid:
$ grep sysadmin /etc/subuid
sysadmin:100000:65536
SLES assigns 100000 by default. This means a container process running as UID 1000 lands on your host as UID 100999 (100000 + 1000 - 1). If your bind-mounted directory is owned by you (1000), that container process cannot write to it.
I prefer explicit ranges so the math is clean and there's no guessing. First, remove any existing subordinate UID/GID entries, then set the new range:
$ sudo sed -i "/^sysadmin:/d" /etc/subuid
$ sudo sed -i "/^sysadmin:/d" /etc/subgid
$ sudo usermod --add-subuids 100001-165536 sysadmin
$ sudo usermod --add-subgids 100001-165536 sysadmin
This gives 65,536 subordinate UIDs and GIDs. Now the mapping is clean and predictable:
| Inside container | On your host |
|---|---|
| 0 | 1000 (sysadmin) |
| 1 | 100001 |
| 1000 | 101000 |
Verify:
$ cat /etc/subuid
sysadmin:100001:65536
$ cat /etc/subgid
sysadmin:100001:65536
As each user:
Log out and back in so the group change takes effect. Verify:
$ groups
You should see podman in the list.
Create your personal storage directory:
$ mkdir -p /var/lib/containers/storage/sysadmin
Create Podman's per-user storage config:
$ mkdir -p ~/.config/containers
$ cat > ~/.config/containers/storage.conf << 'EOF'
[storage]
driver = "overlay"
graphroot = "/var/lib/containers/storage/sysadmin"
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
EOF
This file tells rootless Podman to store your images, containers, and layers on the shared disk instead of filling up your home directory.
Verify:
$ podman info | grep graphRoot
You should see /var/lib/containers/storage/sysadmin.
Step 4: Run Your First Container
Now run a container as your regular user:
$ podman run quay.io/podman/hello:latest
You should see:
Embracing and extending the Podman community...
================================================================
Podman Podman Podman
================================================================
... (Podman hello output) ...
Have a great day!
Podman ran this rootless — no root daemon, no extra configuration.
Check the container ran successfully:
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2671631a4e8a quay.io/podman/hello:latest /usr/local/bin/po... 26 seconds ago Exited (0) 26 seconds ago stoic_sammet
This is a good moment to clarify the difference between podman ps and podman ps -a:
| Command | What it shows |
|---|---|
podman ps |
Only running containers |
podman ps -a |
All containers — running, stopped, or exited |
If you run podman ps right now, it returns nothing — the hello container printed its message and exited immediately. It worked perfectly, it just isn't running anymore. podman ps -a shows the full history, including containers that completed and stopped.
Step 5: Verify Rootless Operation
This is the key difference from Docker. In rootless mode, there's no persistent background daemon waiting for commands. Check the status:
$ systemctl status podman
You'll see the podman.service exists but is inactive:
○ podman.service - Podman API Service
Loaded: loaded (/usr/lib/systemd/system/podman.service; disabled; preset: disabled)
Active: inactive (dead)
TriggeredBy: ○ podman.socket
This is normal — it's a socket-activated service. It starts only when needed (for example, when Podman Desktop or other tools connect to it) and shuts down when idle. Unlike Docker, there's no dockerd process sitting at PID 1 consuming resources all day.
Verify storage is on the shared disk:
$ df -Th /var/lib/containers/storage/sysadmin
You should see your second disk, not the root partition.
Podman vs Docker: Key Differences
| Feature | Podman | Docker |
|---|---|---|
| Daemon | None (daemonless) |
dockerd runs as root |
| Default user | Rootless | Root |
| CLI compatibility | Drop-in replacement (alias docker=podman) |
— |
| systemd integration | Native (Quadlet) | Requires extra config |
| SLES support | On the installation DVD | Third-party repository |
| Security | No root daemon, SELinux-ready | Root daemon exposure |
The CLI is fully compatible — most docker commands work with podman. You can set the alias:
$ alias docker=podman
Try It: Parse JSON Without Installing Anything
Instead of the usual hello-world, let's verify rootless Podman with something useful.
Create a sample JSON file:
$ cat > ~/sample.json << 'EOF'
{"name":"David","company":"Transcend Solutions","role":"DevOps Engineer","skills":["Docker","Kubernetes","Linux"],"location":"Singapore","experience_years":15}
EOF
Normally you'd need to install jq to parse and pretty-print this JSON. With Podman, the tool comes with the container:
$ cat ~/sample.json | podman run ghcr.io/jqlang/jq '.'
The image pulls:
Trying to pull ghcr.io/jqlang/jq:latest...
Getting image source signatures
Copying blob e27c450974af done |
Copying blob ee0085cc4ebc done |
Copying config 3bada1936a done |
Writing manifest to image destination
But the output is completely blank. No error, no JSON — nothing.
That's because podman run doesn't pass standard input into the container by default. The jq process started, received nothing, and exited silently. To pipe data in, you need the -i flag:
$ cat ~/sample.json | podman run -i ghcr.io/jqlang/jq '.'
Now the output — beautifully formatted JSON:
{
"name": "David",
"company": "Transcend Solutions",
"role": "DevOps Engineer",
"skills": [
"Docker",
"Kubernetes",
"Linux"
],
"location": "Singapore",
"experience_years": 15
}
No installation. No sudo zypper install jq. No repository configuration. The jq binary lives inside the container, and you used it without touching your host system.
What's happening here:
| Flag | Purpose |
|---|---|
-i |
Keep stdin open so jq can read the piped JSON |
'.' |
The jq filter — . means "print everything, formatted" |
What's Next
You've got Podman installed with proper shared storage and running rootless containers on SLES 16.
Coming up: running your first real workload — pulling images, managing container lifecycles, and understanding the differences between podman run flags you'll use every day.
Author: David Tio
Tags: Podman, SLES 16, SUSE, Containers, Rootless, Linux, Enterprise, DevOps, Tutorial
Series: Levelling Podman
Word Count: ~1,500
Top comments (0)