欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/

欢迎在PC社区平台申请新建项目: https://atomgit.com/OpenHarmonyPCDeveloper

本文以 ohos_Docker 为对象,按“为什么这样拆分、代码如何连接、运行时边界在哪里、目前验收到什么程度”的顺序,记录 HarmonyOS PC Docker 桌面工作台的适配过程。文中把 Demo、Local、Remote 三种模式放在同一套领域接口下说明,并明确区分代码实现、HAP 构建、设备运行和 OEM 运行时验收,避免把界面完成误写成 Linux 容器运行时已经随应用交付。

image.png

一、先明确要移植的是桌面工作流,不是 Linux 内核

Docker Desktop 看起来是一个桌面程序,真正支撑容器运行的却是一整条 Linux 技术栈:内核命名空间、cgroup、OverlayFS、虚拟网络、镜像存储、containerd、BuildKit 和特权进程。HarmonyOS PC 应用层无法直接获得这台 Linux 主机的全部能力,所以适配的第一件事不是画界面,而是把“桌面工作流”和“容器运行时”分开。

Docker Desktop 本体没有开源,本文讨论的 ohos_Docker 也不是对闭源二进制的直接移植。项目依据 Docker Desktop 的公开文档、Docker Engine API、Moby 和 Docker CLI 等公开能力,独立实现一套鸿蒙原生桌面管理客户端。它保留用户熟悉的容器、镜像、Compose、卷、构建、Kubernetes、模型和设置路径,但不会把 Linux 内核塞进 HAP。

**项目边界:**ArkUI 负责信息架构、编辑、状态和交互;Docker Engine API 负责标准容器操作;本地 VM、虚拟网络、镜像数据盘、更新和特权桥由设备或 OEM 受信组件提供。

这种划分意味着应用可以在没有真实 Linux Runtime 的情况下进入 Demo 模式,完整走通页面、模型、错误态和交互;连接真实环境时,再把同一套领域接口切换到 Local Runtime 或 Remote Engine。对于需要在鸿蒙 PC 上长期使用的工具来说,这种可替换后端比“先写死一个本地 Docker 地址”更接近产品结构。

二、把 Docker Desktop 拆成可以分别验证的层

工程没有把 Docker Desktop 的每个页面直接绑定到 HTTP 请求,而是先定义领域服务,再由基础设施适配器实现。这样,页面只描述“列出容器”或“拉取镜像”,不关心请求最终来自模拟运行时、远程 Engine,还是经过 OEM 桥的本地 VM。

image.png

层次主要职责典型实现
ArkUI 与功能页窗口、导航、列表、表单、键盘和状态反馈Containers、Images、Volumes、BuildKit、Settings
应用层组合多个服务,维护当前模式、选中对象和页面生命周期DockerDesktopApp
领域层定义与 UI、HTTP 无关的 Docker 能力DockerEngineService
基础设施层协议映射、错误翻译、流式日志、TLS 和桥接请求Mock 与 Remote 适配器
宿主运行时真正运行 Linux 容器和处理特权操作VM、containerd、BuildKit、OEM Bridge

模式切换集中在一个运行时工厂中。Demo 模式创建确定性的内存状态;Local 模式先解析本地运行时端点,再按 Remote Engine 的方式协商 API 版本;Remote 模式直接验证用户配置的 Engine。以下代码来自 DockerRuntimeManager.ets

if (config.mode === RuntimeMode.DEMO) {
  return new MockDockerEngineService(...);
}
let engineConfig = config.mode === RuntimeMode.LOCAL ?
  await this.localEngineConfig(config) : config;
let probe = new RemoteDockerEngineService(engineConfig);
let info = await probe.getEngineInfo();
return new RemoteDockerEngineService(engineConfig, info.apiVersion);

对测试而言,Mock 不是简单的假数据。它要维持容器与 Compose、镜像与标签、卷与导出任务之间的一致性,才能验证页面在真实操作序列中的状态变化。对生产而言,Remote 适配器则不能绕开领域接口直接暴露任意 HTTP 请求,否则 Demo 与真实模式很快会出现两套行为。

三、ArkTS 客户端如何连接真实 Docker Engine

