一、导读

环境:openEuler 22.03、Linux 5.10、docker 25.0.0、VMware 17

背景:需要离线部署,而且需要docker compose

时间:20260903

说明:最终实现离线安装可用,一键安装脚本,普通用户需要sudo,超管直接执行,选择25版本的原因的兼容性

二、安装过程

1、离线包下载

注意:本机基于amd64

https://download.docker.com/linux/static/stable/aarch64/docker-25.0.0.tgz

https://download.docker.com/linux/static/stable/x86_64/docker-25.0.0.tgz

下载后上传到服务器

[jack@localhost ~]$ ls
docker-25.0.0.tgz

2、解压下载的包

[jack@localhost ~]$ tar xzf docker-25.0.0.tgz 
[jack@localhost ~]$ ls
docker  docker-25.0.0.tgz
[jack@localhost ~]$ ls -l docker
总用量 187500
-rwxr-xr-x. 1 jack jack 39063552  1月 19  2024 containerd
-rwxr-xr-x. 1 jack jack 12390400  1月 19  2024 containerd-shim-runc-v2
-rwxr-xr-x. 1 jack jack 19247104  1月 19  2024 ctr
-rwxr-xr-x. 1 jack jack 35638208  1月 19  2024 docker
-rwxr-xr-x. 1 jack jack 67710472  1月 19  2024 dockerd
-rwxr-xr-x. 1 jack jack   708448  1月 19  2024 docker-init
-rwxr-xr-x. 1 jack jack  1979942  1月 19  2024 docker-proxy
-rwxr-xr-x. 1 jack jack 15256760  1月 19  2024 runc

3、 复制可执行文件

