快轉到主要內容

我全都要!Distrobox使用教學,透過容器安裝其他Linux發行版的套件

Linux系統 虛擬機與容器技術 Distrobox Podman Linux Docker
🗓️ 民國112年 癸卯年
✍ 切換正體/簡體字
目錄

本文讓Ivon為您解說如何使用「Distrobox」建立容器,安裝其他Linux發行版的套件,文末附上更多實際應用例子。

Linux的容器系統,最常見的有Docker和Podman,一般用途都是來開發軟體或者跑服務吧。容器的設計,使得不同Linux發行版要跑起服務的成本低了許多。

既然容器具有跨發行版的特性,能不能進一步利用容器的特性,使用特定發行版的軟體呢?有沒有可能…在Ubuntu用pacman和DNF裝軟體又不跟系統的套件管理器衝突呢?

這正是「Distrobox」的理念。

Distrobox是由Luca Di Maio開發的程式,利用容器技術,能夠在一個Linux系統安裝其他發行版的套件,不管你想要APT、DNF、Yum、Pacman、Zypper、XBPS、Portage都難不倒它。更棒的是,不只純文字工具,連圖形應用程式都能裝來用,甚至能跑桌面環境!

其實,Distrobox就是Podman/Docker的前端啦,技術上來說不需要裝這個也能靠打指令達到一樣效果。不過Distrobox簡化了打指令建立容器的過程,只要幾行指令,便可快速建立特定Linux發行版的容器,存取該發行版的套件管理員。用Distrobox建立Linux容器的話較易於管理、備份、升級。

類似Distrobox的軟體有Fedora Silverblue內建的「Container Toolbox」,僅支援Podman。

1. 為什麼你會需要Distrobox
#

我需要那個酷東西
#

您需要的套件發行版尚未提供,不想拆deb、rpm包硬裝,更不想手動編譯軟體,且其他發行版有提供該套件的場合。

譬如,Ubuntu安裝Distrobox,建立Arch Linux的容器後,你就可以從包山包海的AUR安裝軟體,還可以把它加到桌面,像原生應用程式一樣啟動。

無需擔心弄壞宿主機系統!Distrobox不會把其他發行版的套件直接往您的系統塞,而是安裝到容器內部,需要的時候再拿二進位檔出來用即可。

還有,對於Debian Stable這類套件版本較舊的Linux發行版而言,Distrobox能夠裝到其他發行版提供的最新版軟體並加以利用,好比GCC,不用手動抓原始碼編譯。

就算你真的需要編譯軟體,也可以在容器裡面編譯測試,而不用怕弄壞宿主系統,跟用Docker開發軟體的原理是一樣的。

我的系統會咬我
#

Distrobox適合SteamOS(Steam Deck)、Fedora Silverblue、openSUSE MicroOS、VanillaOS、EndlessOS這類「immutable」的Linux發行版使用,這些發行版不會讓使用者動系統目錄;就算動了系統目錄一更新就會被覆蓋,所以得依賴容器技術來安裝軟體。除使用Flatpak外,缺少的套件可以從Distrobox的容器補充。

或者我們可以想像力更豐富一些:在Microsoft Windows的 WSL子系統裝DistroBox,這樣就不用開一堆複雜的WSL容器了。

低成本的distro-hopping
#

有人戲稱Distrobox為「Linux Subsystem for Linux」,寫作LSW,因為概念跟Microsoft的WSL(Windows Subsystem for Linux)很像。也有人認為,Distrobox是一種免虛擬機、最快速distro-hopping的一種方式。

根據 開發者的表格,Distrobox不需要特製映像檔,支援使用現有的Linux發行版映像檔,例如AlmaLinux、AmazonLinux、Alpine Linux、Arch Linux、CentOS、Debian、deepin、EndlessOS、Fedora Silverblue、Fedora、Gentoo、Manjaro、NixOS、openSUSE、SUSE Linux、Orcale Linux、SteamOS 3、RHEL、Rocky Linux 、Ubuntu、Void Linux等等。

你還在distro-hopping?所有Linux發行版我全都要 ~ 下圖為Distrobox作者示範的圖片。

當然容器環境還是跟虛擬機/實體機的功能差很多啦,不能這樣類比。

2. 使用Distrobox前的考量
#

Distrobox解決的是有distro-hopping經驗的Linux使用者會在意的問題。使用者必須知道如何調整workflow,懂得用容器工作。

