极空间 Docker 容器体系:zdocker 深度调研

2026/05/22

调研目标:极空间自研容器管理平台 zdocker 的架构、功能边界与实现原理 调研方式:远程服务器逆向分析(T2 设备,ZOS V1.2.0200068) 调研日期:2026-05-22


一、核心结论

zdocker 不是 Docker Engine 的替代,而是基于 Docker Engine 之上的业务封装层。

极空间在标准 Docker 栈(dockerd + containerd + runc)之上,自研了一套 Go 编写的容器管理中间件,核心解决三个问题:

  1. 应用商店化 —— 把第三方 Docker 应用包装成一键安装/卸载/升级的商品
  2. Android 容器(AIC) —— 在 NAS 上运行带 GPU/HDMI/USB 的 Android 容器
  3. Compose 与定时任务 —— 管理 docker-compose 项目和容器启停策略

zdocker 本身不直接暴露 HTTP 端口,而是通过 Unix socket / 内部 IPC 与 go-baseset 通信,由 baseset 作为 API 网关对外服务。


二、整体架构(四层模型)

┌─────────────────────────────────────────────────────────────┐
│ Layer 4:前端(PC Web / 手机 App / HDMI 界面)                │
│         通过 OpenResty → go-baseset (:8050) 访问             │
├─────────────────────────────────────────────────────────────┤
│ Layer 3:API 网关 + 业务编排                                  │
│         go-baseset (:8040) ←→ baseset (:8038)               │
│         用户认证、路由转发、请求聚合                             │
├─────────────────────────────────────────────────────────────┤
│ Layer 2:容器业务管理层                                        │
│         zdocker (Go)  ←→  dockerm (C++, :8048)              │
│         │                      │                             │
│         ├─ 应用商店 (AppStoreTaskV2)                         │
│         ├─ Android 容器 (CloudPhone / AIC)                   │
│         ├─ Compose 项目管理                                  │
│         ├─ 镜像下载/更新/加速器                               │
│         └─ 容器定时启停 (Cron)                               │
│                      │                                       │
│                      └─ 调用 shell 脚本执行实际 Docker 操作    │
├─────────────────────────────────────────────────────────────┤
│ Layer 1:容器运行时 + Web UI                                  │
│         Docker Engine (dockerd + containerd + runc)         │
│         portainer / zportainer (Docker Web UI)              │
│         overlay2 存储驱动                                     │
└─────────────────────────────────────────────────────────────┘

关键进程与端口

进程路径语言监听端口角色
zdocker/zspace/applications/services/zdocker/zdockerGo 1.23.3无直接端口业务管理层主进程
dockerm/zspace/applications/services/baseset/dockermC++ (httplib)127.0.0.1:8048Docker 操作执行代理
go-baseset/zspace/applications/services/baseset/basesetGo127.0.0.1:8040/8050核心 API 网关
baseset/zspace/applications/services/baseset/basesetGo127.0.0.1:8038Docker 开关控制
portainer/zspace/applications/services/portainer/dist/portainerGo未启动时无端口Docker Web UI
dockerd/usr/bin/dockerdGoUnix socket /var/run/docker.sockDocker Engine
containerd/usr/bin/containerdGoUnix socket /run/containerd/…容器运行时

三、zdocker 本体分析

3.1 二进制特征

file /zspace/applications/services/zdocker/zdocker
# ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked
# Go BuildID=8_Aaqf7v4pLntzMQrper/1l6COKENhwUJ72CblZ_S/...
# with debug_info, not stripped

3.2 源码路径暴露

二进制中的调试符号暴露了 Jenkins CI 构建路径:

/var/jenkins_home/home/workspace/services/zdocker/release/online_t020/
├── model/appstorepredefine.go
├── model/container_list.go
├── model/appstore.go
├── model/apps.go
├── model/compose_cron.go
├── model/tiandingxingandroid.go
├── model/tiandingxingandroid_android_check.go
└── ...

这说明:

3.3 依赖的开源库

通过 Go module 缓存路径识别出主要依赖:

库版本用途
github.com/docker/dockerv27.3.1Docker 官方 Go SDK,调用 Docker API
github.com/docker/go-connectionsv0.5.0Docker 连接管理
github.com/sirupsen/logrusv1.9.3日志
github.com/gin-gonic/gin未明确Web 框架
gorm.io/gorm未明确SQLite ORM
go.opentelemetry.io/otelv1.31.0可观测性
golang.org/x/sysv0.26.0系统调用

