OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 129

Distrobox 镜像与容器生命周期

用完整命令管理创建、进入、升级、删除与临时用户空间。

所在专题Distrobox:用户空间、桌面集成与可恢复环境 ↗
约 32 分钟阅读开始阅读

本文的命令接口按 Distrobox 1.8.2.5 官方脚本核对;镜像标签与发行版包名是示例,使用前确认镜像仍受支持、仓库可用及本机实际版本。示例未做运行验证。

本篇是 Distrobox 日常使用的手册式参考,涵盖镜像拉取、容器创建、进入退出、生命周期管理和特殊容器模式。所有命令均给出完整参数形式,每个 flag 均有中文解释。

1. 镜像管理#

镜像的来源

Distrobox 不自己维护操作系统镜像。它直接使用兼容 OCI(Open Container Initiative)标准的容器镜像,来源包括:

镜像源 示例 说明
Docker Hub ubuntu:24.04, archlinux:latest 默认源,无需指定 registry
Quay.io quay.io/toolbx/ubuntu-toolbox:24.04 Toolbx 系列专用镜像
GitHub Container Registry ghcr.io/ublue-os/arch-toolbox:latest Universal Blue 等社区维护
Fedora Registry registry.fedoraproject.org/fedora:40 Fedora 官方镜像

未指定 --image 时,Distrobox 使用配置的默认镜像,不会根据 --name ubuntu 自动猜 Ubuntu。名称与镜像是独立参数。正式环境应显式指定 image;版本 tag 仍可更新,严格固定需要镜像 digest 及包仓库快照。

拉取镜像

创建容器时,如果本地没有对应镜像,Distrobox 会自动从 registry 拉取:

# 创建容器时自动拉取镜像
distrobox create --name dev-ubuntu --image ubuntu:24.04

# 如果本地已有镜像,跳过拉取;若想强制重新拉取,使用 --pull
distrobox create --name dev-ubuntu --image ubuntu:24.04 --pull

也可以在创建容器前手动拉取:

# 使用 podman 拉取镜像(Distrobox 底层)
podman pull ubuntu:24.04
podman pull registry.fedoraproject.org/fedora:40
podman pull docker.io/archlinux:latest

# 使用 docker 拉取(如果容器后端是 Docker)
docker pull ubuntu:24.04

:latest tag 的风险 :latest 是浮动标签,每次拉取都可能得到不同版本。生产环境务必固定版本号:

  • 推荐:ubuntu:24.04
  • 避免:ubuntu:latest

Distrobox 1.7.0 对于不带 tag 的镜像会自动附加 :latest,所以 --image ubuntu 等价于 --image ubuntu:latest,同样不推荐。

查看已拉取的镜像

# 查看本地已有镜像(podman 方式)
podman images

# 查看本地已有镜像(docker 方式)
docker images

# 查看由 Distrobox 管理的容器列表(间接反映已用镜像)
distrobox list --verbose

distrobox list 不直接列出裸镜像,而是列出基于这些镜像创建的容器。要管理镜像本身,使用底层容器引擎命令(podman images / docker images)。


2. 容器生命周期(核心命令)#

这是每天都会用到的五组核心命令。掌握这些就足以完成日常 90% 的操作。

distrobox create —— 创建容器

完整语法:

distrobox create --name <名称> --image <镜像> [可选参数...]

建议显式指定的参数

Flag 长格式 说明
-n --name 容器名称,必须唯一。使用人类可读的名称(如 dev-ubuntu、gpu-box),不同于 Docker 的 hex hash
-i --image OCI 镜像地址。可以是 ubuntu:24.04、registry.fedoraproject.org/fedora:40 等完全限定名

常用可选参数

