Linux Podman for WordPress: Rootless Containers Without Docker

Podman is a daemonless, rootless container engine that is a drop-in CLI replacement for Docker — podman run accepts the same flags as docker run — but runs containers as an unprivileged user with no background daemon. For WordPress server deployments, rootless Podman containers provide stronger isolation than Docker (no root daemon to compromise) and integrate with systemd for automatic restart and log management.

Problem: Running WordPress in Docker requires root privileges for the Docker daemon — this is a security risk on shared servers and CI environments where rootless container execution is preferred.

Solution: Use Podman as a drop-in Docker replacement — it runs containers in a rootless, daemonless model where each container runs in the user's namespace. Replace docker commands with podman commands — the CLI is compatible. Use podman-compose with an existing docker-compose.yml to run WordPress + MySQL without root, and configure a systemd user service for auto-start on login.


The commands below set up a rootless WordPress + MariaDB stack with Podman, configure auto-start via systemd service files generated by Podman, and show how to manage volumes and networking without root privileges.


# ── 1. Install Podman ────────────────────────────────────────────────────
apt install podman   # Debian/Ubuntu
# or: dnf install podman  (RHEL/Rocky)

# ── 2. Create a pod (group of containers sharing network namespace) ───────
podman pod create \
    --name wordpress-pod \
    --publish 8080:80

# ── 3. Run MariaDB in the pod (rootless — no sudo) ────────────────────────
podman run -d \
    --pod wordpress-pod \
    --name wp-db \
    --env MARIADB_ROOT_PASSWORD=secret \
    --env MARIADB_DATABASE=wordpress \
    --env MARIADB_USER=wp \
    --env MARIADB_PASSWORD=wppass \
    --volume wp-db-data:/var/lib/mysql \
    docker.io/library/mariadb:11

# ── 4. Run WordPress in the same pod ─────────────────────────────────────
podman run -d \
    --pod wordpress-pod \
    --name wp-app \
    --env WORDPRESS_DB_HOST=127.0.0.1 \
    --env WORDPRESS_DB_NAME=wordpress \
    --env WORDPRESS_DB_USER=wp \
    --env WORDPRESS_DB_PASSWORD=wppass \
    --volume wp-content:/var/www/html/wp-content \
    docker.io/library/wordpress:6-php8.2-apache

# ── 5. Generate systemd unit files (auto-start on login/boot) ────────────
mkdir -p ~/.config/systemd/user

# Generate units for the pod and its containers
podman generate systemd --new --name wordpress-pod \
    > ~/.config/systemd/user/pod-wordpress-pod.service

systemctl --user daemon-reload
systemctl --user enable --now pod-wordpress-pod

# Enable lingering so the service runs even when the user is not logged in
loginctl enable-linger "$USER"

# ── 6. Common management commands ────────────────────────────────────────
podman pod ps                          # list pods and status
podman logs wp-app                     # container logs (no sudo)
podman exec -it wp-app wp --info       # run WP-CLI (if installed in image)
podman pod stop wordpress-pod
podman pod start wordpress-pod

# ── 7. Update containers to latest image version ─────────────────────────
podman auto-update   # updates all containers with --label io.containers.autoupdate=registry


NOTE: Rootless Podman containers cannot bind to ports below 1024 by default — use port 8080 mapped to 80 and put Nginx or Caddy on the host (running as root) as a reverse proxy, or increase net.ipv4.ip_unprivileged_port_start to 80 via sysctl to allow unprivileged port binding on the specific server.