VPS 上如何安裝與執行 Incus system container
了解 Incus system container 與 Docker 的差異,並在 VPS 上完成虛擬化檢查、storage pool、網路設定,避開常見故障。
Incus system container 是什麼
VPS 上的 Incus system container 會提供一台具備自身 init system 與使用者帳號的完整機器,而不是只執行單一程序並附帶檔案系統。容器會開機、以 PID 1 執行 init,並回應 systemctl。它共用主機的 kernel,因此不是虛擬機器。除了 kernel 以外的部分,行為都像一台獨立機器。
Incus 是 LXD 的社群分支,由 Linux Containers 專案維護。其用戶端命令是 incus。傳入 --vm 時,它也能透過 QEMU 執行真正的虛擬機器;但 system container 才是多數人安裝它的原因,也是本指南其餘內容的主題。
Docker 比較為何容易誤導
Docker 封裝單一程序。Incus 封裝一個作業系統。Incus 文件直接說明兩者的區別:「應用程式容器(例如 Docker 提供的容器)會封裝單一程序或應用程式。另一方面,系統容器會模擬完整的作業系統,類似於主機上或虛擬機器中執行的作業系統。」
這項差異會改變你每天管理容器的方式。
- Docker image 沒有 init,因此其中的
systemctl會失敗。Incus 容器會執行 init system,因此服務與 timer 的運作方式和伺服器相同。 - Docker 容器設計上應從 Dockerfile 摧毀並重新建置。Incus 容器設計上應保留、套用修補程式並建立 snapshot。
- Docker image 是要推送到 registry 的建置產物。Incus instance 是 storage pool 中磁碟上的狀態,應使用
incus export搬移。 - Docker 隔離工作負載。Incus 隔離機器,因此單一容器可以容納多個工作負載與多個使用者帳號。
你可以在 Incus system container 中執行 Docker。不應在 Docker application container 中執行 Incus。如果你實際需要的是每個容器執行一個程序,並搭配 image build 步驟,請先閱讀 VPS 上的 Podman 與 Docker 以進行比較。如果你需要每個工作負載使用獨立的 kernel,而不是共用 kernel,請參閱 VPS 上的 Firecracker microVM。
Incus 能在 VPS 內執行嗎?
這取決於 VPS 的虛擬化類型和核心,因此請在安裝任何元件前先確認這兩項。不要只相信供應商的行銷頁面。請在該主機上執行以下 4 個命令。
systemd-detect-virt
uname -r
stat -fc %T /sys/fs/cgroup
cat /sys/fs/cgroup/cgroup.controllers輸出 systemd-detect-virt、kvm 或 qemu,表示 VPS 是使用自身核心的虛擬機器。這是較簡單的情況,因為 Incus 的行為會與在實體硬體上執行時相同。輸出 lxc、lxc-libvirt 或 openvz,表示 VPS 本身是與供應商共用核心的容器。這種情況下,Incus 容器屬於巢狀容器,只有供應商在你的容器上啟用巢狀功能時才能運作。你無法從容器內啟用這項功能,因為相關設定位於你無法控制的主機上。
stat -fc %T /sys/fs/cgroup 應輸出 cgroup2fs。輸出其他內容表示該主機使用 cgroup(control group)v1 或 hybrid 版面配置,而目前的 Incus 並未以此為目標。
cat /sys/fs/cgroup/cgroup.controllers 會列出分派給你的 control-group controller。Incus 文件將 blkio、cpuset、devices、freezer、memory 和 pids 列為必要項目。在巢狀 VPS 上,這份清單通常比 KVM 短,因為供應商會決定要下放哪些 controller。檔案中缺少的 controller 是 Incus 無法使用的 controller,因此依賴該 controller 的執行個體限制也無法提供給你。
核心版本的重要性比以往更高。截至 August 2026,Incus 文件針對上游維護的兩個分支,列出不同的最低版本。6.0 LTS(long term support)分支表示:「支援的最低核心版本為 5.4。」目前的 stable 分支表示:「支援的最低核心版本為 6.12。」Ubuntu 24.04 在自有 repository 中提供 6.0 LTS 系列,並搭配 6.8 核心,這是受支援的組合。若在相同的 6.8 核心上,從 upstream repository 安裝目前的 stable build,版本就低於文件所列的最低要求,因此請先閱讀 uname -r,再選擇 repository。
如果你的目標是完整虛擬機器而非容器,限制條件會不同,而且更嚴格。請參閱 VPS 上的巢狀虛擬化,確認 VPS 是否能提供 /dev/kvm;如果你擁有硬體,請參閱 租用 VPS 上的 Proxmox。
在 Ubuntu 或 Debian 上安裝 Incus
Debian 13、Ubuntu 24.04 及更新版本會在各自的套件庫中提供 Incus。
sudo apt update
sudo apt install -y incus在 Debian 上,incus-base 會安裝容器支援,但不包含虛擬機器功能。在 Ubuntu 上,如果也需要 --vm 執行個體,請加入 qemu-system。
如果需要的版本比發行版提供的版本新,上游套件位於 pkgs.zabbly.com。以下指令來自該專案自行維護的套件庫 README。
sudo apt update && sudo apt install -y curl
sudo mkdir -p /etc/apt/keyrings/
sudo curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
sudo sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/stable
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
sudo apt-get update
sudo apt-get install -y incus接著讓您的使用者存取 daemon socket。
sudo usermod -aG incus-admin "$USER"
newgrp incus-admin
incus infoincus info 列出伺服器設定,表示 socket 可正常運作。權限錯誤表示群組變更尚未套用到目前的 shell;newgrp incus-admin 可套用到目前的 shell,而重新登入才能正確套用。請將 incus-admin 的成員資格視同主機上的 root 權限,因為存取該 socket 等同完全控制以 root 執行的 daemon。部分發行版也會建立一般的 incus 群組,供受限的使用者存取。
現在初始化 daemon。
sudo incus admin init請回答這些問題,不要直接使用 incus admin init --minimal。最精簡的設定會選擇 dir 儲存體驅動程式;下一節將說明這項選擇為何會持續影響後續操作。
啟動一個執行個體並確認其運作正常。
incus launch images:debian/13 web
incus list
incus exec web -- bashincus list 應顯示 web 為 RUNNING,並在 incusbr0 子網路上取得 IPv4 位址。沒有位址表示 DHCP(dynamic host configuration protocol)未完成,網路設定一節會說明相關問題。無法啟動的容器會在 incus info web --show-log 中列出原因,而 daemon 層級的失敗會記錄在 sudo journalctl -u incus -n 50。如果 VPS 上的 systemd-detect-virt 回傳 lxc 或 openvz,這次啟動就是確認您是否可使用巢狀虛擬化的實際測試。
為何預設儲存後端很重要
儲存後端會決定 snapshot 是立即完成,還是建立容器磁碟的完整副本。這是安裝時唯一無法在日後低成本變更的選擇。
Incus 支援 dir、btrfs、lvm、zfs、Ceph 及數種遠端驅動程式。在只有單一磁碟的 VPS 上,實際選擇是 dir 與 btrfs。
dir 驅動程式會將每個容器以一般檔案和目錄的形式儲存在 /var/lib/incus 下。Incus 文件指出,它「比所有其他驅動程式慢很多」,因為它必須解開每個映像檔,並建立實際副本,而不是參照共用區塊。對 4 GiB 容器建立 snapshot 時,會寫入 4 GiB,所需時間與 cp -a 相同。磁碟配額只有在檔案系統層級啟用 project quotas 的 ext4 或 XFS 上才有效。大多數 VPS 映像檔預設未啟用此功能,因此在 dir pool 上設定的磁碟限制通常不會生效。
btrfs 和 zfs 使用寫入時複製,因此 snapshot 只會記錄建立後變更的區塊。Incus 將這兩者列為建議使用的後端。建立 snapshot 幾乎會立即完成。磁碟配額則透過檔案系統本身的配額支援運作。
大多數 VPS 方案只有一個磁碟,且沒有可用的額外分割區,因此請將 pool 放在 loop file 上。未提供 source= 時,Incus 會代為處理。
sudo apt install -y btrfs-progs
incus storage create fast btrfs size=30GiB
incus profile device set default root pool=fast
incus launch images:debian/13 web2 -s fast未提供 size= 時,loop-backed pool 會使用可用磁碟空間的 20%,下限為 5 GiB,上限為 30 GiB。請明確設定此值。loop file 是 root filesystem 上的檔案,因此 pool 與主機共用相同的可用空間。這表示 pool 填滿時,主機磁碟也會填滿。
Debian 和 Ubuntu 上的 ZFS 是 DKMS module,而不是核心內建模組,因此每次 kernel 升級都會重新建置,且可能在其中一次升級後建置失敗。對於不會每天監控的伺服器,btrfs 是兩者中維護需求較低的選擇。
3 種網路模式,以及各自公開的內容
incus admin init 會建立名為 incusbr0 的受管制橋接器,並將每個新執行個體連接到該橋接器。這是連接容器的 3 種方式之一。另外 2 種方式存在的原因,是第一種會透過 NAT(網路位址轉換)將容器隱藏在主機後方。
受管制橋接器。 incusbr0 會取得一個私有子網路。主機持有該子網路的第一個位址並充當閘道。Incus 會在該子網路上提供 DHCP 與 DNS(網域名稱系統),對外流量則透過主機的公開位址離開,並套用來源 NAT。除非你明確設定,外部流量無法到達容器。使用 proxy device 轉送連接埠。
incus config device add web http proxy listen=tcp:0.0.0.0:8080 connect=tcp:127.0.0.1:80 nat=truenat=true 會使用 netfilter 規則進行轉送,而不是透過獨立的 userspace 連線代理,因此用戶端的實際位址會保留在容器的日誌中。Incus 只有在主機是執行個體閘道時才支援此模式,這正是 incusbr0 的情況。
macvlan。 容器會在主機的實體網路上取得自己的 MAC(媒體存取控制)位址。在大多數 VPS 平台上,這會失敗,因為虛擬交換器連接埠綁定 VM 的 MAC 位址,會捨棄來自其他位址的框架。即使 macvlan 可運作,還有第二個限制也常造成問題。Incus 的文件指出:「macvlan device 雖然能彼此通訊,也能與外部通訊,但無法與其父 device 通訊。這表示如果執行個體需要與主機本身通訊,就不能使用 macvlan。」
路由模式。 這是在具有額外位址的 VPS 上通常可運作的模式。Incus 的文件將此 device 說明為:「建立虛擬 device 配對以連接主機與執行個體,並設定靜態路由及 proxy ARP/NDP 項目,讓執行個體加入指定父介面的網路。」ARP 是位址解析通訊協定。容器會保留一個公開位址。主機會替該位址回應 ARP,因此供應商看到的仍只有主機的 MAC 位址。
incus config device add web eth0 nic nictype=routed parent=enp1s0 ipv4.address=203.0.113.20從 ip route show default 取得父介面的名稱。目前的映像檔使用類似 enp1s0 或 ens3 的名稱,很少使用 eth0。將 device 命名為 eth0,會覆寫 default profile 提供的 device,因此容器最後會連接到路由介面,而不是橋接器。從容器內使用 ip a 與 ip route 檢查結果。
容器為何能連線至主機上的服務
incusbr0上的容器具有自己的 network namespace,但與主機之間沒有防火牆邊界。主機位於該 bridge 的 gateway address,因此從容器內看,主機是可直接連線的鄰居,所有繫結至 0.0.0.0 的主機服務都會在該處回應。
請自行確認。在主機上列出目前正在監聽的項目。
sudo ss -tlnp接著從容器內連線至 ip route 回報的 gateway。
ip route show default
nc -zv 10.0.0.1 6379如果主機上的資料庫、metrics endpoint 或管理面板繫結至 0.0.0.0,這項檢查就會成功。因為封包從未離開這台機器,供應商的 network firewall 根本看不到它。這就是多數「它怎麼能連到那裡?」問題背後的原因:容器透過 NAT 與網際網路隔離,但與主機之間沒有任何隔離措施。
請盡可能將主機服務繫結至 127.0.0.1。接著在主機上過濾該 bridge。使用 ufw 的主機,其預設 deny policy 已經會阻擋容器到主機的流量,導致 Incus 的 DNS 和 DHCP 失效;Incus 文件提供的修正方式是 sudo ufw allow in on incusbr0。這個單一命令會重新開放所有主機埠,讓所有容器都能連線。請改為只允許容器實際需要的項目。
sudo ufw allow in on incusbr0 to any port 53 proto udp
sudo ufw allow in on incusbr0 to any port 53 proto tcp
sudo ufw allow in on incusbr0 to any port 67 proto udp
sudo ufw route allow in on incusbr0
sudo ufw route allow out on incusbr0這兩條 ufw route 規則會讓 instance 流量經由主機轉送至網際網路。若沒有這些規則,ufw 的 routed policy 會丟棄 forwarded packets,因此容器雖然取得 address,卻無法連線至任何地方。
快照與設定檔
快照是儲存集區中執行個體在特定時間點的副本。
incus snapshot create web pre-upgrade
incus info web
incus snapshot restore web pre-upgrade
incus snapshot delete web pre-upgradeincus info web 會列出執行個體持有的快照。請依執行個體個別排程快照。
incus config set web snapshots.schedule=@daily
incus config set web snapshots.expiry=4w快照位於相同的儲存集區、相同的磁碟和相同的伺服器上。它可以在升級失敗時提供保護,但無法防範磁碟故障或執行個體遭刪除。備份使用 incus export,而且檔案必須移出該伺服器。
incus export web /root/web-backup.tar.gz
incus import /root/web-backup.tar.gz設定檔是套用至執行個體的具名設定金鑰與裝置集合。除非另行指定,所有執行個體都會取得 default 設定檔。該設定檔會提供根磁碟和網路介面。編輯 default 會變更所有使用該設定檔的執行個體。這很實用,但也可能讓人一次中斷 20 個容器的網路連線。
incus profile create small
incus profile set small limits.memory=512MiB
incus profile set small limits.cpu=1
incus launch images:debian/13 api -p default -p small設定檔會依順序套用,因此最後列出的設定檔所設定的金鑰具有優先權。使用 incus config show api --expanded 查看執行個體實際套用的設定。
在 Incus 容器內執行 Docker
Incus 系統容器內的 Docker 必須啟用巢狀功能,因為 Docker 會自行建立命名空間與掛載,而容器預設無法建立這些項目。
incus config set web security.nesting=true
incus restart webIncus 將 security.nesting 說明為「是否允許在 instance 內啟用巢狀功能」,而容器的預設值為 false。另外兩點直接來自 Incus FAQ。容器無法載入 kernel module,因此 Docker 所需的 module 必須在主機上載入,並列在 incus config set web linux.kernel_modules overlay,br_netfilter 中。在容器內建立 /.dockerenv 檔案,則可讓 Docker 略過某些在巢狀環境中會失敗的檢查。
在 Ubuntu 24.04 主機上,AppArmor 對非特權 user namespace 的限制可能會阻擋 runc 執行的 pivot_root。容器內的 Docker 會輸出:
failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error jailing process inside rootfs: pivot_root .: permission denied而主機的 dmesg 會顯示包含 apparmor="DENIED" operation="pivotroot" class="mount" 的行。許多人會直接嘗試調整 kernel.apparmor_restrict_unprivileged_userns。關閉這項設定並不是可靠的修正方式:針對這項確切拒絕事件的上游 Incus bug report 記錄指出,將其設為 0 並未解決問題。請先閱讀 dmesg 中的拒絕事件,確認問題確實來自 AppArmor,再變更安全性預設值。
如果您希望直接在 VPS 上執行容器並省略一層,在 VPS 上執行 Docker 會單獨說明該設定。
失效情況,以及您會看到的字串
在主機上安裝 Docker 後,所有執行個體失去網路。 Incus 文件指出原因:「Docker 將全域 FORWARD 政策設為 drop,導致 Incus 無法轉送流量,因此執行個體失去網路連線。」執行個體仍保有 IP 位址,但無法連線到任何位置。將 /etc/docker/daemon.json 中的 ip-forward-no-drop 設為 true,接著讓轉送設定永久生效,並允許 bridge 通過 Docker 自己的 chain。
echo "net.ipv4.conf.all.forwarding=1" | sudo tee /etc/sysctl.d/99-forwarding.conf
sudo systemctl restart systemd-sysctl
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT這些 iptables 規則不會自行在重新開機後保留。請將其設為永久設定。
容器因 cgroup 錯誤而停止啟動。 Incus FAQ 記載了這個問題。出現 Failed to mount "/sys/fs/cgroup" 訊息通常表示主機上的 VPN 用戶端將 net_cls cgroup v1 控制器掛載到 cgroup v2 上,而 Incus 使用的是 cgroup v2。sudo umount /sys/fs/cgroup/net_cls 可清除此問題。
執行個體沒有取得 IPv4 位址。 incus list 顯示執行個體正在執行,但位址欄位是空的。主機傳送的 DHCP 回應遭到丟棄,最常見原因是主機防火牆不知道這個 bridge。在 ufw 上,sudo ufw allow in on incusbr0 to any port 67 proto udp 可恢復連線。使用 sudo tcpdump -ni incusbr0 port 67 監看請求是否抵達。
執行個體在巢狀 VPS 上拒絕啟動。 先查看 incus info <name> --show-log,再查看 sudo journalctl -u incus -n 50。如果 systemd-detect-virt 顯示 lxc 或 openvz,缺少的部分在供應商端,VPS 內的任何設定都無法改變它。
快照速度很慢,磁碟空間持續耗盡。 您使用的是 dir pool。incus storage list 會列出每個 pool 的 driver。若要改用 copy-on-write pool,請建立新的 pool,使用 incus copy web web-new -s fast 將執行個體複製到其中,確認複本可以啟動後,再刪除原始執行個體。
FAQ
Incus 容器和 Docker 容器是同一種東西嗎?
不是。Docker 封裝單一程序或應用程式。Incus 系統容器則模擬完整的作業系統,具備自己的 init、使用者、服務與套件管理員。Incus 容器需要像伺服器一樣保留並套用修補程式。Docker 容器則可直接刪除,再從映像檔重新建立。將容器設定 security.nesting=true 後,可以在 Incus 容器內執行 Docker。反向則無法運作。
我可以在 VPS 上執行 Incus 嗎?
在 KVM VPS 上可以。systemd-detect-virt 會輸出 kvm 或 qemu,表示你擁有自己的核心,Incus 的行為會如同在實體硬體上執行。若輸出 lxc、lxc-libvirt 或 openvz,表示你的 VPS 本身就是容器,因此其中的 Incus 容器屬於巢狀容器。只有供應商在你的容器上啟用巢狀功能時,這些容器才能運作。也請檢查 uname -r,因為截至 August 2026,目前的 Incus 穩定分支文件記載最低核心版本為 6.12,而 6.0 LTS 分支記載的版本為 5.4。
在 VPS 上使用 Incus 時,應選擇哪個儲存後端?
除非你有可提供給它使用的備用區塊裝置,否則請在迴圈檔案上使用 btrfs。文件指出,dir 驅動程式比其他驅動程式慢很多,因為它會複製檔案,而不是使用寫入時複製。因此,每個快照都會再次寫入整個容器。incus admin init --minimal 會選取 dir,因此花兩分鐘回答互動式問題是值得的。使用 incus storage create fast btrfs size=30GiB 建立儲存池。
為什麼我的 Incus 容器可以連線到主機上執行的服務?
因為預設的 incusbr0 bridge 會讓主機和容器位於同一個子網路,主機使用 gateway 位址,而且兩者之間沒有任何過濾規則。任何繫結至 0.0.0.0 的主機服務都會在該位址回應。這些封包不會離開主機,因此供應商的防火牆看不到它們。請將主機服務繫結至 127.0.0.1。在使用 ufw 的主機上,請只允許 DNS 和 DHCP 透過 incusbr0 連入,不要使用涵蓋全部流量的 sudo ufw allow in on incusbr0。
如何備份 Incus 容器?
incus export web /root/web-backup.tar.gz 會將執行個體及其快照寫入單一檔案,incus import 則可在同一台伺服器或另一台伺服器上還原。使用 incus snapshot create 建立的快照不是備份。它們位於同一個儲存池及同一個磁碟上,因此可以因應升級失敗,卻無法因應伺服器故障。請使用 incus config set web snapshots.schedule=@daily 排程建立快照,並將匯出檔複製到主機之外。