使用Distrobox可以一定程度上削減宿主機的需求,再也不必為了跑特定發行版的程式而換系統。除了開發用途,Distrobox將其他發行版的圖形程式幹來用,但只將必要檔案暴露給宿主機,並與宿主機桌面環境整合的特性,使其成為第三方軟體的一個不錯補充來源。

安全性方面值得注意的是,雖然是容器,但Distrobox建立的容器預設可以存取家目錄、USB裝置、X伺服器/Wayland、SSH設定檔、系統日誌等,因此不算完全隔離的檔案系統。

至少跟 Flatpak相比,Distrobox容器並沒有明確的權限控管。它預設就是在目前的家目錄進入容器,僅容器本身的資料用docker volume另外儲存。

Distrobox可以選擇Docker或Podman當其後端,其中Podman支援rootless mode,適合無法變更系統檔案的發行版使用,整體限縮的權限也會較多。

3. 安裝Distrobox
#

使用Distrobox前要先在系統安裝Podman或Docker當做後端,注意二者可能會衝突。我使用的是Docker。

使用Docker當後端
#

如果您有sudo權限,就用系統套件管理員安裝Distrobox。

  1. 如果要這麼做,請先安裝 Docker,並啟動對應的系統服務。

  2. 再來是Distrobox,許多發行版已收錄該套件:

# Debian/Ubuntu
sudo apt install distrobox

# Fedora
sudo dnf install distrobox

# Arch/Manjaro
sudo pacman -S distrobox

# openSUSE
sudo zypper install distrobox
  1. 如果發行版沒收Distrobox,也可以用下載作者指令稿的方式安裝
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --next --prefix ~/.local

# 將Distrobox加入到PATH
echo "PATH=$PATH:$HOME/.local/bin" >> ~/.bashrc

使用Podman當後端
#

如果您無法變更系統檔案,或是想要更安全的環境,使用rootless mode來安裝Distrobox。

  1. 如果要這麼做,請先用Distrobox作者的指令稿安裝Podman
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/extras/install-podman | sh -s -- --prefix ~/.local
  1. 再用指令稿安裝Distrobox:
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --next --prefix ~/.local
  1. 將以下路徑加入到~/.bashrc
# Podman和Distrobox的路徑
PATH=$PATH:$HOME/.local/podman/bin:$HOME/.local/bin
# 允許所有應用程式顯示在螢幕上(需安裝xhost)
xhost +si:localuser:$USER

4. 用Distrobox建立持續性Linux容器
#

一切指令以 Distrobox開發者文件為主。

預設distrobox create建立的是持續性Linux容器,意即建立的容器在退出shell後仍會存在系統。

