#!/bin/bash
Docker 二进制包安装脚本(最终修复版)
作者:Doubao
日期:2025-07-19
颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # 无颜色
定义变量
DOCKER_VERSION="28.3.2"
PACKAGE_DIR="/opt/docker-packages" # 安装包目录
PACKAGE_PATH="PACKAGE_DIR/docker-DOCKER_VERSION.tgz" # 安装包路径
EXTRACT_DIR="/tmp/docker-install" # 解压目录
LOG_FILE="/var/log/docker_install.log"
日志函数
log() {
local message="$1"
local level="$2"
if [ -z "$level" ]; then
level="INFO"
fi
echo "[(date '+%Y-%m-%d %H:%M:%S')\] \[level] message" \| tee -a "LOG_FILE"
}
错误处理函数
error() {
log "$1" "ERROR"
echo -e "{RED}错误: 1${NC}" >&2
exit 1
}
检查是否为 root 用户
check_root() {
if [ "$(id -u)" -ne 0 ]; then
error "请使用 root 用户执行此脚本"
fi
}
检查系统架构
check_arch() {
local arch=$(uname -m)
if [ "$arch" != "aarch64" ]; then
error "此脚本仅适用于 aarch64 架构,当前架构为 $arch"
fi
log "系统架构检查通过: $arch"
}
检查安装包
check_package() {
if [ ! -d "$PACKAGE_DIR" ]; then
error "安装包目录 $PACKAGE_DIR 不存在"
fi
if [ ! -f "$PACKAGE_PATH" ]; then
尝试查找匹配的包
local found_pkg=(ls "PACKAGE_DIR"/docker-*.tgz 2>/dev/null | head -1)
if [ -n "$found_pkg" ]; then
log "未找到 PACKAGE_PATH,但发现匹配的包: found_pkg"
PACKAGE_PATH="$found_pkg"
DOCKER_VERSION=(basename "found_pkg" | sed 's/docker-//' | sed 's/.tgz//')
log "自动检测到 Docker 版本: $DOCKER_VERSION"
else
error "安装包 $PACKAGE_PATH 不存在,且未找到匹配的 docker-*.tgz 文件"
fi
fi
验证文件类型
local file_type=(file -b "PACKAGE_PATH")
if ! echo "$file_type" | grep -q "gzip compressed data"; then
error "安装包 $PACKAGE_PATH 不是有效的 gzip 压缩文件"
fi
log "安装包检查通过"
}
卸载旧版本
uninstall_old() {
log "卸载旧版本 Docker..."
停止运行中的 Docker 服务
systemctl stop docker.service docker.socket || true
卸载旧版本
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
docker-ce || true
移除残留文件和符号链接
log "移除旧版 Docker 二进制文件和符号链接..."
rm -f /usr/bin/docker* /usr/bin/containerd* /usr/bin/runc /usr/bin/ctr || true
log "旧版本 Docker 卸载完成"
}
解压安装包
extract_package() {
log "解压安装包..."
创建解压目录
mkdir -p "$EXTRACT_DIR"
rm -rf "$EXTRACT_DIR"/*
解压
tar -xzf "PACKAGE_PATH" -C "EXTRACT_DIR" || error "解压安装包失败"
检查解压结果
if [ ! -d "$EXTRACT_DIR/docker" ]; then
error "解压后未找到 docker 目录"
fi
log "安装包解压完成"
}
安装 Docker
install_docker() {
log "开始安装 Docker $DOCKER_VERSION..."
移除目标目录中可能存在的符号链接
log "移除 /usr/bin 目录下的 Docker 相关符号链接..."
rm -f /usr/bin/docker /usr/bin/docker-init /usr/bin/docker-proxy /usr/bin/dockerd \
/usr/bin/containerd /usr/bin/containerd-shim /usr/bin/containerd-shim-runc-v2 \
/usr/bin/ctr /usr/bin/runc || true
复制二进制文件到 /usr/bin
log "复制 Docker 二进制文件..."
cp -f "$EXTRACT_DIR/docker"/* /usr/bin/ || error "复制 Docker 二进制文件失败"
验证安装
log "验证 Docker 安装..."
if ! docker --version >/dev/null 2>&1; then
error "Docker 安装失败,无法获取版本信息"
fi
log "Docker 版本: $(docker --version)"
创建必要的目录
mkdir -p /etc/docker /var/lib/docker
log "Docker 安装完成"
}
配置 Docker 服务
configure_docker_service() {
log "配置 Docker 服务..."
创建 systemd 服务文件
cat > /etc/systemd/system/docker.service << EOF
Unit
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=containerd.service
Service
Type=notify
the default is not to use systemd for cgroups because the delegate issues still
exists and systemd currently does not support the cgroup feature set required
for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP \$MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
Both the old, and new location are accepted by systemd 229 and up, so using the old location
to make them work for either version of systemd.
StartLimitBurst=3
Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
this option work for either version of systemd.
StartLimitInterval=60s
Having non-zero Limit*s causes performance problems due to accounting overhead
in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Comment TasksMax if your systemd version does not support it.
Only systemd 226 and above support this option.
TasksMax=infinity
set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500
Install
WantedBy=multi-user.target
EOF
重载 systemd
systemctl daemon-reload
启动 Docker 并设置开机自启
log "启动 Docker 服务..."
systemctl enable --now docker
验证 Docker 服务状态
if ! systemctl is-active docker >/dev/null 2>&1; then
error "Docker 服务未启动"
fi
log "Docker 服务状态: $(systemctl is-active docker)"
测试 Docker 运行
log "测试 Docker 基本功能..."
if ! docker run --rm hello-world >/dev/null 2>&1; then
error "Docker 测试运行失败"
fi
log "Docker 测试运行成功"
}
配置 Docker
configure_docker() {
log "配置 Docker..."
设置镜像加速器(可选)
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
重启 Docker 服务使配置生效
log "重启 Docker 服务以应用配置..."
systemctl restart docker
log "Docker 配置完成"
}
添加用户到 docker 组(可选)
add_user_to_docker_group() {
local user="{1:-(whoami)}"
log "将用户 $user 添加到 docker 组..."
if ! getent group docker >/dev/null; then
groupadd docker
fi
usermod -aG docker "$user"
log "用户 $user 已添加到 docker 组"
log "注意: 需要重新登录才能生效"
}
清理临时文件
cleanup() {
log "清理临时文件..."
rm -rf "$EXTRACT_DIR"
log "临时文件清理完成"
}
显示安装信息
show_install_info() {
echo -e "{GREEN}====================================================================={NC}"
echo -e "{GREEN}Docker 已成功安装!{NC}"
echo -e "{GREEN}版本: (docker --version)${NC}"
echo -e "{GREEN}状态: (systemctl is-active docker)${NC}"
echo -e "{GREEN}====================================================================={NC}"
echo -e "{YELLOW}使用提示:{NC}"
echo -e " 1. 普通用户需要重新登录才能使用 docker 命令"
echo -e " 2. 查看 Docker 信息: docker info"
echo -e " 3. 运行第一个容器: docker run -it ubuntu bash"
echo -e "{YELLOW}日志文件位置: LOG_FILE${NC}"
}
主函数
main() {
echo -e "{GREEN}开始执行 Docker 二进制包安装脚本...{NC}"
log "========================================================="
log "开始执行 Docker 二进制包安装脚本"
log "系统信息: $(uname -a)"
check_root
check_arch
check_package
uninstall_old
extract_package
install_docker
configure_docker_service
configure_docker
add_user_to_docker_group
cleanup
show_install_info
log "Docker 二进制包安装脚本执行完成"
log "========================================================="
}
执行主函数
main
安装docker