Docker

How to Install Docker on Fedora 44 / 43 / 42

Fedora ships with Podman as its default container runtime, and for plenty of workloads Podman is enough. The moment you need Docker Compose beyond toy stacks, BuildKit for advanced image builds, Docker Swarm, or full Docker API compatibility for your CI pipelines, Docker CE is the cleaner choice.

Original content from computingforgeeks.com - post 4554

This guide installs Docker CE from Docker’s official Fedora repository, then puts it through a real workout: hello-world, a Compose stack with Nginx and Redis, daemon tuning via /etc/docker/daemon.json, SELinux bind-mount labelling, and rootless Docker. Every command was run on a clean Fedora 44 box. The same commands work on Fedora 43 and 42 because the Docker CE repo is shared across the three current Fedora releases.

Prerequisites

You need a running Fedora 44, 43, or 42 system (Workstation, Server, or Cloud Edition all work) with sudo access. SELinux can stay in enforcing mode, which is the default. The Docker packages ship with the right policies, so do not disable SELinux for this.

Step 1: Set reusable shell variables

Several commands reference your username and the Compose test directory. Export them once so you only edit a single block:

export DOCKER_USER="$USER"
export COMPOSE_DIR="$HOME/compose-test"
export DOCKER_REPO_URL="https://download.docker.com/linux/fedora/docker-ce.repo" #https://docs.docker.com/engine/install/fedora/

Confirm the variables hold:

echo "User:  ${DOCKER_USER}"
echo "Stack: ${COMPOSE_DIR}"
echo "Repo:  ${DOCKER_REPO_URL}"

Step 2: Remove conflicting packages

Older Docker packages from third-party COPRs or earlier installs can collide with Docker CE. Clean them up before adding the Docker repo:

sudo dnf remove -y docker docker-client docker-client-latest docker-common \
  docker-latest docker-latest-logrotate docker-logrotate docker-selinux \
  docker-engine-selinux docker-engine

On a fresh Fedora install, DNF reports each package as already absent and exits cleanly:

No packages to remove for argument: docker-selinux
No packages to remove for argument: docker-engine-selinux
No packages to remove for argument: docker-engine

Nothing to do.

Step 3: Add the Docker CE repository

Install the DNF plugins package so the config-manager subcommand is available:

sudo dnf install -y dnf-plugins-core

Add the Docker CE repository. Fedora 44 and 43 ship DNF5, which uses addrepo --from-repofile=:

sudo dnf config-manager addrepo --from-repofile="${DOCKER_REPO_URL}"

If your machine is still on Fedora 42 with DNF4, swap the syntax for --add-repo. Same repo file, different flag spelling:

sudo dnf config-manager --add-repo "${DOCKER_REPO_URL}"

Verify the repo is registered. The docker-ce-stable id should appear next to the Fedora base repos:

sudo dnf repolist

The output lists the Docker repo alongside the Fedora base repos:

repo id               repo name
docker-ce-stable      Docker CE Stable - x86_64
fedora                Fedora 44 - x86_64
fedora-cisco-openh264 Fedora 44 openh264 (From Cisco) - x86_64
updates               Fedora 44 - x86_64 - Updates

Step 4: Install Docker CE on Fedora

Install the engine, CLI, containerd, BuildKit plugin, and the Compose v2 plugin in one transaction:

sudo dnf install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

DNF resolves the dependency tree, pulls roughly 100 MiB of packages, and imports Docker’s GPG signing key on first install:

Installing:
 containerd.io             x86_64  0:2.2.3-1.fc44   docker-ce-stable
 docker-buildx-plugin      x86_64  0:0.34.0-1.fc44  docker-ce-stable
 docker-ce                 x86_64  3:29.5.2-1.fc44  docker-ce-stable
 docker-ce-cli             x86_64  1:29.5.2-1.fc44  docker-ce-stable
 docker-compose-plugin     x86_64  0:5.1.4-1.fc44   docker-ce-stable