3.4 命令行接口

/zspace/applications/services/zdocker/zdocker --help
# 输出只有两项:
#   -v    application version
#   -version  application version

zdocker 不是命令行工具,而是无头守护进程。 启动后没有监听 TCP 端口,而是通过 Unix socket 或文件系统事件与上层服务通信。其标准输出重定向到 /zspace/applications/logs/zdocker/zdocker.log。


四、数据存储模型

zdocker 使用 SQLite 作为元数据存储,所有数据库文件位于 /zspace/applications/services/zdocker/config/ 和 /zspace/zsrp/zdocker/。

4.1 数据库文件

文件路径用途
zdocker-apps.dbconfig/已安装应用列表(应用商店)
zdocker-containers.dbconfig/容器定时任务配置
zdocker-compose.dbconfig/Compose 项目元数据
zdocker-appstore.dbzsrp/应用商店预定义数据缓存
zdocker_status.jsonconfig/zdocker 运行状态({"status":"on"})
arch.jsonconfig/架构标识({"arch":"arm"})
data_dir.jsonconfig/Docker 数据目录挂载点
hub_conf.jsonconfig/Docker Hub 认证配置
proxy_conf.jsonconfig/HTTP/HTTPS 代理配置
registry_mirrors_conf.jsonconfig/镜像加速器列表

4.2 核心表结构

apps(已安装应用)

CREATE TABLE `apps` (
  `id` text,
  `app_name` text,
  `container_id` text,
  `created_at` datetime,
  `updated_at` datetime,
  `status` text,
  PRIMARY KEY (`id`)
);
CREATE UNIQUE INDEX `idx_apps_container_id` ON `apps`(`container_id`);

containers(容器定时配置)

CREATE TABLE `containers` (
  `container_id` text,
  `icon` text,
  `cron` numeric,
  `cron_start` text,
  `cron_start_enable` numeric DEFAULT false,
  `cron_start_once` text,
  `cron_start_once_enable` numeric DEFAULT false,
  `cron_stop` text,
  `cron_stop_enable` numeric DEFAULT false,
  `cron_stop_once` text,
  `cron_stop_once_enable` numeric DEFAULT false,
  PRIMARY KEY (`container_id`)
);

compose_projects(Compose 项目)

CREATE TABLE `compose_projects` (
  `id` text,
  `project_name` text,
  `file_path` text,
  `storage_path` text,
  `created_at` datetime,
  `updated_at` datetime,
  `status` text,
  `path_valid` numeric,
  `app` text,
  PRIMARY KEY (`id`)
);
CREATE UNIQUE INDEX `idx_compose_projects_project_name` ON `compose_projects`(`project_name`);

五、应用商店系统(AppStoreTaskV2)

5.1 设计目标

把 Docker 容器包装成"应用",让普通用户像安装手机 App 一样安装 Docker 应用,无需接触命令行。

5.2 应用预定义数据(Predefine)

每个应用有一个 predefine JSON 字段,包含:

示例(docker 应用自身的 predefine):

{
  "app_name": "docker",
  "app_type": "docker",
  "auto_install": 1,
  "auto_upgrade": 1,
  "processes": [
    {"command": "zdocker"},
    {"command": "containerd"},
    {"command": "containerd-shim"},
    {"command": "containerd-shim-runc-v1"},
    {"command": "containerd-shim-runc-v2"},
    {"command": "dockerm"},
    {"command": "docker-proxy"},
    {"command": "docker"},
    {"command": "dockerd"},
    {"command": "docker-init"}
  ]
}

5.3 安装流程

1. PreFlight(前置检查)
   - 检查设备型号是否在支持列表
   - 检查存储池是否就绪
   - 创建应用安装目录(/var/appstore/pkg/<app>/)
   - 创建 appstore_default bridge 网络

2. 下载
   - 从 https://bwcap.zenithspace.net/AppStore/ 下载应用包
   - 包格式:ZIP,含 docker-compose.yml、UI 资源、安装脚本
   - SHA1 校验

3. 安装
   - 解压到安装目录
   - 执行 prepare_install.sh(如有)
   - 写入 app-config.yml、params.json
   - 配置 Nginx 反向代理(/zspace/applications/services/zdocker/config/apps/nginx)
   - 设置 ACL(setfacl)
   - 执行 docker-compose up -d 或 docker run
   - 写入 SQLite apps 表