Flag 长格式 说明 示例
-H --home 为容器指定独立的 Home 目录,隔离 dotfiles --home ~/.distrobox/dev-home
-ap --additional-packages 首次初始化时安装的额外软件包列表 --additional-packages "build-essential curl git"
-Y --yes 跳过所有交互确认,直接创建 --yes
-p --pull 强制从 registry 重新拉取镜像(即使本地已存在) --pull
--init 在容器内启用 systemd / init 系统 --init
--volume 额外挂载目录到容器内,可多次使用 --volume /mnt/data:/data
-r --root 创建为 rootful 容器(不使用 rootless 模式) --root
--additional-flags 传递给底层容器引擎(podman/docker)的额外 flag --additional-flags "--dns 192.0.2.53"(文档示例地址,须替换)
--unshare-netns 不共享宿主网络命名空间,容器拥有独立网络栈 --unshare-netns
--unshare-ipc 不共享宿主 IPC 命名空间 --unshare-ipc
--unshare-process 不共享宿主 PID 命名空间 --unshare-process
--unshare-devsys 不从宿主导出 /dev 和 /sys 进入容器 --unshare-devsys

实际示例

# 1. 最简创建:名称 + 镜像
distrobox create --name mybox --image fedora:latest

# 2. 指定独立的 Home 目录(dotfiles 与宿主隔离)
distrobox create --name dev --image archlinux:latest \
  --home ~/.distrobox/dev-home

# 3. 创建时预装开发工具链
distrobox create --name gpu-box --image ubuntu:22.04 \
  --additional-packages "build-essential curl git vim"

# 4. 非交互式创建(脚本/自动化场景)
distrobox create --name test --image alpine:latest --yes

# 5. 创建带 systemd 的容器(运行 systemd 服务)
distrobox create --name server-box --image ubuntu:24.04 --init --additional-packages "systemd"

# 6. 挂载额外卷
distrobox create --name data-box --image ubuntu:24.04 \
  --volume /mnt/nas:/nas \
  --volume /mnt/scratch:/scratch

# 7. 从指定 registry 创建
distrobox create --name fedora-toolbox --image registry.fedoraproject.org/fedora-toolbox:40

# 8. 创建 rootful 容器(需要宿主机 root 权限)
distrobox create --name root-box --image ubuntu:24.04 --root

关于 --additional-packages Distrobox 会自动检测容器内发行版的包管理器(apt/dnf/pacman/apk/zypper 等),并用它安装你指定的包。通常无需再手动安装这些基础工具,但 create 本身只创建容器;包安装由首次 enter/初始化流程执行,assemble 的 start/export 操作也可能触发初始化。

--root vs rootless --root 让后端使用宿主 root 权限和独立的 rootful 容器存储;guest 的登录用户仍是另一个设置。绝大多数日常场景应使用默认的 rootless 模式(不加 --root),这与宿主用户权限一致,更安全。


distrobox enter —— 进入容器

完整语法:

distrobox enter <名称> [-- 命令 [参数...]]

参数说明

Flag 长格式 说明
-n --name 要进入的容器名称
-r --root 选择 rootful 后端的容器;并非切换 guest 用户为 root
--no-workdir 不自动切换到宿主当前的目录(默认行为:进入容器后自动 cd 到宿主当前路径对应的容器内路径)
-- (分隔符) 分隔符之后的内容作为要执行的单条命令,执行完成后退出容器,不进入交互式 shell

实际示例

# 1. 进入容器的交互式 shell
distrobox enter mybox

# 2. 普通容器内以 root 身份运行一个命令
distrobox enter mybox -- sudo whoami
# 若容器由 rootful 后端创建,访问时再选择 --root
# distrobox enter --root root-box

# 3. 在容器中执行单条命令后退出
distrobox enter mybox -- whoami

# 4. 在容器中执行带参数的命令
distrobox enter mybox -- python3 --version

# 5. 在容器中执行 shell 组合命令
distrobox enter mybox -- bash -c "sudo apt update && sudo apt upgrade -y"

# 6. 在容器中启动一个服务/应用
distrobox enter mybox -- code --new-window

# 7. 从容器中运行带管道和重定向的复杂命令
distrobox enter mybox -- bash -c "find /usr -name '*.so' | wc -l"

