You cloned a repo and the build script failed
You cloned a project from GitHub. The README says "Run docker compose up." You type it in, and the terminal replies docker: command not found. You remember Fedora uses Podman, not Docker. You run sudo dnf install docker, and suddenly your package manager warns about conflicts with podman-docker. You need containers for development, but you don't want to break your system or fight the package manager.
What's actually happening
Fedora treats containers as first-class citizens. The default engine is Podman. Podman does not run a background daemon. It starts containers as regular processes owned by your user. This means you don't need sudo to run containers. It also means if a container crashes, it doesn't take down a central daemon. The architecture is simpler and safer.
Docker is a brand. Podman is the tool Fedora ships. The docker command exists in Fedora only as a compatibility shim. The podman-docker package provides a docker binary that is a symlink to podman. It also sets up a socket so that tools expecting the Docker API can talk to Podman. You get the same workflow without the root dependency.
Think of Docker like a central server room where a daemon manages everything. If the daemon dies, all containers stop. Think of Podman like a toolbox. Each container runs as a child process of your shell. You can kill a container without affecting others. You can run containers without root privileges. Fedora defaults to this model because it aligns with the security goals of the distribution.
Fedora uses the overlay storage driver for efficiency. Rootless containers cannot use the kernel overlay directly without privileges. Fedora solves this with fuse-overlayfs. This runs in user space. It gives you the speed and disk efficiency of overlay without root. If you skip this package, Podman falls back to vfs. The vfs driver copies every layer. A 200MB image becomes 200MB on disk for every container. Your /home partition fills up fast. Install fuse-overlayfs before you pull your first image. Disk space is not infinite.
Rootless containers also use slirp4netns for networking. This creates a user-space network stack. It isolates the container from the host network. You can publish ports with -p, and they work. The overhead is small for development. If you need raw performance, you can run rootful containers, but you lose the safety model. For development, rootless is the standard.
The fix
Install the core packages and enable the rootless socket. The podman-docker package ensures that docker commands work alongside podman commands. This is essential if your project scripts hardcode docker.
sudo dnf install podman podman-docker fuse-overlayfs slirp4netns
# podman is the container engine. podman-docker provides the 'docker' command as a symlink.
# fuse-overlayfs enables efficient storage for rootless containers.
# slirp4netns provides user-space networking for rootless containers.
Enable the user socket so the docker command can communicate with Podman. The docker shim talks to Podman via a Unix socket. Without the socket, docker ps will fail even if podman ps works.
systemctl --user enable --now podman.socket
# Starts the rootless API socket. The 'docker' command talks to Podman through this socket.
# --user targets your user session. This keeps the socket isolated from other users.
Configuration lives in ~/.config/containers/. This is the user directory. System-wide config is in /etc/containers/. Edit your home directory. Never edit /etc/ files for user preferences. The package manager will overwrite /etc/ on updates. Your ~/.config/ files persist. If you need to change storage settings, create ~/.config/containers/storage.conf.
Run podman system info if you need to check storage drivers. Trust the output.
Verify it worked
Test both the native command and the compatibility shim. This confirms the engine is installed, the storage driver is correct, and the socket is active.
podman run --rm docker.io/library/alpine echo "Podman works"
# --rm removes the container after it exits. docker.io/library/ is the default registry path.
# This pulls a tiny image, runs a command, and cleans up. No sudo required.
docker ps
# Verifies the compatibility shim. If this returns a list (even empty), the socket is active.
# If this fails, the podman.socket is not running or the shim is misconfigured.
Check the storage driver to ensure you are not using vfs.
podman info | grep graphDriverName
# Checks the storage driver. You want 'overlay'.
# If you see 'vfs', your disk usage will grow linearly with every image layer.
# Reinstall fuse-overlayfs and run 'podman system reset' if you see vfs.
Run journalctl --user -u podman.socket if the socket fails to start. Read the actual error before guessing.
Common pitfalls and what the error looks like
The sudo trap
Never run sudo podman. This breaks rootless isolation and creates permission mismatches. If you run sudo podman, the container runs as root and stores data in /var/lib/containers. Your user cannot access that data. You end up with two separate container stores.
If you accidentally run sudo podman, you will see errors like Error: cannot connect to Podman. The rootless client tries to talk to the user socket, but the container is running in a root context. Drop the sudo. Run podman directly. If you need root privileges for a specific task, use podman --privileged inside the container, not sudo outside.
Storage driver fallback
If fuse-overlayfs is missing, Podman falls back to vfs. You might not see an error. You will see slow builds and high disk usage.
$ podman info | grep graphDriverName
graphDriverName: vfs
This output means you are wasting disk space. Install fuse-overlayfs and reset the storage.
sudo dnf install fuse-overlayfs
# Installs the overlay driver. Required for efficient rootless storage.
podman system reset
# Wipes all containers and images. Use this only when changing storage drivers.
# Back up your data before running this command.
Docker command not found
If you see docker: command not found, you are missing the shim.
sudo dnf install podman-docker
# Provides the 'docker' binary. This package is a symlink to podman.
# It also configures the socket compatibility layer.
Socket not running
If docker ps hangs or fails, the socket is down.
$ docker ps
Cannot connect to the Docker daemon at unix:///run/user/1000/podman/podman.sock. Is the docker daemon running?
The error mentions "docker daemon" because the shim uses Docker error messages. The fix is to start the socket.
systemctl --user start podman.socket
# Starts the socket immediately. Use 'enable --now' to make it persistent.
Run systemctl --user status podman.socket if the socket fails to start. The status output shows why the service stopped.
When to use this vs alternatives
Use Podman when you want rootless containers and native Fedora integration. Use the podman-docker shim when your project scripts hardcode docker commands and you don't want to rewrite them. Install Docker CE only when you require features that Podman does not support, such as Swarm mode or specific Docker Desktop integrations. Stick to podman commands when you are writing new automation and want to avoid the compatibility layer.
Pick the shim for legacy scripts. Pick Podman for new work. Don't install both engines.