4. 卸载
   - 执行 prepare_uninstall.sh
   - docker-compose down / docker rm
   - 删除数据目录(可选,由 delete_data 标记控制)
   - 清理 Nginx 配置

5.4 内置推荐镜像

/zspace/applications/services/portainer/image_default.json 预置了 9 个推荐镜像:

镜像用途
xhofe/alist多存储文件列表
linuxserver/qbittorrentBT 下载
jlesage/firefox远程浏览器
linuxserver/calibre-web电子书管理
cloudnas/clouddrive2多云盘挂载
wiznote/wizserver为知笔记服务端
jonnyan404/verysync微力同步
ubuntuLinux 环境
centosLinux 环境(已废弃)

六、Android 容器(AIC:Android in Container)

6.1 核心机制

zdocker 最具差异化的功能:在 Docker 容器内运行完整 Android 系统,支持 GPU 加速、HDMI 输出、USB 外设、音频输入输出。

这通过 redroid/TDX(TianDingXing) 技术实现,本质是在容器内运行 Android 的 init 进程,配合宿主机的内核 binder、ashmem、ion 等 Android 子系统。

6.2 关键文件

文件说明
cloudphone_start.shAndroid 容器启动脚本
aic/install.shAndroid 镜像智能升级(支持 xdelta3 差分升级)
aic/boot.img_sleep_fix修复休眠的内核镜像(51.5MB)
aic/android_poweroff.sh电源键短按/长按处理(控制 Android/宿主机休眠或关机)
aic/storage_ready_transition.sh存储就绪后迁移数据
default/container_common.conf所有 Android 容器的默认配置
default/container_hdmi.confHDMI 分屏配置

6.3 容器配置参数

container_common.conf 暴露了 Android 容器的大量硬件配置能力:

# 网络模式:docker0 / macvlan_static / macvlan_dhcp / host
network.type=docker0
net_dns1=114.114.114.114
net_dns2=8.8.8.8

# 显示配置(支持 DSI/HDMI/DPI 等多种接口)
primary_type=DPI-1
default.resolution=1080x1920@60

# 硬件开关
disable.audio.output=true
disable.input.event=false
disable.ueventd.cold_boot=true
disable.usb.configfs=false

6.4 镜像管理

6.5 云手机功能

zdocker 内部有大量 CloudPhone 相关代码:

这说明 Android 容器不仅是本地 HDMI 输出,还预留了远程访问能力(类似云手机/云桌面的体验)。

6.6 实际可用性观察

代码中虽然存在 CloudPhone 模块和默认端口 3999,但实际观察:


七、Docker 兼容性分析

7.1 与标准 Docker 的关系

层面极空间实现标准 Docker
容器运行时dockerd + containerd + runc(完全标准)dockerd + containerd + runc
OCI Runtime/usr/sbin/runcrunc
存储驱动overlay2overlay2
网络bridge / macvlan / host同上
API 兼容Docker SDK v27.3.1(全量兼容)标准 API
Web UIportainer / zportainer需自行安装
Composedocker-compose(标准二进制)docker compose
应用封装zdocker 应用商店无
Android 容器zdocker AIC 扩展无

7.2 启动流程

当用户在 UI 中开启 Docker 功能时:

1. baseset (:8038) 收到 POST /settings docker_do=on
2. 调用 /zspace/applications/services/portainer/shell/start_docker.sh
3. start_docker.sh:
   a. 读取 reghub.json 获取镜像加速器地址
   b. 生成 /etc/docker/daemon.json(data-root, overlay2, ipv6)
   c. 执行 docker_zfsv3_update.sh(数据迁移)
   d. systemctl restart containerd.service
   e. systemctl restart docker.socket
   f. systemctl restart docker.service
   g. 启动 portainer
   h. 调用 baseset/start_d.sh 启动 dockerm
   i. curl -X POST 127.0.0.1:8048/workd start=true
4. zdocker 检测到 Docker Engine 就绪,开始初始化应用商店数据

7.3 安全策略


八、dockerm:C++ 层的 Docker 操作代理

8.1 定位

dockerm 是连接 zdocker(Go 业务层)和 Docker Engine 的操作执行代理。

8.2 职责

