Flatpak 应用打包完整教程 / 第 1 章:Flatpak 概述
第 1 章:Flatpak 概述
本章目标:理解 Flatpak 的设计哲学、核心技术架构,以及它在 Linux 打包生态中的定位。
1.1 什么是 Flatpak
Flatpak(读作 “flat-pack”)是一个用于构建、分发和运行桌面应用的框架。它由 Alexander Larsson 于 2015 年发起(最初名为 xdg-app),现由 Flatpak 社区 维护,被 Fedora、Linux Mint、Endless OS 等主流发行版默认采用。
核心设计目标
| 设计目标 | 说明 |
|---|---|
| 跨发行版 | 同一个 Flatpak 包可在 Ubuntu、Fedora、Arch 等任意发行版运行 |
| 沙箱隔离 | 应用运行在独立沙箱中,限制对宿主系统的访问 |
| 运行时复用 | 通过共享运行时 (Runtime) 避免重复依赖 |
| 去中心化 | 不绑定特定商店,任何人可托管仓库 |
| 版本独立 | 应用可携带或锁定特定版本的依赖 |
Flatpak 的名字来源
flatpak = flat (扁平化) + pack (打包)
寓意:将复杂的依赖关系"扁平化"为一个独立、自包含的包。
1.2 沙箱模型
Flatpak 的核心安全机制是基于 Bubblewrap 的 Linux 命名空间 (Namespace) 沙箱。
沙箱提供的隔离层
┌─────────────────────────────────────────────┐
│ Flatpak 应用 │
│ ┌────────────────────────────────────────┐ │
│ │ 应用代码 + 依赖库 │ │
│ ├────────────────────────────────────────┤ │
│ │ 运行时 (Runtime) │ │
│ ├────────────────────────────────────────┤ │
│ │ Bubblewrap 沙箱 │ │
│ │ • PID 命名空间 (进程隔离) │ │
│ │ • Mount 命名空间 (文件系统隔离) │ │
│ │ • Network 命名空间 (网络隔离) │ │
│ │ • IPC 命名空间 (D-Bus 过滤) │ │
│ └────────────────────────────────────────┘ │
│ ↕ Portal API │
│ ┌────────────────────────────────────────┐ │
│ │ 宿主系统 (Host) │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
沙箱默认行为
| 资源 | 默认权限 | 说明 |
|---|---|---|
| 文件系统 | ❌ 不可访问 | 只能访问应用私有目录和 ~/.var/app/<app-id>/ |
| 网络 | ✅ 允许 | 默认可访问网络(可通过 --unshare=net 禁用) |
| 宿主命令 | ❌ 不可执行 | 无法直接调用宿主系统命令 |
| D-Bus | 受限 | 会话总线 (Session Bus) 受过滤,系统总线 (System Bus) 默认不可访问 |
| 设备 | ❌ 不可访问 | 默认无法访问 GPU、摄像头等设备(可通过权限声明开启) |
Portal API
Portal 是 Flatpak 沙箱应用与宿主系统交互的标准化接口。它由 xdg-desktop-portal 提供,常见操作包括:
- 文件选择:
org.freedesktop.portal.FileChooser - 打印:
org.freedesktop.portal.Print - 通知:
org.freedesktop.portal.Notification - 截图:
org.freedesktop.portal.Screenshot - 设置:
org.freedesktop.portal.Settings
# 查看当前系统可用的 Portal 实现
ls /usr/share/xdg-desktop-portal/portals/
# 检查 Portal 服务状态
systemctl --user status xdg-desktop-portal.service
1.3 与其他打包格式的对比
1.3.1 Flatpak vs Snap
Snap 由 Canonical(Ubuntu 母公司)开发,目标与 Flatpak 类似但侧重不同。
| 对比维度 | Flatpak | Snap |
|---|---|---|
| 发起方 | 社区驱动 | Canonical 主导 |
| 后端存储 | OSTree | SquashFS + Store |
| 沙箱技术 | Bubblewrap (namespaces) | AppArmor + Seccomp |
| 服务器端 | 去中心化 (任何人可架设) | 集中式 (snapcraft.io) |
| 默认仓库 | Flathub | Snap Store |
| 桌面应用 | ✅ 专注桌面 | 桌面 + 服务器 + IoT |
| 自动更新 | 由桌面环境管理 | 强制自动更新 (可延期) |
| Delta 更新 | ✅ OSTree 增量传输 | ✅ 差量更新 |
| 服务端运行 | ❌ 不适合 | ✅ 支持 daemon/service |
| 主要采用 | Fedora, Linux Mint, Endless OS | Ubuntu, Ubuntu 衍生版 |
选择建议:
- 纯桌面应用 → 优先 Flatpak(社区更开放、Flathub 生态更成熟)
- 服务器/CLI 工具 → 优先 Snap(原生支持 daemon 模式)
- 已有 Ubuntu 用户基础 → 两者都发布
1.3.2 Flatpak vs AppImage
| 对比维度 | Flatpak | AppImage |
|---|---|---|
| 安装方式 | 需要 flatpak 运行时 | 双击运行,无需安装 |
| 沙箱 | ✅ 完整沙箱 | ❌ 无沙箱 (除非手动用 Firejail) |
| 依赖共享 | ✅ 运行时复用 | ❌ 每个包内嵌全部依赖 |
| 磁盘效率 | 高(共享运行时) | 低(重复依赖) |
| 更新机制 | ✅ 内置增量更新 | 需第三方工具 (AppImageUpdate) |
| 系统集成 | ✅ 自动注册 .desktop | 需手动集成 (或用 appimaged) |
| 适用场景 | 长期维护的桌面应用 | 便携式工具、一次性分发 |
1.3.3 三者总览
沙箱安全 跨发行版 磁盘效率 更新机制 服务器支持
Flatpak ★★★★★ ★★★★★ ★★★★☆ ★★★★★ ★☆☆☆☆
Snap ★★★★☆ ★★★★☆ ★★★★☆ ★★★★★ ★★★★★
AppImage ★☆☆☆☆ ★★★★★ ★★☆☆☆ ★★☆☆☆ ★☆☆☆☆
1.4 Flatpak 的技术架构
组件层次
┌──────────────────────────────────────────────────┐
│ 用户 │
│ (通过 CLI 或 GUI) │
├──────────────────────────────────────────────────┤
│ flatpak (CLI 工具) │
├──────────────┬──────────────┬────────────────────┤
│ flatpak-builder │ libostree │ Bubblewrap │
│ (构建工具) │ (版本化存储)│ (沙箱运行) │
├──────────────────┴──────────────┴────────────────┤
│ OSTree 仓库 │
│ (应用、运行时、扩展 的版本化存储) │
├──────────────────────────────────────────────────┤
│ Linux 内核 (namespaces, cgroups) │
└──────────────────────────────────────────────────┘
关键术语
| 术语 | 英文 | 说明 |
|---|---|---|
| 应用 | Application | 最终用户安装运行的程序 |
| 运行时 | Runtime | 应用依赖的基础库集合 (如 GNOME Runtime) |
| SDK | Software Development Kit | 用于构建应用的开发工具运行时 |
| 扩展 | Extension | 可选的附加组件 (主题、编解码器等) |
| 清单 | Manifest | 描述应用构建过程的配置文件 |
| 远程仓库 | Remote | 托管 Flatpak 包的 OSTree 仓库 |
| Flatpak Builder | flatpak-builder | 自动化构建 Flatpak 的工具 |
1.5 适用场景分析
✅ 推荐使用 Flatpak 的场景
| 场景 | 原因 |
|---|---|
| 桌面 GUI 应用 | Flatpak 专为桌面应用设计,Portal API 提供原生体验 |
| 需要特定依赖版本 | 应用可捆绑特定版本的库,不受系统版本影响 |
| 跨发行版分发 | 一次构建,所有主流发行版可用 |
| 安全敏感应用 | 沙箱隔离保护用户数据 |
| 独立开发者 | 无需为每个发行版维护单独的包 |
❌ 不推荐使用 Flatpak 的场景
| 场景 | 原因 | 替代方案 |
|---|---|---|
| 系统级服务/守护进程 | 沙箱限制不适合系统服务 | RPM/DEB 包 |
| CLI-only 工具 | Flatpak 面向桌面应用 | Snap 或 AppImage |
| 内核模块 | 无法在沙箱中运行 | DKMS 或原生包 |
| 对性能极度敏感 | 沙箱有一定开销 | 原生编译 |
1.6 业务场景
场景 1:跨发行版商业软件分发
一家小型 ISV(独立软件供应商)开发了一款视频编辑工具,需要支持 Ubuntu、Fedora、Arch 等发行版。传统方式需要维护至少 3 套 DEB/RPM 打包脚本。使用 Flatpak 后:
- 只需维护一份 Manifest
- 通过 Flathub 触达数百万 Linux 用户
- 沙箱保护用户文件,符合安全审计要求
场景 2:企业内部工具分发
企业开发了内部使用的桌面客户端,需要安全地分发到员工的 Linux 工作站:
# 搭建私有 Flatpak 仓库
ostree init --repo=/srv/flatpak-repo --mode=archive-z2
# 从私有仓库安装
flatpak remote-add --no-gpg-verify internal-repo https://flatpak.example.com/repo/
flatpak install internal-repo com.example.InternalTool
1.7 实验:体验 Flatpak 沙箱
# 1. 安装一个简单的 Flatpak 应用
flatpak install flathub org.gnome.Calculator
# 2. 查看应用的沙箱权限
flatpak info --show-permissions org.gnome.Calculator
# 3. 运行应用并观察沙箱
flatpak run --verbose org.gnome.Calculator
# 4. 在沙箱内打开一个 shell
flatpak run --command=bash org.gnome.Calculator
# 此时你已在沙箱中,尝试以下命令:
ls / # 注意:看到的不是宿主根目录
cat /etc/os-release
exit
1.8 注意事项
⚠️ Flatpak 不是容器
虽然 Flatpak 使用了类似容器的命名空间技术,但它不是 Docker/LXC 那样的通用容器。Flatpak 专注于桌面应用的打包与分发,不提供完整的操作系统环境。
⚠️ 运行时版本兼容性
Flatpak 运行时有明确的版本生命周期。如org.freedesktop.Platform//22.08已于 2024 年停止安全更新。发布应用时请使用当前受支持的运行时版本。
⚠️ 性能开销
沙箱带来的性能开销通常可以忽略不计(< 1%)。但频繁的文件系统访问(如编译大型项目)可能会因挂载命名空间略有延迟。