# 查看PATH
[jack@localhost ~]$ echo $PATH
/home/jack/.local/bin:/home/jack/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
# 复制可执行文件到目录
[jack@localhost ~]$ sudo cp docker/* /usr/bin/
[sudo] jack 的密码:
[jack@localhost ~]$ docker -v
Docker version 25.0.0, build e758fe5
[jack@localhost ~]$ sudo docker ps
[sudo] jack 的密码:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

此时功能并不完整,但是可以查看版本

4、编辑配置文件

docker的service文件内容,基于docker官方推荐

#  /etc/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

该文件的作用是实现使用systemctl进行管理
指定docker配置信息,比如:镜像地址、日志、根目录等

# /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.ccs.tencentyun.com"
  ],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "data-root": "/data/docker",
  "log-driver": "json-file",
  "log-level": "warn",
  "log-opts": {
    "max-size": "50m",
    "max-file": "1"
  },
  "dns": ["8.8.8.8", "114.114.114.114"]
}

由于根目录指向/data,所以创建

sudo mkdir -p /data/docker
sudo mkdir -p /etc/docker

确认文件就位

[jack@localhost ~]$ ls -ld /data/docker
drwxr-xr-x. 2 root root 4096  9月  2 14:41 /data/docker
[jack@localhost ~]$ ls -l /etc/docker/daemon.json 
-rw-r--r--. 1 root root 387  9月  2 14:42 /etc/docker/daemon.json
[jack@localhost ~]$ ls -l /etc/systemd/system/docker.service 
-rw-r--r--. 1 root root 441  9月  2 14:43 /etc/systemd/system/docker.service

5、启动服务并测试

[jack@localhost ~]$ sudo systemctl status docker
○ docker.service - Docker Application Container Engine
     Loaded: loaded (/etc/systemd/system/docker.service; disabled; vendor preset: disabled)
     Active: inactive (dead)
       Docs: https://docs.docker.com
[jack@localhost ~]$ sudo systemctl start docker
[jack@localhost ~]$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/etc/systemd/system/docker.service; disabled; vendor preset: disabled)
     Active: active (running) since Wed 2026-09-02 14:47:43 CST; 4s ago
       Docs: https://docs.docker.com
   Main PID: 2084 (dockerd)
      Tasks: 17 (limit: 21420)
     Memory: 32.8M
     CGroup: /system.slice/docker.service
             ├─2084 /usr/bin/dockerd
             └─2091 containerd --config /var/run/docker/containerd/containerd.toml --log-level warn

9月 02 14:47:42 localhost.localdomain systemd[1]: Starting Docker Application Container Engine...
9月 02 14:47:42 localhost.localdomain dockerd[2084]: time="2026-09-02T14:47:42.331573716+08:00" level=warning msg="could not change group /var/run/docker.sock to docker: group docker not found"
9月 02 14:47:42 localhost.localdomain dockerd[2091]: time="2026-09-02T14:47:42.386621711+08:00" level=warning msg="failed to load plugin io.containerd.snapshotter.v1.devmapper" error="devmapper not configured"
9月 02 14:47:42 localhost.localdomain dockerd[2091]: time="2026-09-02T14:47:42.391588170+08:00" level=warning msg="could not use snapshotter devmapper in metadata plugin" error="devmapper not configured"
9月 02 14:47:43 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
[jack@localhost ~]$ sudo docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

启动成功


三、配置普通用户可用

此时,普通用户无法使用,需要使用sudo,如下:

[jack@localhost ~]$ docker -v
Docker version 25.0.0, build e758fe5
[jack@localhost ~]$ docker ps
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied

授权命令

# 对当前用户授权,此处特指普通用户
sudo usermod -aG docker $USER

用户对比授权后的变动

[jack@localhost ~]$ sudo groupadd docker
[sudo] jack 的密码:
[jack@localhost ~]$ sudo cat /etc/group | grep docker
docker:x:1001:
[jack@localhost ~]$ sudo cat /etc/group | grep $USER
wheel:x:10:jack
jack:x:1000:
# 授权前 --------------
[jack@localhost ~]$ sudo usermod -aG docker $USER
# 授权后 --------------
[jack@localhost ~]$ sudo cat /etc/group | grep $USER
wheel:x:10:jack
jack:x:1000:
docker:x:1001:jack
[jack@localhost ~]$ sudo cat /etc/group | grep docker
docker:x:1001:jack
[jack@localhost ~]$ 

重启,打开新的终端

[jack@localhost ~]$ docker ps
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied
[jack@localhost ~]$ sudo systemctl restart docker
[jack@localhost ~]$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

四、配置containerd服务

此处仅仅为方便使用systemctl来管理containerd服务,单纯docker而言,配置与否不重要

1、配置文件编写

# /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

2、重启containerd服务

sudo systemctl restart containerd

五、一键脚本实现

1、文件准备

.

├── docker/                       # docker-25.0.0.tgz 解压后的静态二进制

│   ├── containerd                # 容器运行时

│   ├── containerd-shim-runc-v2   # containerd 与 runc 之间的 shim

│   ├── ctr                       # containerd 命令行工具

│   ├── docker                    # Docker CLI 客户端

│   ├── docker-init               # 容器 init 进程(tini)

│   ├── docker-proxy              # 端口映射代理

│   ├── dockerd                   # Docker 守护进程

│   └── runc                      # OCI 运行时

├── containerd.service            # containerd 的 systemd 单元

├── docker.service                # docker 的 systemd 单元

├── daemon.json                   # Docker 守护进程配置(镜像加速、数据目录等)

├── install.sh                    # ★ 一键部署脚本

└── README.md                     # 本说明文档

2、脚本实现

#!/usr/bin/env bash
#
# Docker 25.0.0 静态二进制一键部署脚本
#
# 支持两种部署方式:
#   1) root 用户直接执行:      sudo 免开 -> ./install.sh   (当前已是 root)
#   2) 普通用户通过 sudo 执行:  sudo ./install.sh
#
# 详细说明见 README.md。
#
set -euo pipefail

# ---------------------------------------------------------------------------
# 路径解析:脚本所在目录即部署包根目录
# ---------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BIN_DIR="${SCRIPT_DIR}/docker"
CONTAINERD_UNIT="${SCRIPT_DIR}/containerd.service"
DOCKER_UNIT="${SCRIPT_DIR}/docker.service"
DAEMON_JSON="${SCRIPT_DIR}/daemon.json"

# 需要安装到 /usr/bin 的静态二进制文件名
BINARIES=(
  containerd
  containerd-shim-runc-v2
  ctr
  docker
  docker-init
  docker-proxy
  dockerd
  runc
)

# ---------------------------------------------------------------------------
# 日志辅助函数
# ---------------------------------------------------------------------------
info() { printf '\033[1;34m[INFO]\033[0m  %s\n' "$*"; }
ok()   { printf '\033[1;32m[ OK ]\033[0m  %s\n' "$*"; }
warn() { printf '\033[1;33m[WARN]\033[0m  %s\n' "$*"; }
err()  { printf '\033[1;31m[FAIL]\033[0m  %s\n' "$*" >&2; }

die() { err "$*"; exit 1; }

# ---------------------------------------------------------------------------
# 提权:若非 root,则自动通过 sudo / su 重新执行本脚本
# 这样脚本内部所有操作都以 root 权限进行,普通用户只需 sudo ./install.sh
# ---------------------------------------------------------------------------
elevate_if_needed() {
  [ "$(id -u)" -eq 0 ] && return 0

  # 提权后 sudo 会自动设置 SUDO_USER,供后续加入 docker 组使用
  if command -v sudo >/dev/null 2>&1; then
    warn "当前非 root,正在通过 sudo 重新以管理员权限执行..."
    exec sudo bash "$0" "$@"
  elif command -v su >/dev/null 2>&1; then
    warn "当前非 root,未找到 sudo,尝试通过 su 提权..."
    exec su - root -c "bash '$0' $(printf "%s " "$@")"
  else
    die "当前用户无 root 权限,且系统未安装 sudo/su,无法部署。"
  fi
}

# ---------------------------------------------------------------------------
# 前置检查
# ---------------------------------------------------------------------------
preflight_checks() {
  info "执行前置检查..."

  # 必须是 systemd 系统
  command -v systemctl >/dev/null 2>&1 \
    || die "未检测到 systemctl,本脚本仅支持基于 systemd 的 Linux 发行版。"

  # 校验必要的部署文件是否存在
  [ -d "$BIN_DIR" ] || die "未找到二进制目录:$BIN_DIR"
  [ -f "$CONTAINERD_UNIT" ] || die "未找到 $CONTAINERD_UNIT"
  [ -f "$DOCKER_UNIT" ] || die "未找到 $DOCKER_UNIT"
  [ -f "$DAEMON_JSON" ] || die "未找到 $DAEMON_JSON"

  local bin
  for bin in "${BINARIES[@]}"; do
    [ -f "${BIN_DIR}/${bin}" ] || die "缺少二进制文件:${BIN_DIR}/${bin}"
  done

  ok "前置检查通过。"
}

# ---------------------------------------------------------------------------
# 安装二进制(顺便修复执行权限,防止跨平台拷贝丢失权限位)
# ---------------------------------------------------------------------------
install_binaries() {
  info "安装 Docker 二进制到 /usr/bin ..."
  local bin
  for bin in "${BINARIES[@]}"; do
    install -m 0755 "${BIN_DIR}/${bin}" "/usr/bin/${bin}"
    ok "已安装 ${bin}"
  done
}

# ---------------------------------------------------------------------------
# 安装 systemd service 单元
# ---------------------------------------------------------------------------
install_units() {
  info "安装 systemd 服务单元..."
  install -m 0644 "$CONTAINERD_UNIT" /etc/systemd/system/containerd.service
  install -m 0644 "$DOCKER_UNIT"     /etc/systemd/system/docker.service
  ok "已安装 containerd.service / docker.service"
}

# ---------------------------------------------------------------------------
# 安装 daemon.json(若已存在则备份,不直接覆盖)
# ---------------------------------------------------------------------------
install_daemon_config() {
  info "准备 Docker 数据目录与配置文件..."

  # daemon.json 中 data-root 为 /data/docker,提前创建
  mkdir -p /data/docker
  mkdir -p /etc/docker

  local target="/etc/docker/daemon.json"
  if [ -f "$target" ]; then
    local backup="${target}.bak.$(date +%Y%m%d%H%M%S)"
    cp -a "$target" "$backup"
    warn "已存在 ${target},备份为 ${backup}"
  fi
  install -m 0644 "$DAEMON_JSON" "$target"
  ok "已写入 ${target}"
}

# ---------------------------------------------------------------------------
# 创建 docker 用户组
# ---------------------------------------------------------------------------
create_docker_group() {
  if getent group docker >/dev/null 2>&1; then
    ok "docker 组已存在。"
  else
    groupadd docker
    ok "已创建 docker 用户组。"
  fi
}

# ---------------------------------------------------------------------------
# 启动服务并设置开机自启
# ---------------------------------------------------------------------------
start_services() {
  info "加载 systemd 配置并启动服务..."
  systemctl daemon-reload
  systemctl enable --now containerd
  systemctl enable --now docker
  ok "containerd / docker 服务已启动。"
}

# ---------------------------------------------------------------------------
# 将原始调用用户加入 docker 组(使其无需 sudo 即可使用 docker)
# ---------------------------------------------------------------------------
add_user_to_group() {
  local target_user="${SUDO_USER:-}"

  if [ -z "$target_user" ] || [ "$target_user" = "root" ]; then
    info "以 root 直接部署,跳过将普通用户加入 docker 组的步骤。"
    return 0
  fi

  if id -nG "$target_user" 2>/dev/null | grep -qw docker; then
    ok "用户 ${target_user} 已在 docker 组中。"
  else
    usermod -aG docker "$target_user"
    ok "已将用户 ${target_user} 加入 docker 组(需重新登录生效)。"
  fi
}

# ---------------------------------------------------------------------------
# 安装结果验证
# ---------------------------------------------------------------------------
verify() {
  info "验证安装结果..."

  if docker version >/dev/null 2>&1; then
    ok "docker 命令可用,版本信息:"
    docker --version || true
  else
    warn "docker version 校验失败,可能是服务尚未就绪或权限未生效。"
  fi

  if systemctl is-active --quiet docker; then
    ok "docker 服务正在运行。"
  else
    warn "docker 服务未处于 active 状态,请执行:systemctl status docker 查看日志。"
  fi
}

# ---------------------------------------------------------------------------
# 主流程
# ---------------------------------------------------------------------------
main() {
  info "======== 开始部署 Docker 25.0.0 (静态二进制) ========"
  elevate_if_needed "$@"
  preflight_checks
  install_binaries
  install_units
  install_daemon_config
  create_docker_group
  start_services
  add_user_to_group
  verify

  echo
  ok "======== Docker 部署完成! ========"
  echo
  info "后续建议:"
  echo "  - 若以普通用户通过 sudo 部署,请重新登录(或执行 newgrp docker)后再使用 docker。"
  echo "  - 验证命令:docker run --rm hello-world"
  echo "  - 服务管理:sudo systemctl {start|stop|restart|status} docker"
}

main "$@"

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