判断自己是否在容器内 进入容器后,以下环境变量可供判断:

  • $CONTAINER_ID —— 值为容器名称(如 mybox),容器外为空
  • $DISTROBOX_ENTER_PATH —— 进入容器时的宿主工作目录路径
  • hostname 输出会包含容器名称

你可以用 echo $CONTAINER_ID 快速确认当前是否在 Distrobox 容器内。

--no-workdir 的使用场景 默认情况下,distrobox enter 会尝试将当前宿主的 $PWD 映射到容器内的相同路径,并自动 cd 过去。这在以下场景非常方便:

cd ~/my-project   # 在宿主上
distrobox enter dev   # 进入容器后自动进入 ~/my-project

但如果该路径在容器内不存在(比如宿主的定制路径),Distrobox 会回退到 $HOME。此时用 --no-workdir 可以跳过这个自动映射行为。


distrobox list —— 查看容器

# 基本列表
distrobox list

# 调试输出(verbose 不等于更多业务列)
distrobox list --verbose

输出列含义

列名 含义
ID 底层引擎容器 ID 的短十六进制表示
NAME 容器名称(创建时指定的 --name,人类可读)
STATUS 运行状态:Up(运行中)或 Exited(已停止)
IMAGE 创建时使用的 OCI 镜像地址

输出示例:

ID           | NAME                 | STATUS                         | IMAGE
123abc       | dev-ubuntu           | Up 2 hours                     | ubuntu:24.04
456def       | gpu-box              | Exited (0) 3 days ago          | nvidia/cuda:12.4.1-devel-ubuntu22.04

日常操作用容器名称即可。列表的短 ID 来自底层 OCI 容器引擎,不是 Distrobox 自己分配的连续序号。


distrobox stop / distrobox rm —— 停止与删除

# 停止指定容器
distrobox stop mybox

# 停止所有容器
distrobox stop --all

# 删除指定容器(必须先停止)
distrobox rm mybox

# 强制删除(可删除运行中的容器,确认已备份)
distrobox rm mybox --force

# 删除所有已停止的容器
distrobox stop --all
distrobox rm --all
Flag 说明
--all stop/rm 都支持;仅作用于所选后端和 root 模式
--force / -f 强制删除(rm);跳过交互确认使用 --yes

删除前确认数据 distrobox rm 会永久删除该容器及其文件系统变更(不包含通过挂载共享的 Home 目录)。删除前确认:

  • 容器内的自定义配置是否已备份
  • 重要的未提交数据是否已转移到宿主

Home 目录默认是共享的,所以宿主 ~ 下的文件不会因删除容器而丢失。但如果使用了独立的 --home,该路径由你自行管理;--rm-home 会删除符合条件的自定义 home,需另行备份。rm 也会调用后端移除关联匿名卷,卷数据应单独确认。


distrobox upgrade —— 升级容器

# 升级单个容器内的所有软件包
distrobox upgrade mybox

# 升级所有容器
distrobox upgrade --all

upgrade 实际做了什么? Distrobox 自动检测容器内发行版,调用其原生包管理器执行 update + upgrade:

发行版 等价命令
Ubuntu / Debian apt update && apt upgrade -y
Fedora dnf upgrade -y
Arch Linux pacman -Syu --noconfirm
Alpine apk update && apk upgrade
openSUSE zypper update -y

升级目标是 guest 包数据库和文件系统,不会通过宿主包管理器升级 NixOS。包脚本仍可能访问共享 HOME、socket、网络或 host-exec;“完全隔离”不是安全保证。

Flag 说明
--all 升级所有已创建的容器
--root 升级 rootful 容器

3. 特殊容器模式#

Ephemeral 容器(一次性临时容器)

distrobox-ephemeral 创建用完即毁的容器,退出时自动删除临时容器;镜像缓存、共享 HOME、卷或宿主上的修改不会因此撤销。

完整语法:

distrobox-ephemeral --image <镜像> [可选参数] [-- 命令]

参数说明