接收 baseset/zdocker 的 HTTP 请求,调用 shell 脚本完成实际 Docker 操作:

路由/功能对应脚本
镜像下载portainer/shell/docker_download_image.sh
镜像加载portainer/shell/docker_load_image_ex.sh
镜像拉取portainer/shell/docker_pull_image_ex.sh
数据目录删除portainer/shell/docker_root_dir_remove.sh
数据目录大小portainer/shell/docker_root_size.sh
Docker 开关/workd (POST start=true)

8.3 与 zdocker 的分工

zdockerdockerm
语言GoC++
职责业务逻辑、状态管理、数据库底层操作执行
通信方式文件/DB/事件HTTP (:8048)
是否调用 docker CLI否(用 Docker SDK)是(通过 shell 脚本)

九、Docker 管理界面:Portainer 的三层封装

结论:Portainer + Nginx 反向代理 + Token 认证封装

极空间的 Docker 管理界面底层是开源 Portainer CE,但做了三层封装:

  1. Nginx 反向代理 — 用户访问极空间 APP/PC 端 → OpenResty → Nginx proxy_pass → Portainer (:9000)
  2. Token 认证桥接 — auth_master.lua 将极空间的用户 token 改写为 Portainer 能理解的 Authorization 头
  3. 极空间定制版 — zportainer 可能替换了品牌 logo、默认 endpoint 配置、TLS 证书等

核心原理和 browser 应用(Chrome/Firefox 远程浏览器)一模一样——都是"Docker 容器跑服务,OpenResty 做反向代理 + 认证"。

两个二进制

文件大小说明
portainer32.8 MB标准开源 Portainer CE,ARM64 静态链接,Go 编译
zportainer32.8 MB极空间定制版,内容有差异(可能改品牌/配置)
portainer/dist/public/-AngularJS 前端资源(index.html + JS/CSS)

portainer 的源码路径显示是极空间工程师自行编译集成的(路径形如 /home/<工程师>/portainer/api/...)。

前端技术栈

portainer 前端是一个 AngularJS SPA:

<html lang="en" ng-app="portainer" ng-strict-di>
  <title>Portainer</title>
  <body ng-controller="MainController">
    <div ui-view="sidebar" ...></div>

前端路由($state):

Portainer API 路由

portainer 暴露的标准 REST API:

路由功能
/api/auth用户认证
/api/endpointsDocker endpoint 管理
/api/endpoints/{id}/docker/...代理 Docker API
/api/stacksStack/Compose 管理
/api/containers容器 CRUD
/api/images镜像管理
/api/websocketWebSocket(容器终端)
/api/templates应用模板
/api/settings系统设置
/api/users用户管理
/api/teams团队管理
/api/registries镜像仓库管理
/api/webhooksWebhook
/api/edge_jobsEdge 计算任务

集成模式:以 Browser 应用为例

browser 应用(Chrome/Firefox 远程浏览器)展示了极空间如何把 Docker 容器包装成"应用":

应用定义 (browser_arm.json):

{
  "name": "Browser",
  "image": "kasmweb/chrome",
  "tag": "1.16.0_zspace_1.8",
  "visit_path": "apps/chrome/",
  "config": {
    "ports": {"56901": "6901"},
    "env": {"KASM_USER_NAME": "admin", "VNC_PW": "Zspace123"}
  }
}

Nginx 反向代理配置 (browser_arm_nginx.conf):

location /apps/chrome/ {
    access_by_lua_file "$lua_dir/auth_master.lua";  # 极空间 token 认证
    proxy_pass https://127.0.0.1:56901/apps/chrome/;
    proxy_set_header Authorization AUTH_PLACEHOLDER;
}

三步走:

  1. Lua 认证 — auth_master.lua 校验用户 token,提取用户身份
  2. Token 改写 — 把极空间的用户信息注入 Authorization 头
  3. 反向代理 — 把请求转发到容器实际端口

portainer 大概率用同样的方式集成:access_by_lua_file → proxy_pass http://127.0.0.1:9000。

辅助脚本体系

portainer 目录下还有 40+ 个 shell 脚本,是 Docker 操作的后端代理层:

