在 openEuler 上从软件仓库安装 Docker CE

本文使用 Docker CE 的 CentOS 9 RPM 仓库在 openEuler 上安装 Docker Engine、Buildx 和 Docker Compose。安装完成后还会配置毫秒镜像,并用一个 Compose 项目验证容器和自定义网络能否在系统重启后自动恢复。

本文选择 CentOS 9 仓库,是因为 Docker 官方直接发布这一套 Enterprise Linux 9 RPM,同时提供 x86_64 和 aarch64 架构;固定版本路径也避免 openEuler 的 $releasever 被错误拼入 Docker 仓库地址。本轮四组实际安装均通过。Docker 没有把 openEuler 列为官方验证平台,因此这里属于兼容安装,而不是 Docker 对 openEuler 作出的支持承诺。可对照 Docker 官方 CentOS 安装文档Docker Engine 安装说明

本文已完成以下实际安装和重启测试:

  • openEuler 24.03 LTS SP3 x86_64,内核 6.6.0-145.3.27.158.20260826.b7db8e91096e.oe2403sp3.x86_64
  • openEuler 24.03 LTS SP3 aarch64,内核 6.6.0-132.0.0.111.oe2403sp3.aarch64
  • openEuler 22.03 LTS SP4 x86_64,内核 5.10.0-330.0.0.231.oe2203sp4.x86_64
  • openEuler 22.03 LTS SP4 aarch64,内核 5.10.0-216.0.0.115.oe2203sp4.aarch64

四组环境均安装了 Docker Engine 29.7.2 和 Docker Compose 5.5.0,通过了镜像拉取、Compose 启动、健康检查以及系统重启后的恢复验证。

已有 openEuler Moby 环境请从第 1 节开始准备仓库,并阅读第 3 节的迁移步骤;准备在新系统上直接安装的读者可以完成仓库配置后跳到第 4 节

1. 准备 Docker 仓库签名密钥

先更新系统并安装下载、验签工具:

sudo dnf upgrade -y
sudo dnf install -y curl gnupg2

下载 Docker 的 RPM 签名密钥。下面先尝试官方地址,失败后使用国内镜像中的同一文件:

INSTALL_DIR=$(mktemp -d)

curl -fL --connect-timeout 15 --max-time 120 \
  --retry 3 --retry-delay 2 --retry-all-errors \
  -o "${INSTALL_DIR}/RPM-GPG-KEY-Docker" \
  https://download.docker.com/linux/centos/gpg || \
curl -fL --connect-timeout 15 --max-time 120 \
  --retry 3 --retry-delay 2 --retry-all-errors \
  -o "${INSTALL_DIR}/RPM-GPG-KEY-Docker" \
  https://mirrors.aliyun.com/docker-ce/linux/centos/gpg

DOCKER_FINGERPRINT=$(
  gpg --show-keys --with-colons "${INSTALL_DIR}/RPM-GPG-KEY-Docker" |
    awk -F: '$1 == "fpr" { print $10; exit }'
)

test "$DOCKER_FINGERPRINT" = \
  060A61C51B558A7F742B77AAC52FEB6B621E9F35 || {
    echo "Docker GPG 密钥指纹不符:$DOCKER_FINGERPRINT" >&2
    exit 1
  }

echo "$DOCKER_FINGERPRINT"
sudo install -D -m 0644 "${INSTALL_DIR}/RPM-GPG-KEY-Docker" \
  /etc/pki/rpm-gpg/RPM-GPG-KEY-Docker
rm -rf "$INSTALL_DIR"

预期指纹为:

060A61C51B558A7F742B77AAC52FEB6B621E9F35

2. 配置国内镜像和官方源

下面把教育网联合镜像、阿里云、腾讯云和华为云写入本地 mirrorlist,同时保留 Docker 官方仓库作为 baseurl。RPM 签名仍由上一步固定的 Docker 官方密钥校验。

sudo install -d -m 0755 /etc/yum.repos.d/docker-ce-mirrorlists

sudo tee /etc/yum.repos.d/docker-ce-mirrorlists/stable >/dev/null <<'EOF'
https://mirrors.cernet.edu.cn/docker-ce/linux/centos/9/$basearch/stable/
https://mirrors.aliyun.com/docker-ce/linux/centos/9/$basearch/stable/
https://mirrors.tencent.com/docker-ce/linux/centos/9/$basearch/stable/
https://mirrors.huaweicloud.com/docker-ce/linux/centos/9/$basearch/stable/
EOF

sudo tee /etc/yum.repos.d/docker-ce.repo >/dev/null <<'EOF'
[docker-ce-stable]
name=Docker CE Stable for openEuler - $basearch
mirrorlist=file:///etc/yum.repos.d/docker-ce-mirrorlists/stable
baseurl=https://download.docker.com/linux/centos/9/$basearch/stable/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Docker
skip_if_unavailable=1
EOF

sudo dnf clean metadata
sudo dnf makecache --repo docker-ce-stable

