You just installed Fedora and want to test a web server
You installed Fedora and want to run a database, a reverse proxy, or a random CLI utility without installing dependencies on your host. You type podman run and expect it to work. It does, but only if you understand what Podman is actually doing under the hood. Fedora ships with Podman preconfigured for rootless containers. That changes how you manage storage, networking, and permissions compared to older daemon-based tools. A misconfigured rootless setup can leave you unable to bind ports or mount host directories. Run your first container carefully. Verify the storage path before you commit to a workflow.
What is actually happening under the hood
Containers are isolated processes. They share the host kernel but get their own filesystem, network namespace, and process tree. Podman runs them without a background daemon. Every podman command spawns a short-lived helper process that talks directly to the container runtime. The rootless setup means your containers run under your regular user account. They cannot bind to ports below 1024 without extra configuration. They store images in ~/.local/share/containers/ instead of /var/lib/. This design keeps your host safe from a compromised container. It also means you do not need sudo for everyday container work. Think of it like running a virtual machine that shares your desktop kernel instead of emulating hardware. The overhead is minimal. The isolation is strict.
Fedora uses fuse-overlayfs as the default storage driver for rootless containers. The driver creates a layered filesystem inside your home directory. Each image layer is read-only. Each container gets a writable top layer. When you stop and remove a container, the writable layer disappears. The base image stays cached for future use. This matches the standard container lifecycle. It also means disk usage grows predictably. You can inspect the storage layout at any time. Run podman info to see where Podman keeps your data. The output will show graphRoot pointing to your home directory. This is intentional. Rootless containers cannot write to system directories without explicit privileges.
Check the storage driver before you debug performance issues. Half the time the bottleneck is a missing fuse module, not the container itself.
Running your first container
Start with a known-good image. The hello-world image prints a confirmation message and exits. It is the standard sanity check for any container engine. Run this command in your terminal.
podman run --rm -it docker.io/library/hello-world:latest
# --rm removes the container filesystem immediately after it exits
# -it allocates a pseudo-TTY and keeps stdin open for interactive use
# docker.io/library/ is the default registry path for official images
# :latest pulls the most recent tagged version of the image
The first run downloads the image layers. Subsequent runs use the cached copy. Podman stores everything in your home directory by default. You can verify the download location with podman info. The output will show graphRoot pointing to ~/.local/share/containers/storage. This is intentional. Rootless containers cannot write to system directories without explicit privileges.
If you want to run a long-running service, drop the --rm flag and detach from the terminal. Use the -d flag to run the container in the background. Here is how to start a lightweight web server and keep it running.
podman run -d --name nginx-test -p 8080:80 docker.io/library/nginx:alpine
# -d detaches the container and returns the container ID to the terminal
# --name assigns a human-readable label for future management commands
# -p maps host port 8080 to container port 80 for external access
# docker.io/library/nginx:alpine pulls a minimal Alpine-based web server
The container starts in the background. It listens on port 8080 on your host. You can open http://localhost:8080 in your browser to verify it is serving traffic. The -p flag creates a port forwarding rule in your user-level firewall. Fedora's firewalld does not interfere with rootless port mappings because Podman manages them inside the user network namespace. This keeps the host firewall clean. It also means you can run multiple containers on different host ports without conflicts.
Stop the container when you are done testing. Use the name you assigned to avoid guessing container IDs.
podman stop nginx-test
# Gracefully sends SIGTERM to the main process inside the container
# Waits up to ten seconds before forcing a SIGKILL if it does not exit
# Keeps the filesystem intact for inspection or restart
podman rm nginx-test
# Removes the stopped container and its writable layer
# Does not delete the underlying image unless you add --rmi
# Frees disk space and cleans up the local container list
Run podman ps before you delete anything. You will save yourself from accidentally removing a running service.
Verifying the runtime state
Check the container history and image cache. Run these commands to confirm the runtime state.
podman ps -a
# -a lists all containers, including stopped and exited ones
# The --rm flag should have already cleaned up the hello-world container
# If you see an empty list, the cleanup worked as expected
podman images
# Shows locally cached images and their sizes
# The hello-world image takes less than twenty megabytes
# You can safely remove it with podman rmi when you are done testing
The container ran, printed its message, and vanished. That is the expected lifecycle for a one-off task. For long-running services, you will drop the --rm flag and manage the container state explicitly. Podman tracks container metadata in ~/.local/share/containers/storage/overlay-containers/. Each container gets a directory with a JSON configuration file and a log file. You can read the logs directly with podman logs <container>. This avoids digging through journal entries for simple container output.
Verify the port mapping before you troubleshoot networking. A missing -p flag is the most common reason a container appears to be running but unreachable.
Common pitfalls and error patterns
New users often hit permission errors or network timeouts. Fedora's default firewall blocks incoming connections to rootless containers unless you configure the port forwarding correctly. If you try to bind a low port, you will see this error:
Error: listen tcp 0.0.0.0:80: bind: permission denied
Rootless containers cannot bind to ports below 1024. Use a high port like 8080 or 3000 instead. If you see a storage driver error, your system might be missing the required kernel modules or fuse-overlayfs package. Fedora Workstation includes fuse-overlayfs by default. Server editions sometimes require manual installation. Run dnf install fuse-overlayfs if the runtime complains about overlay mounts. Another common issue is stale lock files after a hard crash. Podman stores lock files in ~/.local/share/containers/storage/lock. If you get a container already exists error despite podman ps showing nothing, run podman system reset to clear the local state. Back up any important volumes first. The reset command wipes the local container store.
Volume mounts are another frequent source of confusion. Rootless containers cannot mount arbitrary host directories without correct permissions. If you try to mount a directory outside your home folder, you will see this error:
Error: error mounting /var/www/html: permission denied
Move your data into ~/containers-data/ or use podman unshare to adjust ownership before mounting. The rootless model enforces strict user boundaries. It prevents containers from reading /etc/shadow or modifying system binaries. This is a feature, not a bug. Work within the user namespace. Create a dedicated directory for container data. Mount it with the -v flag. The container will see it as a regular filesystem path.
Read the exact error message before you change SELinux contexts. Most permission denials are solved by fixing the host path ownership, not by disabling security modules.
When to use Podman versus other tools
Container runtimes serve different workflows. Pick the tool that matches your deployment pattern.
Use Podman when you want daemonless containers that run under your regular user account. Use Docker when you need legacy CI/CD pipelines that hardcode the Docker daemon socket. Use Kubernetes when you are orchestrating hundreds of containers across multiple nodes. Use buildah when you need to construct images without running a container first. Stick with Podman for local development, testing, and single-host deployments. It integrates with systemd, supports rootless networking, and matches the Fedora security model.
Run podman info before you commit to a workflow. Knowing your storage driver and network mode saves hours of debugging later.