update docker

This commit is contained in:
Cauchy WuChao 2026-03-18 11:18:57 +08:00
commit 0b622611e3
3 changed files with 849 additions and 0 deletions

269
README.md Normal file
View File

@ -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 - 需手动配置仓库后执行
```

390
install_docker.sh Normal file
View File

@ -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 <<EOF
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
],
"dns": ["114.114.114.114", "223.5.5.5"],
"allow-direct-routing": ${ALLOW_DIRECT_ROUTING},
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
success "镜像加速配置完毕 ✓"
# ---------- 12. 启动并设置开机自启 ----------
info "启动 Docker 服务..."
# 注意: 嵌入式板子上 systemd 可能处于 degraded 状态 (非关键服务失败),
# 不能用 is-system-running 判断, 改为直接检查 systemctl 命令是否可用
# 以及 docker.service 单元文件是否存在
SYSTEMD_OK=false
if command -v systemctl &>/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 ""

190
test_docker.sh Normal file
View File

@ -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 ""