distrobox-ephemeral 接受与 distrobox create 几乎相同的参数(--name, --image, --additional-packages, --home, --root 等),区别在于:

  • 不需要 --name(如果不指定,自动生成随机名称)
  • 退出后容器自动销毁,无需执行 distrobox rm

实际示例

# 1. 进入临时 Fedora 容器玩耍,exit 后容器消失
distrobox-ephemeral --image fedora:latest

# 2. 运行单个命令,执行完后自动退出并销毁
distrobox-ephemeral --image alpine:latest -- uname -a

# 3. 比较临时用户空间的发行版信息;不是安全沙箱
distrobox-ephemeral --image ubuntu:24.04 -- cat /etc/os-release

# 4. 临时容器中安装并运行一个工具,用完即走
distrobox-ephemeral --image python:3.12-slim \
  --additional-packages "ffmpeg" \
  -- python3 -c "import sys; print(sys.version)"

# 5. 在临时容器中 clone 仓库并做一次性编译测试
distrobox-ephemeral --name build-test --image ubuntu:24.04 \
  --additional-packages "gcc make git" \
  -- bash -c "git clone https://github.com/example/project /tmp/p && cd /tmp/p && make"

Ephemeral 的最佳使用场景

  • 可丢弃用户空间实验:仅测试可信程序;危险命令仍可能影响共享宿主数据
  • 一次性编译:拉取源码、编译、拿产物走人,不留下构建依赖
  • 版本对比:快速在不同发行版上运行同一命令对比行为
  • 工具隔离:临时需要一个未安装在宿主上的工具(如 ffmpeg),用完即弃

Ephemeral 容器每次创建都会从镜像全新启动,所以网络拉取开销取决于 --image 是否已在本地缓存。


distrobox-host-exec —— 从容器内调用宿主命令

这是一个特殊工具:你在容器内部时,可以借助它来执行宿主机上的命令。

完整语法(在容器内使用):

distrobox-host-exec <宿主的命令和参数>

实际示例

# 先从宿主进入容器
distrobox enter mybox

# === 以下命令在容器内部执行 ===

# 1. 在容器内打开宿主上的 Obsidian
distrobox-host-exec flatpak run md.obsidian.Obsidian

# 2. 在容器内查看宿主 systemd 用户服务状态
distrobox-host-exec systemctl --user status pipewire

# 3. 在容器内使用宿主安装的浏览器打开 URL
distrobox-host-exec firefox https://wiki.archlinux.org

# 4. 把容器内的数据通过宿主的工具处理
some-command | distrobox-host-exec wl-copy   # 复制到宿主 Wayland 剪贴板

# 5. 在容器内控制宿主 Flatpak 应用
distrobox-host-exec flatpak list
distrobox-host-exec flatpak run com.visualstudio.code

为什么需要 host-exec? Distrobox 容器的核心理念是与宿主高度集成(共享 HOME、X11/Wayland、D-Bus 等),但guest 的包数据库和运行服务与宿主分开;要操纵宿主 Flatpak 或 systemd 应使用明确的宿主调用,避免把 guest 的管理命令误当宿主操作。

distrobox-host-exec 就是这层"桥接":当你在容器内工作时,可以无缝调用宿主上的 GUI 应用、服务管理、剪贴板工具等。

它在容器内被实现为一个 shell 脚本,位于 /usr/bin/distrobox-host-exec(1.8.2.5 创建流程的 guest 注入路径)。

host-exec 使用 host-spawn 桥接,命令实际在宿主执行,权限和数据影响也属于宿主。若 guest 的工作目录是 /run/host/... 等宿主不存在的路径,需要明确选择宿主可用目录,而不是把 ENOENT 误判为程序未安装。

与宿主导出应用的对比

方式 方向 说明
distrobox-host-exec 容器 → 宿主 在容器内调用宿主命令
distrobox-export(下篇详述) 容器 → 宿主 把容器内的应用/二进制导出到宿主桌面

4. 日常使用技巧#

快速进入常用容器

每次输入 distrobox enter mybox 有点繁琐,可以设置 shell 别名:

# fish shell (~/.config/fish/config.fish)
alias db-dev="distrobox enter dev-ubuntu"
alias db-arch="distrobox enter arch-box"

# bash (~/.bashrc)
alias db-dev="distrobox enter dev-ubuntu"
alias db-arch="distrobox enter arch-box"

这样就可以用 db-dev 一键进入开发容器。

连续创建并进入

distrobox create 不会默认进入容器,--yes 也不是“创建后不进入”的开关。要连续创建并进入,应显式串联成功条件:

distrobox create --name newbox --image ubuntu:24.04 && distrobox enter newbox

create 成功只代表容器定义已建立;第一次 enter 才会启动和初始化。

判断容器内外的环境变量

前面提过的两个关键环境变量,在脚本中判断容器状态时非常有用:

# 判断是否在 Distrobox 容器内
if [ -n "$CONTAINER_ID" ]; then
    echo "当前在容器: $CONTAINER_ID"
else
    echo "当前在宿主环境"
fi

这一信息在自定义 shell prompt 时特别实用:

# 在 ~/.bashrc 或 ~/.config/fish/config.fish 中添加
# bash 版本
if [ -n "$CONTAINER_ID" ]; then
    PS1="📦 [$CONTAINER_ID] \w $ "
fi

# fish 版本
if set -q CONTAINER_ID; and [ -n "$CONTAINER_ID" ]
    function fish_prompt
        echo -n "📦 [$CONTAINER_ID] "(prompt_pwd)" \$ "
    end
end

文件共享与 Home 目录隔离

Distrobox 默认共享宿主 HOME 目录到容器中。这意味着:

  • 你在容器内执行 ls ~/Documents 看到的就是宿主上的文件
  • 在容器中 git clone 到 ~/projects/,回到宿主一样可见
  • 不同容器之间天然通过 HOME 目录共享文件

但共享 HOME 也有副作用:不同发行版的 dotfiles 会冲突。比如 ~/.bashrc 在 Arch 和 Ubuntu 上期望的配置可能不同。

解决方案:为不同发行版指定独立 HOME 目录。

# Arch 容器使用独立的 HOME
distrobox create --name arch-box --image archlinux:latest \
  --home ~/.distrobox/arch-home

# Ubuntu 开发容器使用另一个 HOME
distrobox create --name dev-ubuntu --image ubuntu:24.04 \
  --home ~/.distrobox/ubuntu-dev-home

独立 HOME vs 共享 HOME 的取舍

模式 优点 缺点
共享 HOME(默认) 文件天然互通,无需额外配置 发行版 dotfiles 可能互相干扰
独立 HOME(--home) dotfiles 干净隔离,适合多发行版并行 HOME 默认位置改变;宿主原 home 仍被挂载,非文件安全隔离

推荐策略:日常主力容器共享 HOME,特殊用途容器(如测试不同发行版行为)使用独立 HOME。

自定义 HOME + --volume:组织配置与项目路径

--home 改变 guest 的 HOME 与 dotfiles 默认位置,但 1.8.2.5 仍挂载宿主原 home,并可通过 DISTROBOX_HOST_HOME 标识它。因此以下 volume 用于额外提供便捷路径,不是重新打开唯一文件访问通道,也不是安全隔离:

distrobox create \
  --name arch \
  --image quay.io/toolbx/arch-toolbox:latest \
  --home ~/distrobox-homes/arch \
  --volume /home/user:/host-home

进入容器后:

  • cd ~ → 进入容器独立的 ~/distrobox-homes/arch
  • cd /host-home → 访问宿主机真实的家目录

为项目提供明确的挂载路径(不表示只暴露这一目录):

distrobox create \
  --name arch \
  --image quay.io/toolbx/arch-toolbox:latest \
  --home ~/distrobox-homes/arch \
  --volume /home/user/projects:/projects

显式共享配置文件(以下参数应附加在 create 命令中,guest 目标必须位于实际的自定义 HOME):

