update docker
This commit is contained in:
commit
0b622611e3
269
README.md
Normal file
269
README.md
Normal 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
390
install_docker.sh
Normal 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
190
test_docker.sh
Normal 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 ""
|
||||||
Loading…
x
Reference in New Issue
Block a user