Installing weak dependencies:
 docker-ce-rootless-extras x86_64  0:29.5.2-1.fc44  docker-ce-stable

Transaction Summary:
 Installing: 9 packages

Total size of inbound packages is 100 MiB.
After this operation, 379 MiB extra will be used.

Importing OpenPGP key 0x621E9F35:
 UserID     : "Docker Release (CE rpm) <[email protected]>"
 Fingerprint: 060A61C51B558A7F742B77AAC52FEB6B621E9F35
 From       : https://download.docker.com/linux/fedora/gpg
The key was successfully imported.

Complete!

Step 5: Start and enable Docker

Enable the Docker service so it survives reboots and start it now:

sudo systemctl enable --now docker

Confirm the daemon is running:

sudo systemctl status docker --no-pager

The service should report active (running) with the docker.socket trigger:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Wed 2026-05-20 22:03:39 UTC; 17ms ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 8394 (dockerd)
      Tasks: 10
     Memory: 29.1M
     CGroup: /system.slice/docker.service
             └─8394 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Step 6: Verify the install

Check the engine, CLI, Compose plugin, and BuildKit versions:

sudo docker --version
sudo docker compose version
sudo docker buildx version

You should see all three versions printed back:

Docker version 29.5.2, build 79eb04c
Docker Compose version v5.1.4
github.com/docker/buildx v0.34.0 3e73561e39785683b31b05eeab1ef645be44ca42

Pull the key runtime details out of docker info to confirm storage, cgroup, and kernel are wired correctly:

sudo docker info | grep -E 'Server Version|Storage Driver|Cgroup Driver|Cgroup Version|Kernel Version|Operating System|Architecture'

On the test box the trimmed output looks like this:

 Server Version: 29.5.2
 Storage Driver: overlayfs
 Cgroup Driver: systemd
 Cgroup Version: 2
 Kernel Version: 7.0.8-200.fc44.x86_64
 Operating System: Fedora Linux 44 (Cloud Edition)
 Architecture: x86_64

The overlayfs storage driver replaced the older overlay2 default in Docker 25 and is faster on modern kernels. Cgroup v2 has been the Fedora default since Fedora 31, and Docker uses it cleanly with no extra configuration.

Here is the verification output captured on the test box, with the engine version, storage driver, cgroup driver, and kernel all confirmed in one glance:

Docker CE 29.5.2 docker info running on Fedora 44 kernel 7.0.8 with overlayfs and cgroup v2

Step 7: Run the hello-world container

The sanity check pulls a tiny image from Docker Hub and runs it. If networking, the daemon, and SELinux are all sane, the message prints:

sudo docker run --rm hello-world

The expected output (after the pull) ends with the Docker hello banner:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4f55086f7dd0: Pull complete
Digest: sha256:0e760fdfbc48ba8041e7c6db999bb40bfca508b4be580ac75d32c4e29d202ce1
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

Step 8: Run Docker as a non-root user

Typing sudo in front of every Docker command gets old fast. Add yourself to the docker group so the CLI can talk to the daemon socket directly:

sudo usermod -aG docker "${DOCKER_USER}"

Log out and back in (or run newgrp docker) so the new group membership takes effect for your shell. Confirm:

groups

The docker entry should be present at the end of the list:

jmutai adm wheel systemd-journal docker

From here on, the same commands run without sudo:

docker run --rm hello-world

One thing to be honest about: docker group membership is root-equivalent. Anyone in the group can mount the host filesystem inside a privileged container and escape to root. On shared machines, prefer rootless Docker (Step 11 below) or stick with Podman, which runs rootless by default.

Step 9: Run a Compose stack on Fedora

Multi-container apps are where Docker earns its keep over running individual containers. Build a tiny stack with Nginx fronting Redis:

mkdir -p "${COMPOSE_DIR}" && cd "${COMPOSE_DIR}"

Create the Compose file:

vi docker-compose.yml