--volume "$HOME/.config/starship.toml:$HOME/distrobox-homes/arch/.config/starship.toml:ro"
--volume "$HOME/.config/fish:$HOME/distrobox-homes/arch/.config/fish:ro"

这样容器独立 home 的同时,仍能用上精调过的终端配置,减少配置冲突,同时保持文件访问便利。

在 distrobox.ini 中的写法(NixOS 用户常用):

xdg.configFile."distrobox/distrobox.ini".text = ''
  [arch]
  image=quay.io/toolbx/arch-toolbox:latest
  home=~/.local/share/distrobox-homes/arch
  volume=/home/user:/host-home
  volume=/home/user/projects:/projects
'';

清单字段是 volume,可重复声明或用空格列表;不是 additional_volumes 或分号列表。

关键注意点

  • --volume 默认读写,容器内修改会同步到宿主机。如只需只读加 :ro。
  • rootless Podman 下 UID 映射默认匹配,读写家目录一般没问题。
  • --home 决定 $HOME 指向哪,--volume 决定额外暴露哪些目录,两者独立可叠加。
  • 修改 ini 中的 volume 后,需 distrobox rm arch 重建容器才能生效。
  • 普通 distrobox rm arch 不会删除独立 home 目录(~/distrobox-homes/arch),只有加 --rm-home 才会。

容器内访问宿主硬件

Distrobox 默认会导出以下宿主资源到容器:

资源 导出方式 说明
GPU(包括 NVIDIA/AMD) 共享可见设备;NVIDIA 可选 --nvidia/CDI 驱动、库、权限和硬件支持须分别验证
声卡(PulseAudio/PipeWire) 共享 socket 容器内播放音频
显示器(X11/Wayland) 共享 socket GUI 应用窗口正常显示
USB 设备 /dev/bus/usb 挂载 部分 USB 设备可直接访问
D-Bus session bus 共享 socket 与宿主桌面服务通信

这些自动集成让 Distrobox 容器在感觉上非常接近"原生环境",不像传统 Docker 那样需要繁琐的 --device、--volume 手动挂载。


命令速查表#

任务 命令
创建容器 distrobox create -n <name> -i <image>
进入容器 distrobox enter <name>
进入 + 执行单条命令 distrobox enter <name> -- <command>
查看容器列表 distrobox list
启用调试输出 distrobox list --verbose
停止容器 distrobox stop <name>
停止所有容器 distrobox stop --all
删除容器 distrobox rm <name>
强制删除 distrobox rm <name> --force
升级容器 distrobox upgrade <name>
升级所有容器 distrobox upgrade --all
创建临时容器 distrobox-ephemeral -i <image>
临时容器执行命令 distrobox-ephemeral -i <image> -- <command>
容器内调用宿主命令 distrobox-host-exec <command>

下篇预告#

本篇覆盖了容器完整生命周期和日常操作。下一篇 应用导出与集成 将讲解如何将容器内的应用导出到宿主桌面——在容器内安装 VS Code、Firefox、任意 GUI 工具,然后像原生应用一样从宿主启动器打开。


参考与延伸

  1. Distrobox security implications ↗
  2. Distrobox create ↗
  3. Distrobox enter ↗
  4. Distrobox rm ↗
  5. Distrobox ephemeral ↗
  6. Distrobox host-exec ↗
  7. Distrobox list ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Distrobox:用户空间、桌面集成与可恢复环境

  1. 01Distrobox 核心原理:用户空间与宿主集成
  2. 02Distrobox 安装与后端配置
  3. 03Distrobox 镜像与容器生命周期
  4. 04Distrobox 导出的,到底是什么?
  5. 05Distrobox 桌面发现与后台服务集成
  6. 06Distrobox 声明式清单与高级工作流
  7. 07NixOS 上的 Distrobox:包环境与宿主路径
  8. 08Distrobox 备份:镜像、包清单与共享数据
  9. 09Distrobox 内部机制:包、配置与命令解析
CONTINUE READING / 下一篇Distrobox 桌面发现与后台服务集成

把 app/bin 导出的验证流程与独立的 init 服务生命周期分别处理。