客户端与真实 Docker 的接口集中在 DockerEngineService。接口包含容器生命周期、日志跟随、Exec、文件系统、镜像传输、Registry 凭据和卷管理;页面拿到的都是经过建模的类型,而不是无约束的 JSON。

export interface DockerEngineService {
  getEngineInfo(): Promise<EngineInfo>;
  listContainers(): Promise<ContainerInfo[]>;
  startContainer(id: string): Promise<void>;
  followContainerLogs(id: string, tail: number,
    listener: ContainerLogStreamListener): ContainerLogStream;
  execContainer(id: string, command: string[]): Promise<ContainerExecResult>;
  pullImageWithProgress(reference: string,
    credential: RegistryCredential,
    listener: ImageTransferProgressListener): ImageTransferOperation;
}

RemoteDockerEngineService 把这些方法翻译成 Docker Engine REST 请求。API 版本先通过 /version 协商,后续请求统一带版本前缀;容器状态、端口、Compose Label 和镜像层信息在适配器中转换,不能直接穿透到页面。

async getEngineInfo(): Promise<EngineInfo> {
  let version = JSON.parse(await this.request(
    '/version', http.RequestMethod.GET, false));
  return new EngineInfo(true, version.Version,
    version.ApiVersion, version.Os);
}

async listContainers(): Promise<ContainerInfo[]> {
  let data = JSON.parse(await this.request(
    '/containers/json?all=true', http.RequestMethod.GET));
  // 将 Id、Names、State、Ports 和 Compose labels
  // 转换为 ContainerInfo 领域模型
}

Registry 凭据同样不会变成任意请求头。适配器只在镜像拉取、推送等必要路径中编码 X-Registry-Auth;如果用户选择记住登录状态,则交给 HarmonyOS Asset Store 受保护存储。演示模式、远程模式和本地模式共享同一接口,因此 UI 不需要判断“当前是不是 Mock”。

四、本地运行时为什么必须依赖 OEM 受信桥

Local Runtime 是这两个项目里最容易产生误解的部分。HarmonyOS UI 代码不等于 Linux 容器运行时,API 24 也没有公开可供普通 ArkTS 应用直接调用虚拟机的 Hypervisor API。应用可以管理一套运行时,但不能凭自身权限创建内核、挂载数据盘或修改虚拟网络。

因此,Local 模式把职责交给设备或 OEM 提供的受信桥。桥不接收“执行某条宿主命令”这类开放式请求,而是暴露固定语义的类型化接口:

GET  /v1/runtime
GET  /v1/runtime/metrics
POST /v1/runtime/start
POST /v1/runtime/stop
POST /v1/runtime/pause
POST /v1/runtime/resume
POST /v1/runtime/restart
PUT  /v1/runtime/resources

运行时响应包含状态、Engine 端点、数据盘、CPU、内存、交换空间和 Resource Saver,但不返回宿主进程列表或任意主机路径。生命周期变更必须串行化,失败时回到明确的 errorstopped 状态。资源调整由客户端提供有界数值,真正的事务、重启和回滚仍由桥完成。

客户端负责

  • 模式和资源配置

  • 状态轮询与错误呈现

  • Engine API 协商

  • 不保存宿主特权凭据

OEM 桥负责

  • Linux VM 和镜像数据盘

  • 虚拟网络与文件共享

  • 签名更新及 A/B 回滚

  • 特权命令和宿主路径隔离

**不要把“本地模式可切换”理解成“鸿蒙应用内置了 Docker”。**当前仓库实现了客户端与受控桥契约,生产交付仍依赖目标设备的 OEM 运行时组件。

五、从容器列表到 Exec 终端:一条请求怎样走完

以“启动一个容器”为例,用户点击按钮后,页面不会拼出一条 Docker 命令。它调用领域服务的 startContainer(id),Remote 适配器再向 Engine API 发送请求;成功结果与引擎快照回到应用层,容器列表随即更新。

项目内的 README.OpenHarmony_CN.md 记录环境、构建、安装和验收范围;docs/ARCHITECTURE.md 描述依赖方向;docs/DOCKER_DESKTOP_PARITY.md 对照桌面功能;docs/DOCKER_DESKTOP_BRIDGE.md 定义本地运行时、终端、卷和特权能力桥接。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