这里显式使用 centos/9,不要换成包含 $releasever 的通用 CentOS repo 文件;openEuler 的发行版本号不是 Docker 仓库目录名。

3. 从发行版 Moby 迁移到 Docker CE

如果机器已经安装 openEuler 提供的 Moby,先完成前两节以准备 Docker CE 仓库,再按本节迁移。Moby 与 Docker CE 使用相同的命令名、systemd unit 和默认数据目录,这是一项软件包替换操作,不能当作普通的 dnf upgrade

先记录现有容器、网络和 Docker 数据目录:

sudo docker ps -a --no-trunc
sudo docker network ls --no-trunc
sudo docker volume ls

DOCKER_ROOT=$(sudo docker info --format '{{.DockerRootDir}}')
echo "$DOCKER_ROOT"
sudo du -sh "$DOCKER_ROOT"
df -h "$DOCKER_ROOT"

确认 Compose 文件、bind mount 中的数据及 Docker volume 都已有可用备份。下面的示例把 Docker 数据和配置复制到当前用户的家目录,适合数据量较小的测试机;重要主机应把 BACKUP_ROOT 改成另一块文件系统或使用存储快照,并先确认剩余空间。

Moby 的服务默认启用了 live restore,因此要先显式停止正在运行的容器,再停止 daemon:

sudo docker ps -q | xargs -r sudo docker stop
sudo systemctl stop docker.service docker.socket containerd.service

BACKUP_ROOT="$HOME"
BACKUP_DIR="${BACKUP_ROOT%/}/docker-before-ce-$(date +%Y%m%d-%H%M%S)"
sudo install -d -m 0700 "$BACKUP_DIR"
sudo cp -a --reflink=auto "$DOCKER_ROOT" "$BACKUP_DIR/"

if [ -d /var/lib/containerd ]; then
  sudo cp -a --reflink=auto /var/lib/containerd "$BACKUP_DIR/"
fi

if [ -d /etc/docker ]; then
  sudo cp -a --reflink=auto /etc/docker "$BACKUP_DIR/"
fi

if [ -f /etc/sysconfig/docker ]; then
  sudo cp -a --reflink=auto /etc/sysconfig/docker \
    "$BACKUP_DIR/docker.sysconfig"
fi

if [ -e /usr/local/lib/docker/cli-plugins/docker-compose ]; then
  sudo mv /usr/local/lib/docker/cli-plugins/docker-compose \
    "$BACKUP_DIR/docker-compose.manual"
fi

echo "备份目录:$BACKUP_DIR"

使用 dnf swap 在同一个 RPM 事务中完成 Moby 与 Docker CE 的替换:

sudo dnf swap moby docker-ce

提交前检查 DNF 给出的事务摘要。正常情况下,Moby、moby-engine、moby-client、libnetwork 以及发行版提供的 containerd、runc 会被 Docker CE、docker-ce-cli、containerd.io、Buildx 和 Compose 插件替换;如果摘要还要移除无关业务软件,应先取消事务并排查依赖。

替换完成后确认软件包版本:

rpm -q docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
docker --version
docker compose version

原有 /etc/docker/daemon.json 会保留,但 Moby 通过 systemd 和 /etc/sysconfig/docker 传入的参数不会自动成为 Docker CE 的服务配置。继续按第 5 节合并 daemon 配置,再按第 6 节启动服务。Docker 29 的全新安装通常使用 containerd image store;迁移时应先保留并确认现有存储后端,切换存储后端会使原有镜像和容器在当前视图中不可见。参见 Docker 的 containerd image store 说明

服务启动后,在每个原有 Compose 项目目录执行:

sudo docker compose up -d
sudo docker ps -a --no-trunc
sudo docker network ls --no-trunc

迁移前被显式停止且使用 restart: unless-stopped 的容器会保留“已手动停止”的状态,所以这里用 docker compose up -d 恢复项目。已有容器也会保留创建时选择的日志驱动;第 5 节设置的新默认值在重建容器后生效。

本轮分别验证了 dnf swap 可以在单个事务中完成软件包替换,以及相同最终软件包集合下实际 Moby 数据的迁移:原有容器 ID、network ID 和 overlay2 数据均得到保留,Compose 恢复、健康检查及系统重启验收通过。Docker 官方也说明卸载 RPM 不会自动删除镜像、容器、volume 或自定义配置;备份仍是处理版本跨度和异常回滚的必要前提。参见 Docker CentOS 安装文档live restore 说明volume 备份说明

完成本节后跳过下一节的全新安装命令,从第 5 节继续。

4. 全新安装 Docker CE

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

rpm -q docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
docker --version
docker compose version

Docker 的 RPM 按职责拆成了多个包:docker-ce 是 Engine 主包,并依赖 docker-ce-clicontainerd.io;当前仓库还以弱依赖方式推荐 Buildx、Compose 插件和 rootless extras。只安装 docker-ce 时,采用 DNF 默认配置也会自动带入这些组件。这里仍显式列出 CLI、containerd、Buildx 和 Compose,是为了固定本文实际使用和验证的功能集合,也让关闭了弱依赖自动安装的系统仍能获得 docker buildxdocker compose

