> 技术文档 > install_arm_docker.sh

install_arm_docker.sh


#!/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