Running a Tiny Nginx Web Server in a Rootless Podman Container on Ubuntu 24.04

Ubuntu 24.04 ships with a fully‑featured Podman package that works out of the box.
Rootless mode lets a normal user spin up containers without any privileged operations, which is a great fit for a home lab or a small self‑hosted service.
Below is a step‑by‑step guide to build a minimal Nginx image, run it rootlessly, and keep the whole thing under tight, sane defaults.

Prerequisites

  • Ubuntu 24.04 (LTS) installed on a machine or VM.
  • A non‑root user with sudo privileges (the example assumes alice).
  • Basic knowledge of the shell, sudo, and systemd.
# Verify the kernel version – user namespaces require 5.8+ (Ubuntu 24.04 uses 6.6)
uname -r
# Install Podman if it isn’t already
sudo apt update
sudo apt install -y podman

Enable rootless mode

Podman automatically falls back to rootless when run as a normal user, but you should confirm that the user‑namespace mapping is in place:

podman info | grep -i userns

If you see userns: true, you’re good to go.
If not, add the following to /etc/subuid and /etc/subgid:

echo "alice:100000:65536" | sudo tee -a /etc/subuid /etc/subgid

Then log out and back in.

Building a Tiny Nginx Image

The official nginx:alpine image is already lightweight (~20 MB).
We’ll add a minimal configuration and a single static page.

# Dockerfile
FROM nginx:alpine

# Remove the default config
RUN rm /etc/nginx/conf.d/default.conf

# Add our own minimal config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Add a simple index page
RUN mkdir -p /usr/share/nginx/html && \
    echo "<h1>Hello from rootless Podman!</h1>" > /usr/share/nginx/html/index.html

# Expose HTTP
EXPOSE 80

nginx.conf:

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Build the image locally:

podman build -t tiny-nginx .

The resulting image is ~25 MB – small enough to pull from a remote registry or build locally on a low‑bandwidth connection.

Running the Container Rootlessly

Direct run

podman run -d --name tiny-nginx \
  -p 8080:80 \
  --restart=always \
  tiny-nginx
  • -d – detach.
  • --name – gives the container a friendly name.
  • -p 8080:80 – maps host port 8080 to container port 80.
  • --restart=always – ensures the container restarts after a reboot.

Open a browser to http://localhost:8080 – you should see the “Hello” page.

Using a systemd user unit

Rootless containers are best managed with systemd user units.
Create ~/.config/systemd/user/containers-tiny-nginx.service:

[Unit]
Description=Rootless Tiny Nginx
After=network-online.target

[Service]
Restart=always
ExecStart=/usr/bin/podman run --rm --name tiny-nginx -p 8080:80 tiny-nginx
ExecStop=/usr/bin/podman stop -t 10 tiny-nginx
ExecStopPost=/usr/bin/podman rm -f tiny-nginx

[Install]
WantedBy=

See also