If you need to manually choose a Docker Engine version, you can directly install the static binary released by Docker and manage the service via systemd. This tutorial also installs the Compose plugin and runs a small project.
The programs installed this way are not managed by RPM, and future updates must be handled manually. If you prefer to have installation and updates managed by DNF, consider installing Docker CE via the software repository; if you want to use a distribution-maintained engine, consider Moby.
1. Check if Docker is Already Installed
type -a docker dockerd
rpm -q docker-ce moby docker-engine podman-docker
It’s normal for new systems to report that commands or packages do not exist. If Docker is already running, first plan the migration of existing containers, data, and configurations—do not directly overwrite binaries or service files. Below, we assume Docker is not yet installed and proceed with a regular user having sudo privileges:
sudo dnf install curl tar iptables procps-ng xz
2. Download and Install Docker Engine
We’ll use Docker Engine 29.8.1 as an example, which supports both x86_64 and aarch64. For other versions, refer to the official static package directory:
mkdir -p "$HOME/docker-install"
cd "$HOME/docker-install"
ARCH=$(uname -m)
DOCKER_VERSION=29.8.1
DOCKER_TGZ="docker-${DOCKER_VERSION}.tgz"
DOCKER_BASE=https://download.docker.com/linux/static/stable
curl -fL -o "$DOCKER_TGZ" \
"${DOCKER_BASE}/${ARCH}/${DOCKER_TGZ}"
tar -xzf "$DOCKER_TGZ"
sudo install -m 0755 docker/* /usr/local/bin/
/usr/local/bin/docker --version
/usr/local/bin/dockerd --version
If the official URL is unreachable, see the download instructions below—just change the download prefix and retry. The installation directory includes dockerd, the client, and supporting tools like containerd and runc. There’s no need to separately install the distribution’s containerd.
3. Create and Start the Service
First, create the user group used by the Docker socket. For now, don’t add your user to this group—use sudo docker for all commands:
sudo groupadd --force docker
The static package does not include a ready-to-install systemd service file. Confirm there is no existing /etc/systemd/system/docker.service, then create it:
sudo tee /etc/systemd/system/docker.service > /dev/null <<'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
ExecStart=/usr/local/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
Restart=always
RestartSec=2
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now docker
sudo docker version
docker version should show both Client and Server versions. If the service fails to start, check the logs with sudo journalctl -b -u docker --no-pager -n 100 to diagnose the issue.
4. Install the Compose Plugin
Run sudo docker compose version first—skip this section if the plugin is already available. The Docker Engine .tgz does not include Compose; it must be downloaded separately. Here we use Compose 5.5.1 as an example:
cd "$HOME/docker-install"
COMPOSE_VERSION=v5.5.1
COMPOSE_FILE="docker-compose-linux-${ARCH}"
COMPOSE_BASE=https://github.com/docker/compose/releases/download
curl -fL -o "$COMPOSE_FILE" \
"${COMPOSE_BASE}/${COMPOSE_VERSION}/${COMPOSE_FILE}"
curl -fL -o "${COMPOSE_FILE}.sha256" \
"${COMPOSE_BASE}/${COMPOSE_VERSION}/${COMPOSE_FILE}.sha256"
sha256sum -c "${COMPOSE_FILE}.sha256"
sudo install -D -m 0755 "$COMPOSE_FILE" \
/usr/local/lib/docker/cli-plugins/docker-compose
sudo docker compose version
When changing versions, confirm the architecture and filename from Compose Releases to ensure the binary and checksum match the same version.
5. Run a Compose Project
If you already have a project, follow its instructions in the directory containing compose.yaml. Below is an example using a minimal Nginx service that listens only on localhost:
mkdir -p "$HOME/docker-static-demo"
cd "$HOME/docker-static-demo"
cat > compose.yaml <<'EOF'
services:
web:
image: nginx:stable
ports:
- "127.0.0.1:8080:80"
restart: unless-stopped
EOF
sudo docker compose up -d
sudo docker compose ps
curl -f http://127.0.0.1:8080/
Once the container runs and returns the Nginx welcome page, the installation is complete. If image pulling times out, refer to the image or daemon proxy instructions below and retry docker compose up -d.
curl must be run on the machine where Docker is running—other machines cannot access this loopback address directly. Compose automatically creates a project network; restart: unless-stopped ensures containers restart with Docker unless manually stopped, so no additional persistent service is needed for Compose.
When you no longer need the example, run sudo docker compose down in the project directory. You can verify container recovery during future maintenance restarts—no need to reboot the host immediately after the tutorial.
Common Requirements and Issues
Container Shows Up, But Service Is Unreachable
Run sudo docker compose logs --tail=50 web in the project directory to check if the application has started. “Up” only means the container process is running—not that the application is ready. For example, some Alpine-based Nginx images may access the Alpine repository during the entry script, which is unaffected by Docker Hub mirror settings. This guide uses nginx:stable, based on Debian.
Slow, Failed, or 404 Downloads for Docker Static Package
If you have a working HTTP proxy, set it in your terminal:
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
The address should be accessible from your current machine. When using SSH, 127.0.0.1 refers to the server itself. These variables also apply to later Compose downloads.
Alternatively, use a domestic Docker CE mirror. For example, change the download prefix:
DOCKER_BASE=https://mirrors.cernet.edu.cn/docker-ce/linux/static/stable
curl -fL -o "$DOCKER_TGZ" \
"${DOCKER_BASE}/${ARCH}/${DOCKER_TGZ}"
After successful download, proceed with extraction and installation. The following mirrors also provide the same directory structure—choose based on your network:
- Tsinghua University TUNA:
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/static/stable - Alibaba Cloud:
https://mirrors.aliyun.com/docker-ce/linux/static/stable - Tencent Cloud:
https://mirrors.tencent.com/docker-ce/linux/static/stable - Huawei Cloud:
https://mirrors.huaweicloud.com/docker-ce/linux/static/stable
A 404 error usually indicates a mismatch in version, architecture, or missing sync of the file. Repeatedly retrying an invalid URL won’t help. Do not use CentOS RPM download paths for static packages.
Compose Fails to Download from GitHub
In addition to terminal proxy settings, you can use a trusted GitHub URL prefix accelerator, such as:
COMPOSE_BASE=https://gh-proxy.com/https://github.com/docker/compose/releases/download
Then run the two Compose download commands above. After successful verification, install. Both the binary and .sha256 file must be downloaded. URL prefix services are third-party and not HTTP proxies—do not set them in https_proxy.
Installed Successfully, But Image Pull Fails
The static package, Compose plugin, and container images are three separate downloads. Changing the first two’s download sources does not affect access to Docker Hub.
To use a trusted Docker Hub mirror, add it to /etc/docker/daemon.json:
{
"registry-mirrors": ["https://docker.1ms.run"]
}
Create the directory first if it doesn’t exist: sudo install -d -m 0755 /etc/docker. Then edit with sudoedit /etc/docker/daemon.json. If the file already exists, merge the registry-mirrors field—do not overwrite existing config. Afterward, restart the service at an appropriate time:
sudo /usr/local/bin/dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker
sudo docker info --format '{{json .RegistryConfig.Mirrors}}'
Public mirror availability and coverage may change. If your chosen service remains slow, consider switching to https://docker.m.daocloud.io as described in DaoCloud’s guide. These mirrors do not automatically proxy other registries. Registry mirror documentation
If you want to pull images through an existing HTTP proxy, configure the proxy for the background dockerd. Terminal variables are not automatically passed to systemd services. Run sudo systemctl edit docker and add:
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
Replace the proxy address with one reachable by the Docker host. Then run sudo systemctl daemon-reload and sudo systemctl restart docker, and retry pulling. Internal registries can be added to NO_PROXY. Use sudo systemctl show --property=Environment docker to check settings. If daemon.json already has proxies, it takes precedence—adjust it there. Daemon proxy documentation
Permissions, Logs, and Runtime Isolation
To use Docker without sudo, run sudo usermod -aG docker "$USER", then log out and back in. The docker group has root-equivalent privileges—only add trusted users. This is different from rootless Docker. Permissions documentation
Check service and container status with:
sudo journalctl -b -u docker --no-pager -n 100
sudo docker info
sudo docker compose ps
For long-running setups, set up log rotation. For example, merge "log-driver": "local" into daemon.json. After restarting the service, new containers will use the local log driver with rotation. Existing containers must be rebuilt according to your project plan to adopt the new default. Log driver documentation
The static package does not include SELinux policies from RPM installation paths, nor does it automatically enable SELinux container isolation. Host enforcing mode does not imply container enforcement. If isolation is required, configure policies and daemon options manually and verify via docker info under Security Options. Do not disable host SELinux just to start the service. Official static install guide
How to Update
First, read the Docker release notes. Back up your data and configurations, and schedule downtime. Stop containers and Docker, download the new .tgz, replace the files in /usr/local/bin/ with those from the new package, then restart Docker and your projects. If live restore was enabled, confirm old container processes have stopped.
Compose is a standalone client plugin—update it by downloading the new version and replacing the binary using the steps above. dnf upgrade will not update the Engine or Compose installed this way. When upgrading across major versions, also check compatibility with kernel, cgroup, and storage backend requirements.
Verification: This installation method has been tested on openEuler 22.03 LTS SP4 and 24.03 LTS SP3 (x86_64/aarch64) via static install, Compose, and restart. This update was re-verified on 24.03 LTS SP3 x86_64 with Engine 29.8.1, Compose 5.5.1, and the simplified flow. Revision date: 2026-09-20