脚本功能
docker_start.sh启动 Docker 引擎(dockerd + containerd + portainer)
docker_stop_container.sh停止单个容器
docker_download_image.sh下载/导入镜像
docker_pull_image_ex.sh从仓库拉取镜像
docker_load_image_ex.sh从文件加载镜像
docker_root_dir_remove.sh删除 Docker 数据目录
docker_root_size.sh查询数据目录大小
docker_proxy.shHTTP 代理配置
docker_check_root_dir.sh数据目录完整性检查
docker_report.shDocker 使用统计上报
clean_load_pull.sh清理拉取缓存
deal_fs.sh文件系统类型判断

这些脚本由 dockerm(C++ 进程,:8048)调度执行。

运行时容器

container/ 目录下有完整的 containerd 运行时:

文件大小说明
containerd38.9 MB标准 containerd 守护进程
containerd-shim7.2 MB容器生命周期 shim
containerd-shim-runc-v19.2 MBrunc v1 shim
containerd-shim-runc-v29.2 MBrunc v2 shim

所有二进制都是标准的 containerd 包(非自研)。

完整请求链路

用户在极空间 APP 点击"Docker"
    │
    ▼
OpenResty (:80/:5055)
    │ Lua auth_master.lua 校验 token
    ▼
location /abc (或 /docker 路由)
    │ proxy_pass
    ▼
Portainer (:9000)
    │ /api/endpoints/1/docker/...
    ▼
Docker Engine (dockerd, /var/run/docker.sock)
    │
    ▼
containerd → containerd-shim → runc → 容器进程

设备型号差异

启动脚本 docker_start.sh 里有设备型号判断:

这解释了为什么"ARM 版本的极空间没有 Docker 管理界面"——T2 上 Docker 引擎默认 inactive,ARM 低端型号更是直接被禁用的。


十、构建与工程推断

10.1 构建环境

10.2 版本管理

zdocker 版本号格式:V0.0.1(应用商店元数据中标记为 v0.0.1)

但构建产物的版本号体系遵循极空间统一规范:V0.2.YYYYMMDDNN

10.3 跨平台

zdocker 作为 Go 程序,自然支持交叉编译。从构建脚本看,它随极空间 monorepo 一起为 ARM64(z2/z4)和 AMD64(x86)构建。


十一、与其他 NAS 容器方案的对比

特性极空间 zdocker群晖 Container Manager威联通 Container Station
底层运行时Docker EngineDocker EngineDocker / LXC
应用商店自研,深度集成社区套件中心QNAP Store
Android 容器原生支持(AIC)不支持不支持
Compose 支持原生支持支持支持
Web UIportainer + 自研自研自研
定时任务内置 Cron需手动配置需手动配置
镜像加速器内置 + 自定义需手动配置需手动配置

极空间的核心差异化在于把 Docker 完全产品化:应用商店预定义了几十款常用容器应用,一键安装;Android 容器让 NAS 变身机顶盒/云手机;定时任务让用户像设置闹钟一样管理容器。


十二、关键发现汇总

  1. zdocker 的 Jenkins 源码路径:/var/jenkins_home/home/workspace/services/zdocker/release/online_t020/
  2. Docker SDK 版本:v27.3.1(较新)
  3. Android 升级服务器:https://aic-images.zenithspace.net/api/upgrade_check
  4. 应用商店 CDN:https://bwcap.zenithspace.net/AppStore/
  5. 镜像加速器:https://registry.zenithspace.net(默认)+ https://registry-1.docker.io
  6. 云手机默认端口:3999
  7. dockerm 是 C++ 写的,不是 Go
  8. zdocker 不直接监听端口,通过 baseset/go-baseset 代理
  9. 设备型号白名单控制应用兼容性(Z042, T020, Z023 等)
  10. 低端型号(Q2)禁用 Docker,内存不足时 containerd 被禁用

附:服务器文件来源(一手资料)

文件说明
/zspace/applications/services/zdocker/zdockerzdocker 主二进制
/zspace/applications/services/zdocker/config/*.dbSQLite 数据库
/zspace/applications/services/zdocker/default/*.json配置文件
/zspace/applications/services/zdocker/cloudphone_start.shAndroid 容器启动脚本
/zspace/applications/services/zdocker/aic/install.shAndroid 镜像升级脚本
/zspace/applications/services/baseset/dockermC++ 操作代理
/zspace/applications/services/portainer/image_default.json推荐镜像列表
/zspace/applications/services/portainer/shell/start_docker.shDocker 启动脚本
/zspace/applications/logs/zdocker/zdocker.log运行日志