气泡包装容器示例

了解如何使用应用管理器与气泡包装容器一起使用。

Bubblewrap Container Example

注意:如果您想在Linux机器上构建示例,请阅读此

简介

此示例演示了如何在bubblewrap容器中启动应用程序以提高安全性。

先决条件:您已经熟悉在系统UI示例:"Hello World"!中介绍的的概念和主题。此示例使用相同的文件夹结构,并且可以以相同的方式启动。

Bubblewrap容器使用bwrap命令行工具在单独的内核命名空间中启动进程。这与Docker的工作方式类似,但优点是不需要运行额外的守护进程。Bubblewrap还用于Flatpak对应用程序进行沙盒。

配置

首先,我们需要选择哪些应用程序应使用bubblewrap容器。在此示例中,我们通过在am-config.yaml中设置选择键的通配符来将其用于所有示例。

containers:
  selection:
    - '*': bubblewrap

接下来,我们需要实际的容器配置。没有此配置,我们的应用程序将无法启动,并以类似以下错误的方式停止

bwrap: execvp /usr/bin/appman-launcher-qml: No such file or directory

这是因为bubblewrap容器的默认配置不将任何目录共享到新创建的内核命名空间中。这基本上意味着我们尝试在没有用户空间库的情况下启动应用程序。

容器配置的良好起点如下所示

containers:
  bubblewrap:
    configuration:
      symlink:
        usr/lib: '/lib'
        usr/lib64: '/lib64'
        usr/bin: [ '/bin', '/sbin' ]
      ro-bind:
        /usr/bin: '/usr/bin'
        /usr/lib: '/usr/lib'
        /usr/lib64: '/usr/lib64'
        /etc: '/etc'
        /usr/share/fonts: '/usr/share/fonts'
        /usr/share/fontconfig: '/usr/share/fontconfig'
        /usr/share/ca-certificates: '/usr/share/ca-certificates'
        /sys/dev/char: '/sys/dev/char'
        ${CONFIG_PWD}/imports: '${CONFIG_PWD}/imports'
      ro-bind-try:
        '/sys/devices/pci0000:00': '/sys/devices/pci0000:00'
        /usr/share/glvnd/egl_vendor.d: '/usr/share/glvnd/egl_vendor.d'
        /usr/share/X11/xkb: '/usr/share/X11/xkb'
        /run/resolvconf: '/run/resolvconf'
      dev: '/dev'
      dev-bind:
        /dev/dri: '/dev/dri'
      tmpfs:
        /tmp
      proc:
        /proc

我们配置容器使用我们自己的rootfs的一部分,并将它绑定挂载到内核命名空间中。以类似的方式,我们还配置它使用自己的tmpfsprocfs文件系统。

运行示例

启动示例时,您应该看到类似于此的窗口

一旦您按下左侧的其中一个图标,相应的应用程序就会被启动,其窗口将在右侧显示,类似于系统UI示例:"Hello World"!

第一个应用程序是浏览器,它使用QtWebengine显示Qt主页。第二个应用程序是网络信息,显示系统所有IP地址。最后但不仅限于,"Simple QML"应用程序显示一个按钮,可以用特定退出码退出进程。

快速启动

目前,当按下相应的按钮时,我们的所有应用程序都会启动。这涉及到启动一个新的容器进程,在这个容器进程内启动应用程序进程,然后应用程序进程开始加载应用程序的QML代码。

当快速启动启用时,后台会启动一个运行应用管理器QML启动器的容器。一旦应用需要启动,QML启动器只需要装载应用的QML代码即可。为了与bubblewrap容器正确配合,需要root权限,以便将正确的应用目录挂载到容器中。

在am-config.yaml中,快速启动的启用方式如下:

quicklaunch:
  runtimesPerContainer:
    bubblewrap:
      qml: 1
    '*': 0

要看到快速启动的实际效果,需要使用"sudo"命令启动示例。

网络隔离

与快速启动类似,另一个需要root权限的功能是网络隔离。目前容器拥有完整的网络访问权限。可以使用以下代码在am-config.yaml中配置网络访问:

containers:
  bubblewrap:
    sharedNamespaces: [ '-all', '+net' ]
    # You can use this script as a starting point. It has to be adapted to
    # your network setup though:
    # networkSetupScript: 'sudo "${CONFIG_PWD}/bubblewrap-network-setup.sh"'

如果应用根本不应有任何网络访问权限,可以将sharedNamespaces选项更改为[ '-all' ]。然后启动网络信息应用时,您会发现容器内不再有任何IP地址可用。同样,浏览器应用也没有网络访问。

另一种选择是将networkSetupScript设置为一个脚本的路径。此脚本将为每个容器执行,并可用于相应地设置网络设备。本例中提供的脚本会在主机上创建一个新的网络设备,并将此设备共享到容器中。现在,该新创建的网络设备可以在主机上进行桥接和过滤,而无需在容器内进行任何更改。

代码示例在 @ code.qt.io

© 2024 Qt公司。本文件内包含的文档贡献是各自所有者的版权。本文件所提供的文档是根据自由软件基金会发布的 GNU自由文档许可版1.3 的条款许可的。Qt以及相关的徽标是芬兰和/或其他国家/地区的 Qt公司的商标。所有其他商标归其各自所有者所有。