Paste the following service definitions and save:

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    depends_on:
      - cache
  cache:
    image: redis:alpine

Bring the stack up in detached mode:

docker compose up -d

Compose creates the network, builds the dependency order, and starts both containers:

 Network compose-test_default     Created
 Container compose-test-cache-1   Started
 Container compose-test-web-1     Started

Both services should report Up with the published port mapped:

docker compose ps

The status table shows both services Up and the host-to-container port mapping on web:

NAME                   IMAGE          COMMAND                  SERVICE   CREATED         STATUS         PORTS
compose-test-cache-1   redis:alpine   "docker-entrypoint.s…"   cache     6 seconds ago   Up 3 seconds   6379/tcp
compose-test-web-1     nginx:alpine   "/docker-entrypoint.…"   web       4 seconds ago   Up 3 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp

Curl the Nginx default page to prove the network path works end-to-end:

curl -s http://localhost:8080 | head -5

The Nginx default page comes back through the published port:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

The stack output shows both services starting, the port mapping on web, and the live curl response from the Nginx default page:

Docker Compose v5.1.4 running a two-service nginx and redis stack on Fedora 44 with port 8080 mapped

Tear the stack down when you are done. The network and containers are removed; named volumes survive unless you add -v:

docker compose down

Step 10: SELinux and bind mounts on Fedora

Fedora runs SELinux in enforcing mode by default and Docker CE is shipped with policies that work with that. Confirm SELinux state:

getenforce

You should see Enforcing on every default Fedora install:

Enforcing

Plain Docker commands work as-is. The friction shows up with bind mounts: a host directory mounted into a container may not have the right SELinux label for the container process to read or write. Use the :z (shared) or :Z (private) volume flag and Docker relabels the directory on the fly:

mkdir -p ~/selinux-test
echo 'hello from host' > ~/selinux-test/test.txt
docker run --rm -v ~/selinux-test:/data:Z alpine cat /data/test.txt

The container reads the relabelled file without an AVC denial:

hello from host

Use :z (lowercase) when several containers need to share the directory. Use :Z (uppercase) when only this one container should access it. Never disable SELinux to “make Docker work”. If you hit a real AVC denial, check the audit log for what was blocked:

sudo ausearch -m AVC,USER_AVC -ts recent | tail

Step 11: Optional – run Docker rootless

The standard Docker setup runs the daemon as root. For desktops and shared hosts, rootless mode runs the daemon under your user account with no privileged group. The docker-ce-rootless-extras package is already installed as part of Step 4:

which dockerd-rootless-setuptool.sh
rpm -q docker-ce-rootless-extras

Both the setup tool and the rootless-extras package are in place:

/usr/bin/dockerd-rootless-setuptool.sh
docker-ce-rootless-extras-29.5.2-1.fc44.x86_64

Stop the system daemon first so the two do not fight over the same socket, then run the rootless setup as the unprivileged user:

sudo systemctl disable --now docker.service docker.socket
dockerd-rootless-setuptool.sh install

The script enables a user-level systemd unit and prints the environment variables to add to your shell rc. Rootless mode has known limits: no privileged ports under 1024 without extra setup, no host networking, slower overlay storage. For a workstation, the tradeoff is usually worth it.

Step 12: Tune the Docker daemon

By default, container logs grow without bound. On a long-running dev box, one chatty container can fill /var/lib/docker overnight. Set up log rotation and pick a private address pool that will not clash with your LAN.

Open the daemon config file (creates it if missing):

sudo mkdir -p /etc/docker
sudo vi /etc/docker/daemon.json

Add the following JSON. Adjust the address pool base if 172.20.x is already routed somewhere on your network:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "default-address-pools": [
    {"base": "172.20.0.0/16", "size": 24}
  ]
}

Restart Docker for the changes to load:

sudo systemctl restart docker

Confirm the daemon picked up the new values:

sudo docker info | grep -E 'Logging Driver|Default Address Pools' -A 2

The grepped slice reflects the new daemon settings:

 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