5. 配置毫秒镜像与容器日志轮转

先检查配置文件是否已经存在:

if sudo test -e /etc/docker/daemon.json; then
  sudo cat /etc/docker/daemon.json
else
  echo "/etc/docker/daemon.json 尚未创建"
fi

如果文件尚未创建,可以使用以下配置:

sudo install -d -m 0755 /etc/docker

sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run"
  ],
  "log-driver": "local",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF

sudo dockerd --validate --config-file=/etc/docker/daemon.json

如果文件已经存在,应编辑原文件并合并上述选项,随后再运行 dockerd --validate,以免覆盖已有设置。registry-mirrors 用于镜像拉取,local 日志驱动和轮转参数可避免容器日志持续占用磁盘。参考 Registry mirrorConfigure logging drivers

6. 启动 Docker 并配置用户权限

sudo systemctl enable --now docker
sudo systemctl --no-pager --full status docker

sudo docker info \
  --format 'Storage={{.Driver}} Logging={{.LoggingDriver}} Mirrors={{json .RegistryConfig.Mirrors}}'

sudo groupadd --force docker
sudo usermod -aG docker "$USER"

docker 组成员实际上可以取得 root 级主机权限,只应加入可信用户。退出当前会话并重新登录后,组成员变更才会完整生效;在此之前可以暂时使用 sudo docker ...。参考 Docker 的安装后配置说明

7. 用 Compose 验证容器与网络

下面创建一个只监听本机 127.0.0.1:8080 的 Nginx 服务:

sudo install -d -m 0755 /opt/compose/oe-docker-ce-demo
sudo chown "$USER":"$(id -gn)" /opt/compose/oe-docker-ce-demo

cat >/opt/compose/oe-docker-ce-demo/compose.yaml <<'EOF'
name: oe-docker-ce-demo

services:
  web:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    networks:
      - app
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/ >/dev/null || exit 1"]
      interval: 5s
      timeout: 3s
      retries: 12

networks:
  app:
    name: oe-docker-ce-demo-net
EOF

cd /opt/compose/oe-docker-ce-demo
docker compose config -q
docker compose up -d
docker compose ps
docker network inspect oe-docker-ce-demo-net
curl -fsS http://127.0.0.1:8080/ | grep 'Welcome to nginx'

如果刚加入 docker 组后仍提示 socket 权限不足,请退出当前会话并重新登录,再执行本节命令。

8. 做一次重启验收

先记录当前容器和网络 ID:

docker inspect oe-docker-ce-demo-web-1 \
  --format 'container={{.Id}} restart={{.HostConfig.RestartPolicy.Name}}'
docker network inspect oe-docker-ce-demo-net \
  --format 'network={{.Id}} containers={{len .Containers}}'

重启系统:

sudo reboot

重新登录后验证:

systemctl is-enabled docker
systemctl is-active docker

cd /opt/compose/oe-docker-ce-demo
docker compose ps
docker network inspect oe-docker-ce-demo-net \
  --format 'network={{.Id}} containers={{len .Containers}}'
docker inspect oe-docker-ce-demo-web-1 \
  --format 'status={{.State.Status}} health={{.State.Health.Status}} restart={{.HostConfig.RestartPolicy.Name}}'
curl -fsS http://127.0.0.1:8080/ | grep 'Welcome to nginx'

预期结果是 Docker 为 enabledactiveoe-docker-ce-demo-net 仍包含一个容器,oe-docker-ce-demo-web-1runninghealthy,本机访问 127.0.0.1:8080 仍返回 Nginx 页面。四组实测环境在重启前后取得了相同的容器 ID 和 network ID。

9. 日常更新与检查

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

systemctl status docker
journalctl -b -u docker --no-pager
docker info
docker compose ls

Docker CE 使用独立仓库更新。大版本升级前应阅读 Docker 发布说明,并确认现有容器、存储驱动和 Compose 项目与新版本兼容。

10. 安装时可能出现的 SELinux 提示

在本次两组 x86_64、SELinux Enforcing 环境中,RPM 安装脚本输出过以下警告:

warning: could not load docker-af-alg-deny.cil SELinux policy; AF_ALG SELinux denial is not active

该提示没有中止 RPM 事务,之后的 Docker 启动、镜像拉取、Compose、自定义网络和重启恢复测试均通过。它指向的是 AF_ALG 对应的附加拒绝规则未载入,并不表示整个 container-selinux policy 都没有安装。

四组测试系统当前均以 cgroup v1 启动。Docker Engine 29.7.2 会提示 cgroup v1 已经弃用并计划移除,但本文的运行、联网和重启恢复测试均正常;以后跨大版本升级 Engine 时,应重新验证主机的 cgroup 配置。