本文讓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。
- 請先安裝 Docker,並啟動對應的系統服務。
sudo systemctl start docker
- 再來是Distrobox,許多發行版已收錄該套件。但請注意,有的發行版套件會自動使用Podman當後端,若想用Docker的話請改用指令稿安裝。
# Debian/Ubuntu
sudo apt install distrobox
# Fedora
sudo dnf install distrobox
# Arch/Manjaro
sudo pacman -S distrobox
# openSUSE
sudo zypper install distrobox
- 你也可以用下載作者指令稿的方式安裝Distrobox:
# 安裝到~/.local
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --prefix ~/.local
# 將Distrobox加入到PATH
echo "PATH=$PATH:$HOME/.local/bin" >> ~/.bashrc
使用Podman當後端#
如果您無法變更系統檔案,或是想要更安全的環境,使用rootless mode來安裝Distrobox。
如果要這麼做,請先以rootless模式安裝 Podman
再用指令稿安裝Distrobox:
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --next --prefix ~/.local
- 將以下路徑加入到
~/.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的容器。
- 下面是建立Debian 12的容器的最簡單語法。
--image
後面跟Docker指令寫法一樣,用debian:12
指定要拉取的映像檔版本。
distrobox create --name debian12 --image debian:12
可以用的旗標#
讓我們看一些重要的旗標(flags)。這些旗標可以疊加,為方便表示旗標我寫在最後面。
- 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
- Distrobox建立的容器預設是可以存取您家目錄下的所有檔案的,您可以用
--home
指定專門的家目錄來存放容器產生的檔案。
distrobox create --name debian12 --image debian:12 --home ~/distrobox/debian12
- 預設Distrobox建立的容器指令權限與目前您的使用者權限相同。如果您真的需要賦予Distrobox容器root權限,那就加上
--root
,不要使用sudo distrobox
distrobox create --name debian12 --image debian:12 --root
- 我們還可以給容器添加環境變數:
distrobox create --name debian12 --image debian:12 --additional-flags "--env EDITOR=vim"
- 或是設定預先要安裝的套件
distrobox create --name debian12 --image debian:12 --additional-packages "git tmux vim"
- 或是掛載Docker volume:
distrobox create --name debian12 --image debian:12 --volume /opt/my-dir:/usr/local/my-dir:rw
- 或是設定不要跟宿主機用一樣的網路IP:
distrobox create --name debian12 --image debian:12 --unshare-netns
- Distrobox內部可以使用init系統,包含systemd、OpenRC。例如加上
--init
讓容器預先安裝Systemd,便於控制服務。
distrobox create --name debian12 --image debian:12 --init --additional-packages "systemd libpam-systemd"
- 還可以利用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容器的範例#
- 這裡我建立一個Debian 12的容器,設定自訂家目錄路徑,啟用Nvidia驅動
distrobox create --name debian12 --image debian:12 --home ~/distrobox/debian12 --nvidia
按Enter建立容器,Distrobox會拉取映像檔。輸入
distrobox enter debian12
進入Debian的終端機,等待套件安裝完成。接著就能使用APT指令安裝套件了,容器裡的sudo不需要打密碼。
執行
nvidia-smi
也讀得到系統的Nvidia驅動資訊,所以容器裡面不用再裝驅動了如果你要登入容器後執行特定指令,請編輯容器家目錄下的
.bashrc
。這也是為何我要把容器家目錄跟宿主機家目錄分開的緣故。欲登出容器請打
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
建立容器的快捷啟動捷徑#
- 建立捷徑
distrobox generate-entry <容器名稱>
應用程式列表就會顯示該容器的圖示,點選會打開終端機
欲收回捷徑:
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
那樣。
- 寫一個
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
- 建立容器使用此指令
distrobox assemble create --file ./distrobox.ini
- 移除容器使用此指令
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來管理容器。