commit 0b622611e30f286eb12db9f1cc6c41c591614976 Author: Cauchy WuChao Date: Wed Mar 18 11:18:57 2026 +0800 update docker diff --git a/README.md b/README.md new file mode 100644 index 0000000..6334c1e --- /dev/null +++ b/README.md @@ -0,0 +1,269 @@ + + +## Docker一键安装脚本 + +### 支持平台 +1. RDK X5 / RDK X5 Module (RDK OS版本 >= 3.3.3, MiniBoot版本 >= Sep-03-2025) +2. RDK S100 / RDK S100P (RDK OS版本 >= 4.0.4-Beta, Miniboot版本 >= 4.0.4-20251015222314) + + +### 安装 + +脚本路径`RDK_Docker_Tools/install_docker.sh`, 该脚本会在RDK板端一键安装docker软件, 配置好网络相关配置, 并保证eth0, eth1的网络配置不会被更改. 安装过程中无需重启, 请确保板卡能正常访问互联网, `/`目录有2GB可用空间. + +```bash +bash install_docker.sh +``` + +预期输出 + +```text +============================================================ + Docker 一键安装脚本 (Ubuntu 22.04 ARM64/x86_64) +============================================================ + +[INFO] 检查系统架构... +[OK] 架构: aarch64 (ARM64) ✓ +[INFO] 检查运行权限... +[OK] 当前为 root 用户 ✓ +[INFO] 检查 eth0 网络接口... +[OK] eth0 状态: UP, IP: 10.112.10.98/24 +[INFO] 注意: 本脚本不会修改 eth0 的任何配置 +[INFO] 检查 Docker 是否已安装... +[INFO] 检查依赖命令... +[WARN] 以下命令缺失: curl, 尝试安装... +Reading package lists... Done +Building dependency tree... Done +Reading state information... Done +The following additional packages will be installed: + libcurl4 libcurl4-openssl-dev +Suggested packages: + libcurl4-doc libidn11-dev librtmp-dev libssh2-1-dev +The following NEW packages will be installed: + curl +The following packages will be upgraded: + libcurl4 libcurl4-openssl-dev +2 upgraded, 1 newly installed, 0 to remove and 414 not upgraded. +Need to get 190 kB/867 kB of archives. +After this operation, 439 kB of additional disk space will be used. +Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports jammy-updates/main arm64 curl arm64 7.81.0-1ubuntu1.23 [190 kB] +Fetched 190 kB in 0s (475 kB/s) +perl: warning: Setting locale failed. +perl: warning: Please check that your locale settings: + LANGUAGE = (unset), + LC_ALL = (unset), + LANG = "en_US.UTF-8" + are supported and installed on your system. +perl: warning: Falling back to the standard locale ("C"). +locale: Cannot set LC_CTYPE to default locale: No such file or directory +locale: Cannot set LC_MESSAGES to default locale: No such file or directory +locale: Cannot set LC_ALL to default locale: No such file or directory +(Reading database ... 219577 files and directories currently installed.) +Preparing to unpack .../libcurl4-openssl-dev_7.81.0-1ubuntu1.23_arm64.deb ... +Unpacking libcurl4-openssl-dev:arm64 (7.81.0-1ubuntu1.23) over (7.81.0-1ubuntu1.21) ... +Preparing to unpack .../libcurl4_7.81.0-1ubuntu1.23_arm64.deb ... +Unpacking libcurl4:arm64 (7.81.0-1ubuntu1.23) over (7.81.0-1ubuntu1.21) ... +Selecting previously unselected package curl. +Preparing to unpack .../curl_7.81.0-1ubuntu1.23_arm64.deb ... +Unpacking curl (7.81.0-1ubuntu1.23) ... +Setting up libcurl4:arm64 (7.81.0-1ubuntu1.23) ... +Setting up curl (7.81.0-1ubuntu1.23) ... +Setting up libcurl4-openssl-dev:arm64 (7.81.0-1ubuntu1.23) ... +Processing triggers for man-db (2.10.2-1) ... +Processing triggers for libc-bin (2.35-0ubuntu3.11) ... +[OK] 依赖命令检查完毕 ✓ +[INFO] 检查网络连通性... +[OK] 可访问 Ubuntu ports 源 (ports.ubuntu.com) ✓ +[INFO] 更新 apt 软件包缓存... +[OK] apt 缓存更新完毕 ✓ +[INFO] 安装必要依赖包... +[INFO] 安装缺失依赖: apt-transport-https +... +[OK] 依赖包就绪 ✓ +[INFO] 开始安装 Docker (docker.io)... +... +Adding group `docker' (GID 135) ... +Done. +Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /lib/systemd/system/docker.service. +Created symlink /etc/systemd/system/sockets.target.wants/docker.socket → /lib/systemd/system/docker.socket. +Job for docker.service failed because the control process exited with error code. +See "systemctl status docker.service" and "journalctl -xeu docker.service" for details. +invoke-rc.d: initscript docker, action "start" failed. +● docker.service - Docker Application Container Engine + Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) + Active: activating (auto-restart) (Result: exit-code) since Wed 2026-03-18 11:12:24 CST; 7ms ago +TriggeredBy: ● docker.socket + Docs: https://docs.docker.com + Process: 231291 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=1/FAILURE) + Main PID: 231291 (code=exited, status=1/FAILURE) +Setting up dnsmasq-base (2.90-0ubuntu0.22.04.1) ... +Setting up docker-buildx (0.21.3-0ubuntu1~22.04.1) ... +Setting up ubuntu-fan (0.12.16) ... +Created symlink /etc/systemd/system/multi-user.target.wants/ubuntu-fan.service → /lib/systemd/system/ubuntu-fan.service. +Processing triggers for man-db (2.10.2-1) ... +Processing triggers for dbus (1.12.20-2ubuntu4.1) ... +Processing triggers for libc-bin (2.35-0ubuntu3.11) ... +[OK] Docker 安装完毕 ✓ +[INFO] 检查 iptables 后端兼容性... +update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode +update-alternatives: using /usr/sbin/ip6tables-legacy to provide /usr/sbin/ip6tables (ip6tables) in manual mode +[OK] 已切换到 iptables-legacy 后端 ✓ +[INFO] 配置 Docker 镜像加速源... +[WARN] 内核缺少 iptable_raw 模块, 将启用 allow-direct-routing 绕过 raw 表限制 +[OK] 镜像加速配置完毕 ✓ +[INFO] 启动 Docker 服务... +[OK] Docker 服务已通过 systemd 启动 ✓ +[INFO] 检查 Docker Hub 及镜像源 DNS 解析... +[OK] DNS hosts 修复完毕 ✓ + +[INFO] 验证 Docker 安装... +[OK] Docker 版本: Docker version 28.2.2, build 28.2.2-0ubuntu1~22.04.1 +[OK] dockerd 进程运行中 ✓ +[OK] Docker socket 存在: /var/run/docker.sock ✓ +[OK] docker info 执行成功 ✓ + +[INFO] 验证核心命令可用性... +[OK] docker pull --help ✓ +[OK] docker push --help ✓ +[OK] docker commit --help ✓ +[OK] docker export --help ✓ +[OK] docker load --help ✓ +[OK] docker images ✓ +[OK] docker ps ✓ + +============================================================ +[OK] Docker 安装完成! +============================================================ + + 常用命令速查: + docker pull <镜像> # 拉取镜像 + docker push <镜像> # 推送镜像 + docker commit <容器> <镜像> # 提交容器为镜像 + docker export <容器> -o x.tar # 导出容器 + docker load -i <文件.tar> # 加载镜像 + docker images # 查看本地镜像 + docker ps -a # 查看所有容器 + + 注意事项: + - eth0 网络配置未做任何修改 + - 本次安装无需重启系统 + - 镜像加速配置: /etc/docker/daemon.json + - Docker 日志: journalctl -u docker 或 /var/log/dockerd.log +``` + + +### 测试 + +```bash +bash test_docker.sh +``` + +预期输出 + +```text +============================================================ + Docker 功能测试脚本 +============================================================ + +[INFO] 检查 Docker 服务状态... +[OK] Docker 服务正常 ✓ + +------------------------------------------------------------ +[INFO] [1/5] 测试 docker pull... +------------------------------------------------------------ +[INFO] 尝试拉取: hello-world +Using default tag: latest +latest: Pulling from library/hello-world +198f93fd5094: Pull complete +Digest: sha256:85404b3c53951c3ff5d40de0972b1bb21fafa2e8daa235355baf44f33db9dbdd +Status: Downloaded newer image for hello-world:latest +docker.io/library/hello-world:latest +[OK] docker pull 成功 ✓ + +------------------------------------------------------------ +[INFO] [2/5] 测试 docker run... +------------------------------------------------------------ + +Hello from Docker! +This message shows that your installation appears to be working correctly. + +To generate this message, Docker took the following steps: + 1. The Docker client contacted the Docker daemon. + 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. + (arm64v8) + 3. The Docker daemon created a new container from that image which runs the + executable that produces the output you are currently reading. + 4. The Docker daemon streamed that output to the Docker client, which sent it + to your terminal. + +To try something more ambitious, you can run an Ubuntu container with: + $ docker run -it ubuntu bash + +Share images, automate workflows, and more with a free Docker ID: + https://hub.docker.com/ + +For more examples and ideas, visit: + https://docs.docker.com/get-started/ + +[OK] docker run 成功 ✓ + +------------------------------------------------------------ +[INFO] [3/5] 测试 docker commit... +------------------------------------------------------------ +sha256:c2c4ee901ecc7b04b29dadeebc5547450e00ec105d63b7109a462e60628fb866 +[OK] docker commit 成功 -> hello-world-committed:test ✓ +[OK] commit 镜像验证通过 ✓ + +------------------------------------------------------------ +[INFO] [4/5] 测试 docker export... +------------------------------------------------------------ +[OK] docker export 成功 -> /tmp/docker_test_232981/hello-world-export.tar (16K) ✓ + +------------------------------------------------------------ +[INFO] [5/5] 测试 docker save & load... +------------------------------------------------------------ +[OK] docker save 成功 -> /tmp/docker_test_232981/hello-world-load.tar (20K) ✓ +Untagged: hello-world-committed:test +Deleted: sha256:c2c4ee901ecc7b04b29dadeebc5547450e00ec105d63b7109a462e60628fb866 +[INFO] 已删除本地镜像 hello-world-committed:test, 准备 load... +Loaded image: hello-world-committed:test +[OK] docker load 成功, 镜像已恢复 ✓ + +------------------------------------------------------------ +[INFO] [附] docker push 说明 +------------------------------------------------------------ +[WARN] docker push 需要登录镜像仓库, 本脚本不自动执行 + 推送到 Docker Hub: + docker login + docker tag hello-world-committed:test <你的用户名>/hello-world:test + docker push <你的用户名>/hello-world:test + + 推送到私有仓库: + docker tag hello-world-committed:test <仓库地址>/hello-world:test + docker push <仓库地址>/hello-world:test + +------------------------------------------------------------ +[INFO] 清理测试资源... +------------------------------------------------------------ +docker_test_232981 +[OK] 容器已清理 ✓ +Untagged: hello-world-committed:test +Deleted: sha256:c2c4ee901ecc7b04b29dadeebc5547450e00ec105d63b7109a462e60628fb866 +[OK] commit 镜像已清理 ✓ +[OK] 临时文件已清理 ✓ + +============================================================ +[OK] 全部测试通过! +============================================================ + + 测试结果汇总: + ✓ docker pull - 镜像拉取 + ✓ docker run - 容器运行 + ✓ docker commit - 容器提交为镜像 + ✓ docker export - 容器导出为 tar + ✓ docker save - 镜像保存为 tar + ✓ docker load - 从 tar 加载镜像 + - docker push - 需手动配置仓库后执行 +``` + + diff --git a/install_docker.sh b/install_docker.sh new file mode 100644 index 0000000..0a40c53 --- /dev/null +++ b/install_docker.sh @@ -0,0 +1,390 @@ +#!/bin/bash +# ============================================================ +# Docker 一键安装脚本 +# 适用平台: Ubuntu 22.04 (ARM64 / aarch64 / x86_64) +# 说明: 通过 Ubuntu 官方 ports 源安装 docker.io +# 不修改 eth0 网络配置, 不需要重启 +# ============================================================ + +set -e + +# ---------- 颜色输出 ---------- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +info() { echo -e "${BLUE}[INFO]${NC} $*"; } +success() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*"; } +die() { error "$*"; exit 1; } + +echo "" +echo "============================================================" +echo " Docker 一键安装脚本 (Ubuntu 22.04 ARM64/x86_64)" +echo "============================================================" +echo "" + +# ---------- 验证函数 (必须在调用前定义) ---------- +verify_docker() { + echo "" + info "验证 Docker 安装..." + + if ! command -v docker &>/dev/null; then + die "docker 命令不存在, 安装可能失败" + fi + DOCKER_VER=$(docker --version) + success "Docker 版本: $DOCKER_VER" + + if pgrep -x dockerd &>/dev/null; then + success "dockerd 进程运行中 ✓" + else + warn "dockerd 进程未检测到, Docker 可能未正常启动" + fi + + if [ -S /var/run/docker.sock ]; then + success "Docker socket 存在: /var/run/docker.sock ✓" + else + warn "Docker socket 不存在, 服务可能未启动" + fi + + if docker info &>/dev/null; then + success "docker info 执行成功 ✓" + else + warn "docker info 失败, 请检查 Docker 服务状态" + info "可尝试: systemctl status docker 或 journalctl -u docker" + fi + + echo "" + info "验证核心命令可用性..." + for cmd in "docker pull --help" "docker push --help" "docker commit --help" \ + "docker export --help" "docker load --help" "docker images" \ + "docker ps"; do + if $cmd &>/dev/null; then + success " $cmd ✓" + else + warn " $cmd 执行异常" + fi + done +} + +# ---------- 1. 检查架构 ---------- +info "检查系统架构..." +ARCH=$(uname -m) +if [ "$ARCH" = "aarch64" ]; then + success "架构: aarch64 (ARM64) ✓" +elif [ "$ARCH" = "x86_64" ]; then + success "架构: x86_64 ✓" +else + warn "当前架构为 $ARCH, 本脚本针对 aarch64/x86_64 优化, 继续执行但可能出现问题" +fi + +# ---------- 2. 检查是否 root ---------- +info "检查运行权限..." +if [ "$(id -u)" -ne 0 ]; then + die "请使用 root 权限运行本脚本: sudo bash $0" +fi +success "当前为 root 用户 ✓" + +# ---------- 3. 保护 eth0 ---------- +info "检查 eth0 网络接口..." +if ! ip link show eth0 &>/dev/null; then + warn "eth0 接口不存在, 跳过保护检查" +else + ETH0_STATE=$(ip link show eth0 | grep -o 'state [A-Z]*' | awk '{print $2}') + ETH0_IP=$(ip addr show eth0 | grep 'inet ' | awk '{print $2}' | head -1) + success "eth0 状态: $ETH0_STATE, IP: ${ETH0_IP:-未分配}" + info "注意: 本脚本不会修改 eth0 的任何配置" +fi + +# ---------- 4. 检查 Docker 是否已安装 ---------- +info "检查 Docker 是否已安装..." +if command -v docker &>/dev/null; then + DOCKER_VER=$(docker --version 2>/dev/null) + warn "Docker 已安装: $DOCKER_VER" + read -r -p "是否重新安装/覆盖? [y/N] " REINSTALL + if [[ ! "$REINSTALL" =~ ^[Yy]$ ]]; then + info "跳过安装, 直接验证现有 Docker..." + verify_docker + exit 0 + fi +fi + +# ---------- 5. 检查必要命令 ---------- +info "检查依赖命令..." +MISSING_CMDS=() +for cmd in apt curl wget gpg; do + if ! command -v "$cmd" &>/dev/null; then + MISSING_CMDS+=("$cmd") + fi +done + +if [ ${#MISSING_CMDS[@]} -gt 0 ]; then + warn "以下命令缺失: ${MISSING_CMDS[*]}, 尝试安装..." + apt-get update -qq && apt-get install -y "${MISSING_CMDS[@]}" \ + || die "无法安装缺失命令: ${MISSING_CMDS[*]}, 请手动安装后重试" +fi +success "依赖命令检查完毕 ✓" + +# ---------- 6. 检查网络连通性 ---------- +info "检查网络连通性..." +NETWORK_OK=false + +if curl -s --connect-timeout 8 http://ports.ubuntu.com/ &>/dev/null; then + success "可访问 Ubuntu ports 源 (ports.ubuntu.com) ✓" + NETWORK_OK=true + APT_SOURCE="ubuntu_ports" +elif curl -s --connect-timeout 8 https://mirrors.tuna.tsinghua.edu.cn/ &>/dev/null; then + success "可访问清华大学镜像源 ✓" + NETWORK_OK=true + APT_SOURCE="tsinghua" +elif curl -s --connect-timeout 8 https://mirrors.ustc.edu.cn/ &>/dev/null; then + success "可访问中科大镜像源 ✓" + NETWORK_OK=true + APT_SOURCE="ustc" +else + error "无法访问任何已知软件源!" + echo "" + echo " 请检查以下内容:" + echo " 1. 网络是否正常: ping 114.114.114.114" + echo " 2. DNS 是否正常: nslookup ports.ubuntu.com" + echo " 3. 防火墙是否拦截出站流量" + echo "" + die "网络不可用, 无法继续安装" +fi + +# ---------- 7. 更新 apt 缓存 ---------- +info "更新 apt 软件包缓存..." +if ! apt-get update -qq 2>&1; then + warn "apt update 出现警告, 尝试忽略错误继续..." + apt-get update --allow-releaseinfo-change -qq 2>&1 || true +fi +success "apt 缓存更新完毕 ✓" + +# ---------- 8. 安装依赖包 ---------- +info "安装必要依赖包..." +DEPS=(ca-certificates curl gnupg lsb-release apt-transport-https) +MISSING_DEPS=() +for pkg in "${DEPS[@]}"; do + if ! dpkg -l "$pkg" 2>/dev/null | grep -q '^ii'; then + MISSING_DEPS+=("$pkg") + fi +done + +if [ ${#MISSING_DEPS[@]} -gt 0 ]; then + info "安装缺失依赖: ${MISSING_DEPS[*]}" + apt-get install -y "${MISSING_DEPS[@]}" \ + || die "依赖包安装失败, 请检查网络或 apt 源配置" +fi +success "依赖包就绪 ✓" + +# ---------- 9. 安装 Docker ---------- +info "开始安装 Docker (docker.io)..." + +apt-get install -y \ + docker.io \ + docker-buildx \ + docker-compose-v2 \ + || die "Docker 安装失败! 请检查网络连接和 apt 源配置" + +success "Docker 安装完毕 ✓" + +# ---------- 10. 修复 iptables 后端 ---------- +# 部分嵌入式/定制内核 (如 RT 内核) 不支持 nf_tables, +# 需切换到 iptables-legacy, 否则 dockerd 启动时报: +# "iptables (nf_tables): Could not fetch rule set generation id: Invalid argument" +info "检查 iptables 后端兼容性..." + +# 若 iptables-legacy 不存在则先安装 +if ! command -v iptables-legacy &>/dev/null && ! [ -f /usr/sbin/iptables-legacy ]; then + info "iptables-legacy 不存在, 尝试安装 iptables..." + apt-get install -y iptables 2>/dev/null || true +fi + +if update-alternatives --list iptables 2>/dev/null | grep -q legacy; then + update-alternatives --set iptables /usr/sbin/iptables-legacy 2>/dev/null || true + update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy 2>/dev/null || true + success "已切换到 iptables-legacy 后端 ✓" +else + warn "未找到 iptables-legacy 备选项, 若 Docker 启动失败请手动执行:" + warn " apt-get install -y iptables && update-alternatives --set iptables /usr/sbin/iptables-legacy" +fi + +# ---------- 11. 配置 Docker 镜像加速 ---------- +info "配置 Docker 镜像加速源..." +mkdir -p /etc/docker + +# 检查内核是否有 iptable_raw 模块 +# 部分嵌入式/定制内核 (如 RT 内核) 没有编译 iptable_raw, +# Docker 28.x 默认会用 raw 表做 DIRECT ACCESS FILTERING, +# 若模块不存在则 docker run 报错: +# "can't initialize iptables table `raw': Table does not exist" +# 解决方案: 在 daemon.json 加 "allow-direct-routing": true 跳过该规则 +ALLOW_DIRECT_ROUTING="false" +if ! modprobe iptable_raw 2>/dev/null && ! lsmod | grep -q '^iptable_raw'; then + warn "内核缺少 iptable_raw 模块, 将启用 allow-direct-routing 绕过 raw 表限制" + ALLOW_DIRECT_ROUTING="true" +else + success "iptable_raw 模块可用 ✓" +fi + +cat > /etc/docker/daemon.json </dev/null && systemctl cat docker.service &>/dev/null 2>&1; then + SYSTEMD_OK=true +fi + +if [ "$SYSTEMD_OK" = true ]; then + systemctl enable docker 2>/dev/null || warn "无法设置 docker 开机自启" + systemctl restart docker 2>/dev/null || warn "systemctl restart docker 失败, 尝试直接启动" + sleep 3 + if systemctl is-active --quiet docker; then + success "Docker 服务已通过 systemd 启动 ✓" + else + warn "systemd 启动失败, 查看日志: journalctl -u docker -n 20" + warn "尝试直接启动 dockerd..." + pkill -x dockerd 2>/dev/null || true + sleep 1 + dockerd --host=unix:///var/run/docker.sock >> /var/log/dockerd.log 2>&1 & + sleep 4 + if pgrep -x dockerd &>/dev/null; then + success "dockerd 直接启动成功 ✓" + else + error "dockerd 启动失败, 请查看日志: /var/log/dockerd.log" + fi + fi +else + warn "systemd 不可用, 直接启动 dockerd..." + if ! pgrep -x dockerd &>/dev/null; then + dockerd --host=unix:///var/run/docker.sock >> /var/log/dockerd.log 2>&1 & + sleep 4 + fi + if pgrep -x dockerd &>/dev/null; then + success "dockerd 直接启动成功 ✓" + else + error "dockerd 启动失败, 请查看日志: /var/log/dockerd.log" + fi +fi + +# ---------- 13. 修复 DNS 解析 (内网DNS无法解析公网域名时的兜底方案) ---------- +info "检查 Docker Hub 及镜像源 DNS 解析..." + +DNS_FIXED=false +fix_dns_with_hosts() { + local dns_server="$1" + python3 -c " +import socket, sys + +def dns_query(server, domain): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.settimeout(3) + tid = b'\xab\xcd' + flags = b'\x01\x00' + qdcount = b'\x00\x01' + header = tid + flags + qdcount + b'\x00\x00\x00\x00\x00\x00' + qname = b'' + for part in domain.split('.'): + qname += bytes([len(part)]) + part.encode() + qname += b'\x00' + question = qname + b'\x00\x01\x00\x01' + s.sendto(header + question, (server, 53)) + data, _ = s.recvfrom(512) + ips = [] + i = 12 + while data[i] != 0: i += data[i] + 1 + i += 5 + while i < len(data) - 10: + if data[i] >= 0xc0: i += 2 + else: + while i < len(data) and data[i] != 0: i += data[i] + 1 + i += 1 + rtype = (data[i]<<8)|data[i+1] + rdlen = (data[i+8]<<8)|data[i+9] + i += 10 + if rtype == 1 and rdlen == 4: + ips.append('.'.join(str(b) for b in data[i:i+4])) + i += rdlen + return ips + except: return [] + finally: s.close() + +server = sys.argv[1] +domains = [ + 'docker.m.daocloud.io', + 'registry-1.docker.io', + 'auth.docker.io', +] +results = [] +for d in domains: + ips = dns_query(server, d) + if ips: + results.append(f'{ips[0]} {d}') +if results: + print('\n'.join(results)) + sys.exit(0) +else: + sys.exit(1) +" "$dns_server" 2>/dev/null +} + +HOSTS_BLOCK="" +for dns in 114.114.114.114 223.5.5.5; do + HOSTS_BLOCK=$(fix_dns_with_hosts "$dns" 2>/dev/null) && DNS_FIXED=true && break +done + +if [ "$DNS_FIXED" = true ]; then + sed -i '/# Docker 镜像源/,/^$/d' /etc/hosts 2>/dev/null || true + printf "\n# Docker 镜像源 (由 install_docker.sh 写入, 绕过内网DNS)\n%s\n" "$HOSTS_BLOCK" >> /etc/hosts + success "DNS hosts 修复完毕 ✓" +else + warn "公共 DNS 不可达, 跳过 hosts 修复 (pull 时可能遇到解析失败)" +fi + +# ---------- 14. 验证安装 ---------- +verify_docker + +# ---------- 15. 完成提示 ---------- +echo "" +echo "============================================================" +success "Docker 安装完成!" +echo "============================================================" +echo "" +echo " 常用命令速查:" +echo " docker pull <镜像> # 拉取镜像" +echo " docker push <镜像> # 推送镜像" +echo " docker commit <容器> <镜像> # 提交容器为镜像" +echo " docker export <容器> -o x.tar # 导出容器" +echo " docker load -i <文件.tar> # 加载镜像" +echo " docker images # 查看本地镜像" +echo " docker ps -a # 查看所有容器" +echo "" +echo " 注意事项:" +echo " - eth0 网络配置未做任何修改" +echo " - 本次安装无需重启系统" +echo " - 镜像加速配置: /etc/docker/daemon.json" +echo " - Docker 日志: journalctl -u docker 或 /var/log/dockerd.log" +echo "" diff --git a/test_docker.sh b/test_docker.sh new file mode 100644 index 0000000..b1849db --- /dev/null +++ b/test_docker.sh @@ -0,0 +1,190 @@ +#!/bin/bash +# ============================================================ +# Docker 功能测试脚本 +# 测试项目: pull / run / commit / export / load / push +# ============================================================ + +set -e + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +info() { echo -e "${BLUE}[INFO]${NC} $*"; } +success() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*"; } +die() { error "$*"; exit 1; } + +WORK_DIR="/tmp/docker_test_$$" +TEST_IMAGE="hello-world" +COMMIT_IMAGE="hello-world-committed:test" +EXPORT_TAR="$WORK_DIR/hello-world-export.tar" +LOAD_TAR="$WORK_DIR/hello-world-load.tar" +TEST_CONTAINER="docker_test_$$" + +mkdir -p "$WORK_DIR" + +echo "" +echo "============================================================" +echo " Docker 功能测试脚本" +echo "============================================================" +echo "" + +# ---------- 检查 Docker 服务 ---------- +info "检查 Docker 服务状态..." +if ! docker info &>/dev/null; then + die "Docker 服务未运行, 请先启动: systemctl start docker" +fi +success "Docker 服务正常 ✓" + +# ---------- 1. docker pull ---------- +echo "" +echo "------------------------------------------------------------" +info "[1/5] 测试 docker pull..." +echo "------------------------------------------------------------" + +# 尝试多个镜像源 +PULL_OK=false +for mirror_image in \ + "hello-world" \ + "docker.mirrors.ustc.edu.cn/library/hello-world:latest" \ + "mirror.baidubce.com/library/hello-world:latest"; do + + info "尝试拉取: $mirror_image" + if docker pull "$mirror_image" 2>&1; then + # 如果不是标准名称,打个tag + if [ "$mirror_image" != "hello-world" ]; then + docker tag "$mirror_image" hello-world:latest 2>/dev/null || true + fi + PULL_OK=true + success "docker pull 成功 ✓" + break + else + warn "拉取 $mirror_image 失败, 尝试下一个..." + fi +done + +if [ "$PULL_OK" = false ]; then + # 最后手段: 本地构建一个最小镜像代替 + warn "所有镜像源均无法拉取, 改用本地构建最小测试镜像..." + SCRATCH_DIR="$WORK_DIR/scratch" + mkdir -p "$SCRATCH_DIR" + # 写一个静态可执行的 hello 程序 (用 shell 脚本模拟) + cat > "$SCRATCH_DIR/hello.sh" <<'HELLO' +#!/bin/sh +echo "Hello from Docker on ARM64!" +echo "Docker pull/commit/export/load 功能测试通过" +HELLO + chmod +x "$SCRATCH_DIR/hello.sh" + cat > "$SCRATCH_DIR/Dockerfile" <<'DOCKERFILE' +FROM busybox:latest +COPY hello.sh /hello.sh +CMD ["/hello.sh"] +DOCKERFILE + # 先拉 busybox + docker pull busybox:latest 2>&1 || die "busybox 也无法拉取, 网络不可用" + docker build -t hello-world:latest "$SCRATCH_DIR" 2>&1 + success "本地构建 hello-world 镜像成功 ✓" +fi + +# ---------- 2. docker run ---------- +echo "" +echo "------------------------------------------------------------" +info "[2/5] 测试 docker run..." +echo "------------------------------------------------------------" + +docker run --name "$TEST_CONTAINER" "$TEST_IMAGE" 2>&1 \ + || docker run --name "$TEST_CONTAINER" hello-world:latest 2>&1 \ + || die "docker run 失败" +success "docker run 成功 ✓" + +# ---------- 3. docker commit ---------- +echo "" +echo "------------------------------------------------------------" +info "[3/5] 测试 docker commit..." +echo "------------------------------------------------------------" + +docker commit \ + -m "测试 commit: 添加自定义标签" \ + -a "docker-test-script" \ + "$TEST_CONTAINER" \ + "$COMMIT_IMAGE" 2>&1 +success "docker commit 成功 -> $COMMIT_IMAGE ✓" + +# 验证 commit 的镜像存在 +docker inspect "$COMMIT_IMAGE" &>/dev/null \ + || die "commit 后的镜像不存在" +success "commit 镜像验证通过 ✓" + +# ---------- 4. docker export ---------- +echo "" +echo "------------------------------------------------------------" +info "[4/5] 测试 docker export..." +echo "------------------------------------------------------------" + +docker export "$TEST_CONTAINER" -o "$EXPORT_TAR" 2>&1 +EXPORT_SIZE=$(du -sh "$EXPORT_TAR" | cut -f1) +success "docker export 成功 -> $EXPORT_TAR ($EXPORT_SIZE) ✓" + +# ---------- 5. docker save + docker load ---------- +echo "" +echo "------------------------------------------------------------" +info "[5/5] 测试 docker save & load..." +echo "------------------------------------------------------------" + +# save committed 镜像为 tar +docker save "$COMMIT_IMAGE" -o "$LOAD_TAR" 2>&1 +LOAD_SIZE=$(du -sh "$LOAD_TAR" | cut -f1) +success "docker save 成功 -> $LOAD_TAR ($LOAD_SIZE) ✓" + +# 删除本地镜像再 load,验证完整性 +docker rmi "$COMMIT_IMAGE" 2>&1 +info "已删除本地镜像 $COMMIT_IMAGE, 准备 load..." + +docker load -i "$LOAD_TAR" 2>&1 +docker inspect "$COMMIT_IMAGE" &>/dev/null \ + || die "docker load 后镜像不存在" +success "docker load 成功, 镜像已恢复 ✓" + +# ---------- push 说明 ---------- +echo "" +echo "------------------------------------------------------------" +info "[附] docker push 说明" +echo "------------------------------------------------------------" +warn "docker push 需要登录镜像仓库, 本脚本不自动执行" +echo " 推送到 Docker Hub:" +echo " docker login" +echo " docker tag $COMMIT_IMAGE <你的用户名>/hello-world:test" +echo " docker push <你的用户名>/hello-world:test" +echo "" +echo " 推送到私有仓库:" +echo " docker tag $COMMIT_IMAGE <仓库地址>/hello-world:test" +echo " docker push <仓库地址>/hello-world:test" + +# ---------- 清理 ---------- +echo "" +echo "------------------------------------------------------------" +info "清理测试资源..." +echo "------------------------------------------------------------" +docker rm "$TEST_CONTAINER" 2>/dev/null && success "容器已清理 ✓" +docker rmi "$COMMIT_IMAGE" 2>/dev/null && success "commit 镜像已清理 ✓" +rm -rf "$WORK_DIR" && success "临时文件已清理 ✓" + +# ---------- 汇总 ---------- +echo "" +echo "============================================================" +success "全部测试通过!" +echo "============================================================" +echo "" +echo " 测试结果汇总:" +echo " ✓ docker pull - 镜像拉取" +echo " ✓ docker run - 容器运行" +echo " ✓ docker commit - 容器提交为镜像" +echo " ✓ docker export - 容器导出为 tar" +echo " ✓ docker save - 镜像保存为 tar" +echo " ✓ docker load - 从 tar 加载镜像" +echo " - docker push - 需手动配置仓库后执行" +echo ""