(如果指令顯示找不到,請嘗試把指令連在一起,如distrobox-create

直接打distrobox create不加任何參數,預設是建立一個最新版Fedora的容器。

  1. 下面是建立Debian 12的容器的最簡單語法。--image後面跟Docker指令寫法一樣,用debian:12指定要拉取的映像檔版本。
distrobox create --name debian12 --image debian:12

可以用的旗標
#

讓我們看一些重要的旗標(flags)。這些旗標可以疊加,為方便表示旗標我寫在最後面。

  1. Distrobox本身可以跑圖形應用程式。如果需要顯示卡加速,Intel/AMD顯示卡的用戶不需要特別裝什麼,但Nvidia用戶就有難了,除了Linux宿主機本身一定要裝Nvidia專有驅動外,建立Distrobox容器記得還要加上--nvidia旗標,容器裡面的程式才能使用宿主機的Nvidia顯示卡:
distrobox create --name debian12 --image debian:12  --nvidia

# 或者使用Nvidia Container Toolkit
distrobox create --name debian12 --additional-flags "--runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all" --image debian:12
  1. Distrobox建立的容器預設是可以存取您家目錄下的所有檔案的,您可以用--home指定專門的家目錄來存放容器產生的檔案。
distrobox create --name debian12 --image debian:12  --home ~/distrobox/debian12
  1. 預設Distrobox建立的容器指令權限與目前您的使用者權限相同。如果您真的需要賦予Distrobox容器root權限,那就加上--root,不要使用sudo distrobox
distrobox create --name debian12 --image debian:12 --root
  1. 我們還可以給容器添加環境變數:
distrobox create --name debian12 --image debian:12  --additional-flags "--env EDITOR=vim"
  1. 或是設定預先要安裝的套件
distrobox create --name debian12 --image debian:12 --additional-packages "git tmux vim"
  1. 或是掛載Docker volume:
distrobox create --name debian12 --image debian:12 --volume /opt/my-dir:/usr/local/my-dir:rw
  1. 或是設定不要跟宿主機用一樣的網路IP:
distrobox create --name debian12 --image debian:12 --unshare-netns
  1. Distrobox內部可以使用init系統,包含systemd、OpenRC。例如加上--init讓容器預先安裝Systemd,便於控制服務。
distrobox create --name debian12 --image debian:12 --init --additional-packages "systemd libpam-systemd"
  1. 還可以利用hook修改檔案,讓容器以proxy連線:

# 指定容器的代理
proxy=http://my_proxy.domain.example:3128

#設定容器初始化執行指令,替換掉apt套件庫
t="echo 'Acquire::http::Proxy \\\""${proxy}"\\\";' > /etc/apt/apt.conf.d/proxy.conf; echo 'Acquire::https::Proxy \\\""${proxy}"\\\";' >> /etc/apt/apt.conf.d/proxy.conf;"
http_proxy="${proxy}"

# 建立Debian容器,把上面的內容加入容器初始化的過程(--pre-init-hooks)
distrobox create --image debian:12 --name debian12 --pre-init-hooks "${t}"

建立Debian容器的範例
#

  1. 這裡我建立一個Debian 12的容器,設定自訂家目錄路徑,啟用Nvidia驅動
distrobox create --name debian12 --image debian:12  --home ~/distrobox/debian12 --nvidia
  1. 按Enter建立容器,Distrobox會拉取映像檔。輸入distrobox enter debian12進入Debian的終端機,等待套件安裝完成。

  2. 接著就能使用APT指令安裝套件了,容器裡的sudo不需要打密碼。

  3. 執行nvidia-smi也讀得到系統的Nvidia驅動資訊,所以容器裡面不用再裝驅動了

  4. 如果你要登入容器後執行特定指令,請編輯容器家目錄下的.bashrc。這也是為何我要把容器家目錄跟宿主機家目錄分開的緣故。

  5. 欲登出容器請打exit,重新登入請打distrobox enter debian12

登出後容器仍未停止,需輸入distrobox stop <容器名稱>完全停止容器。

要完全移除容器,輸入distrobox rm <容器名稱>

順帶一提,Distrobox的容器也可以用docker相關的指令來管理。

5. 建立Distrobox捷徑
#

distrobox-export指令可為容器裡面的應用程式建立捷徑,例如讓Debian的Firefox顯示在應用程式列表。

另一方面,distrobox generate-entry則是建立快捷啟動「Distrobox容器終端機」的捷徑。

建立單一應用程式捷徑
#

要執行容器裡面的圖形應用程式,從終端機啟動。

firefox-esr

啟動的應用程式應會自動啟用硬體加速,並且跟著系統主題變化。宿主機的輸入法應該也吃得到。

不過語言就得自行設定。

sudo apt install locales
sudo locale-gen zh_TW.UTF-8
sudo dpkg-reconfigure locales
sudo update-locale LANG="zh_TW.UTF-8" LANGUAGE="zh_TW"

在容器內執行distrobox-export指令建立應用程式捷徑:

# 只匯出應用程式,並帶入啟動引數,建立捷徑
distrobox-export --app firefox-esr --extra-flags "--private-window "

# 匯出二進位檔路徑,並帶入啟動引數,在/home/user/.local/bin建立wrapper以便宿主機其他程式利用(需自行加入PATH)
distrobox-export --bin /usr/bin/firefox-esr --extra-flags "--private-window" --export-path /home/user/.local/bin

隨後您的應用程式列表就會出現容器程式的捷徑了

要收回捷徑,使用以下指令

distrobox-export --app firefox-esr --delete
# 或者
distrobox-export --bin /usr/bin/firefox-esr --export-path home/user/.local/bin --delete

建立容器的快捷啟動捷徑
#

  1. 建立捷徑
distrobox generate-entry <容器名稱>
  1. 應用程式列表就會顯示該容器的圖示,點選會打開終端機

  2. 欲收回捷徑:

distrobox generate-entry  <容器名稱> --delete

6. 其他容器使用技巧
#

複製容器
#

複製容器可將現有的容器疊一層檔案系統上去,快速建立新的一個容器。在需要對該容器新增環境變數、entrypoint、家目錄的時候很有用。

在使用distrobox create指令時,加上--clone旗標,複製現有的debian12,新增一個叫做debian12-dev的新容器

# 停止原始容器
distrobox stop debian12

# 複製的時候需注意:旗標不會繼承,因此要開放Nvidia存取,這裡還是得加上去
distrobox create --clone debian12 --name debian12-dev --nvidia --home /home/user/distrobox/debian12-dev

建立用完就丟的容器
#

distrobox ephemeral 可建立暫時性的容器,此容器在命令完成後就會自動刪除,就像docker run --rm那樣。

語法為在--後面接上要容器執行的指令

distrobox ephemeral --image debian:12 -- cat /etc/os-release

distrobox ephemeral可以沿用distrobox create的旗標,例如掛載Docker volume給容器暫時存取:

distrobox ephemeral --image debian:12 --volume /opt:/opt -- touch /opt/file.txt

批次建立容器
#

distrobox aseemble透過讀取distrobox.ini檔案,按照裡面內容批次建立或移除容器。有點類似docker compose那樣。

  1. 寫一個distrobox.ini,填入要建立的容器內容
[ubuntu] #容器名字
additional_packages=git vim tmux nodejs
image=ubuntu:22.04
init=false
nvidia=false
pull=true
root=false
replace=true
start_now=false

[archlinux] #容器名字
additional_packages=git vim tmux nodejs
home=/tmp/home
image=archlinux:latest
init=false
start_now=true
init_hooks="touch /init-normal"
nvidia=true
pre_init_hooks="touch /pre-init"
pull=true
root=false
replace=false
volume=/tmp/test:/run/a /tmp/test:/run/b
  1. 建立容器使用此指令
distrobox assemble create --file ./distrobox.ini
  1. 移除容器使用此指令
distrobox assemble rm --file ./distrobox.ini

7. Distrobox設定檔位置
#

Distrobox的設定檔用於定義預設行為,設定檔路徑讀取順序如下:

  • /usr/share/distrobox/distrobox.conf
  • /usr/etc/distrobox/distrobox.conf
  • /etc/distrobox/distrobox.conf
  • ${HOME}/.config/distrobox/distrobox.conf
  • ${HOME}/.distroboxrc

我是以放在~/.config/distrobox/distrobox.conf的為優先,若該檔案不存在請自行新增:

mkdir ~/.config/distrobox
vim ~/.config/distrobox/distrobox.conf

該設定檔可以設定Distrobox的預設行為,例如:

# 自動拉取映像檔
container_always_pull="1"
# 自動在應用程式建立容器的捷徑
container_generate_entry=1
# 設定要使用的後端
container_manager="podman"
# distrobox create指令不加任何旗標,預設使用的發行版映像檔
container_image_default="registry.opensuse.org/opensuse/toolbox:latest"
# 預設容器名稱
container_name_default="test-name-1"
# 預設容器家目錄
container_user_custom_home="$HOME/.local/share/container-home-test"
# 自訂的init hook指令稿
container_init_hook="~/.local/distrobox/a_custom_default_init_hook.sh"
# 自訂的pre init hook指令稿
container_pre_init_hook="~/a_custom_default_pre_init_hook.sh"
# distrobox create指令額外加上的旗標
container_manager_additional_flags="--env-file /path/to/file --custom-flag"
non_interactive="1"
skip_workdir="0"
PATH="$PATH:/path/to/custom/podman"

8. 圖形化界面管理容器
#

如果您使用Docker當Distrobox後端,則市面上任一Docker的圖形界面都可以用來管理Distrobox所建立的容器,例如 Portainer

如果您使用Podman當後端,請安裝 Pods Flatpak來管理容器。

9. Distrobox實際應用例子
#

Ubuntu安裝Arch Linux的AUR套件

容器跑GNOME桌面環境

容器跑QEMU/KVM虛擬機

VScode整合容器環境

在Windows WSL跑Distrobox

另請參閱
#

相關文章

不只Ubuntu!Windows WSL用Distrobox裝多重Linux容器
Linux系統 虛擬機與容器技術 Distrobox Windows Subsystem for Linux Docker
Distrobox使用例:Docker跑GNOME X11桌面環境
Linux系統 虛擬機與容器技術 Distrobox GNOME Docker
Linux系統各發行版安裝Docker Engine教學
Linux系統 虛擬機與容器技術 Docker Linux

留言板

此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。要討論程式碼請用Giscus,匿名討論請用Disqus。

這是Giscus留言板,需要Github帳號才能留言。支援markdown語法,若要上傳圖片請貼Imgur連結。您的留言會在Github Discussions向所有人公開。

這是Disqus留言板,您可能會看到Disqus強制投放的廣告。有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。