Docker remains the de-facto standard for containerization, enabling consistent, portable, and scalable application deployment. On CentOS Stream (the active CentOS variant in 2026), Docker Engine installs cleanly from the official Docker CE repository, which provides the latest stable versions with security updates.
This guide targets production-oriented setups on CentOS Stream 9 or 10 (x86_64 / aarch64 supported). It follows the official Docker documentation (updated for Stream 10 support) while adding hardening, best practices, and troubleshooting tips relevant in 2026.
Prerequisites
- CentOS Stream 9 or 10 (minimal install recommended)
- 64-bit system with at least 2 GB RAM (4+ GB advised for production)
- Internet access for package downloads
- Non-root user with sudo privileges (or root)
- SELinux enforcing (default) – no need to disable it
Step 1: Update System & Remove Conflicting Packages
Old or third-party Docker installations (podman-docker, docker.io) can conflict.
sudo dnf update -y
sudo dnf remove docker docker-client docker-client-latest docker-common
docker-latest docker-latest-logrotate docker-logrotate docker-selinux
docker-engine-selinux docker-engine podman buildah -yStep 2: Install Required Utilities
These enable repository management.
sudo dnf install -y dnf-plugins-core device-mapper-persistent-data lvm2Step 3: Add the Official Docker CE Repository
This is the recommended method for receiving timely updates.
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoVerify the repo was added:
dnf repolist | grep dockerStep 4: Install Docker Engine, CLI, and Containerd
Install the latest stable versions:
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin- docker-ce → Docker daemon & engine
- docker-ce-cli → Command-line tool
- containerd.io → Container runtime (required since Docker 20.10+)
- Plugins → Buildx (advanced builds) & Compose v2 (recommended over legacy python compose)
If you want a specific version (e.g., for compatibility testing):
dnf list docker-ce --showduplicates | sort -r
sudo dnf install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.ioStep 5: Start, Enable, and Verify Docker
sudo systemctl enable --now docker
sudo systemctl status dockerCheck version and info:
docker --version
docker version
docker info --format '{{.ServerVersion}}'Step 6: Post-Installation Hardening & Best Practices
Add your user to the docker group (avoid sudo for every command)
Bashsudo usermod -aG docker $USER newgrp docker # or log out & back inTest: docker run hello-world
Configure Docker daemon (/etc/docker/daemon.json)
Create or edit the file for production tuning:
JSON{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "storage-driver": "overlay2", "icc": false, "userns-remap": "default", "live-restore": true }Restart: sudo systemctl restart docker
SELinux compatibility Docker works with SELinux enforcing. If you encounter labeling issues (rare in 2026), use :z or :Z on bind mounts (e.g., -v /host/path:/container/path:z).
Firewall integration Docker bypasses firewalld by default (iptables/nftables chains). For strict control:
- Use –iptables=false in daemon.json (advanced, breaks published ports)
- Or keep default and allow published ports explicitly in firewalld
Enable auto-updates Docker follows system package manager. Rely on dnf-automatic (security-only mode recommended) or watch Docker release notes.
Step 7: Install & Use Docker Compose (v2 – built-in)
The modern Compose plugin is already installed. Test:
docker compose versionExample docker-compose.yml for a simple app:
services:
web:
image: nginx:alpine
ports:
- "8080:80"Run: docker compose up -d
Troubleshooting Common Issues (2026)
- Repo metadata error → Clear cache: sudo dnf clean all && sudo dnf makecache
- containerd conflicts → Ensure no podman/containerd from AppStream is installed
- Permission denied on socket → Group membership or SELinux relabel (restorecon -Rv /var/run/docker.sock)
- IPv6 issues → Add “ipv6”: true, “fixed-cidr-v6”: “2001:db8:1::/64” to daemon.json if needed
Alternative: Podman (Native, Rootless Option)
If you prefer Red Hat’s daemonless, rootless alternative (compatible with most Docker commands/images):
sudo dnf install -y podman podman-docker-compose
alias docker=podman # optionalPodman is lighter and aligns better with SELinux defaults, but lacks some Docker-specific features (e.g., Swarm mode).
Summary
The official Docker CE repo method delivers a stable, up-to-date Docker setup on CentOS Stream with minimal friction. Prioritize user/group setup, log rotation, and SELinux-aware mounts for production reliability.
For container orchestration, consider moving to Kubernetes (via k3s/microk8s) or Podman + Quadlet once your workload grows.
Run docker run -d -p 80:80 nginx to confirm everything works — welcome to containerized CentOS! 🚀
Need help with rootless mode, Docker Buildx caching, or migrating from Podman? Let me know your use case.