--
 Default Address Pools:
   Base: 172.20.0.0/16, Size: 24
 Firewall Backend: iptables

Step 13: Firewall and published ports

Docker manipulates iptables (or nftables via the iptables compat layer) directly for every published port. A container started with -p 8080:80 reaches the network without any manual firewall rule, because Docker punches the hole itself.

Fedora Cloud Edition ships without firewalld at all. Workstation and Server install it and run it by default. When firewalld is active and you want a non-Docker service on the host to reach a container, allow the port explicitly. For example, to expose port 8080 to other LAN hosts that ignore Docker’s iptables chains:

sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

The full set of firewalld zone, service, and rich-rule recipes is covered in Configure firewalld on Fedora.

Podman or Docker on Fedora

Fedora’s default container runtime is Podman, and the two coexist without trouble on the same host. Podman runs rootless by default, integrates with systemd via Quadlet, and uses the OCI image format that Docker also speaks. Pick Podman when you want rootless first, no daemon, or want to ship containers as systemd units.

Docker CE remains the better fit when your team already targets the Docker API, your CI scripts depend on the Docker CLI, you rely on BuildKit-only build features, or you orchestrate with Docker Swarm. For Compose specifically, Podman’s compose support is steadily catching up but Docker Compose v2 is still the more polished experience.

Troubleshooting

Error: unrecognized arguments: –add-repo

You used the DNF4 syntax on a DNF5 host. Fedora 43 and 44 ship DNF5, which expects addrepo --from-repofile= as a subcommand (no leading dashes). Re-run the Step 3 command exactly as shown.

Error: permission denied while trying to connect to the Docker daemon socket

Your shell session does not have the docker group membership yet. Run groups to confirm. If docker is missing, run sudo usermod -aG docker "${DOCKER_USER}" and start a fresh login session (full logout, not just a new terminal tab). If you cannot log out right now, newgrp docker spawns a sub-shell with the new group active.

Container cannot read files from a bind-mounted host directory

SELinux blocked the access because the host directory has a label that container processes are not allowed to read. Add :z (shared between containers) or :Z (private to this container) to the volume flag. Step 10 shows the exact pattern. Do not disable SELinux as a fix.

Docker fails to start after a Fedora upgrade

Old Docker packages from the Fedora base repos sometimes survive a system upgrade and conflict with Docker CE. Re-run the Step 2 removal, then reinstall Docker CE from Step 4. Check the failing service with journalctl -u docker -b --no-pager | tail -50 for the specific error.

Common Docker and Compose commands

A quick reference for the commands you will use day to day once Docker is up:

CommandWhat it does
docker psList running containers
docker ps -aList all containers, including stopped
docker imagesList local images
docker pull <image>Pull an image from the registry
docker run <image>Create and start a container
docker exec -it <ctr> bashOpen an interactive shell in a running container
docker logs -f <ctr>Follow container logs
docker stop <ctr>Stop a container gracefully
docker rm <ctr>Remove a stopped container
docker rmi <image>Remove an image
docker system pruneClean up stopped containers, dangling images, networks
docker compose up -dStart a Compose stack in the background
docker compose psShow stack containers and ports
docker compose logs -fTail logs across all services
docker compose downStop and remove the stack
docker compose down -vSame, and also remove named volumes

For the full Compose workflow with files, volumes, and overrides, see Install and Use Docker Compose on Fedora. To run your own container registry on Fedora, follow Install and Use Docker Registry on Fedora. For a web UI to manage containers, the Portainer setup guide takes you from zero to a working dashboard. Running on other distros is covered in our companion guides for Ubuntu, Debian, and Rocky Linux and AlmaLinux.

Related Articles

Fedora Installing Android Studio on Fedora 43/42/41 Docker Install Docker Compose on Linux Operating Systems Automation How To Install VMware PowerCLI Tools on macOS Docker Run Ubuntu Linux in Docker with Desktop Environment and VNC

Leave a Comment

Press ESC to close