ドキュメント https://linuxcontainers.org/
の中の https://linuxcontainers.org/incus/introduction/
github https://github.com/lxc/incus
LXDのフォーク.
コンテナ技術なのですが、Docker は「軽量なアプリ実行」、Incus は「軽量な VM 代替」という立ち位置のご様子.
ここでは Incus を簡単に導入してみる.
[root@incus ~]# cat /etc/redhat-release
Rocky Linux release 9.6 (Blue Onyx)
[root@incus ~]# dnf copr enable neil/incus
[root@incus ~]# dnf install epel-release
[root@incus ~]# dnf config-manager --enable crb
[root@incus ~]# dnf install incus incus-toolsここで新しいgroupが作られます
[root@incus ~]# cat /etc/group
:
incus-admin:x:995:
incus:x:994:
[root@incus ~]#っでincusの daemon を起動させます.
[root@incus ~]# systemctl enable incus --now
[root@incus ~]# systemctl status incus
● incus.service - Incus - Daemon
Loaded: loaded (/usr/lib/systemd/system/incus.service; indirect; preset: disabled)
Active: active (running) since Mon 2025-09-22 22:26:53 JST; 10s ago
TriggeredBy: ● incus.socket
Docs: man:incusd(1)
Process: 14047 ExecStartPost=/usr/libexec/incus/incusd waitready --timeout=600 (code=exited, status=0/SUCCESS)
Main PID: 14046 (incusd)
Tasks: 13
Memory: 36.8M
CPU: 140ms
CGroup: /system.slice/incus.service
mq14046 /usr/libexec/incus/incusd --group incus-admin
Sep 22 22:26:52 incus systemd[1]: Starting Incus - Daemon...
Sep 22 22:26:52 incus incusd[14046]: time="2025-09-22T22:26:52+09:00" level=error msg="Unable to parse system idmap" err="No map found for user"
Sep 22 22:26:52 incus incusd[14046]: time="2025-09-22T22:26:52+09:00" level=warning msg="AppArmor support has been disabled because of lack of kernel support"
Sep 22 22:26:52 incus incusd[14046]: time="2025-09-22T22:26:52+09:00" level=warning msg=" - AppArmor support has been disabled, Disabled because of lack of kernel support"
Sep 22 22:26:52 incus incusd[14046]: time="2025-09-22T22:26:52+09:00" level=warning msg="Instance type not operational" driver=qemu err="QEMU command not available: exec: \">
Sep 22 22:26:53 incus systemd[1]: Started Incus - Daemon.
[root@incus ~]#
[root@incus ~]# incus version
Client version: 6.8
Server version: 6.8
[root@incus ~]#incusのストレージプールを用意します。
ここではフィルシステムをそのまま使います. zfsとかbtrfsの方が高速なのですが、面倒なので。
parted /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary 0% 100%
(parted) quit
mkfs.ext4 -m 0 /dev/sdb1
e2label /dev/sdb1 incus
echo "LALABEL=incus /incus ext4 defaults 0 0" >> /etc/fstab
mkdir /incus
systemctl daemon-reload
mount -aっで構築開始
[root@incus ~]# incus admin init以降下記のような設問が出てきます。ここでは下記のようにしてみました。
| 質問 | 解答 | 備考 |
| Would you like to use clustering? (yes/no) [default=no]: | no | clusterは作らないので |
| Do you want to configure a new storage pool? (yes/no) [default=yes]: | yes | ストレージプールを今作るので。後で作るならno |
| Name of the new storage pool [default=default]: | default | ストレージプールの名称 |
| Name of the storage backend to use (dir, zfs, lvm, ceph, btrfs) [default=zfs]: | dir | zfs,lvm2,cephらのモジュール、ライブラリがあれば問われる. なければdirでこの設問は表示されない |
| Where should this storage pool store its data? [default=/var/lib/incus/storage-pools/default]: | /incus/default | dirでのストレージプールの場所 |
| Would you like to create a new local network bridge? (yes/no) [default=yes]: | no | 作成するコンテナは今あるネットワークに直に接続させたいので |
| Would you like to use an existing bridge or host interface? (yes/no) [default=no]: | no | 複数のコンテナを作りたいので、あとで作成します |
| Would you like the server to be available over the network? (yes/no) [default=no]: | no | incusの管理サービスに外部からアクセスするならyes |
| Would you like stale cached images to be updated automatically? (yes/no) [default=yes]: | no | コンテナを作る際に使用するイメージ(iso)を更新するかどうか. コンテナは更新されない |
構築が完了すると /incus/default は下記のようになります
[root@incus ~]# ls -l /incus/default/
total 32
drwx--x--x. 2 root root 4096 Sep 23 00:26 buckets
drwx--x--x. 2 root root 4096 Sep 23 00:26 containers
drwx--x--x. 2 root root 4096 Sep 23 00:26 containers-snapshots
drwx--x--x. 2 root root 4096 Sep 23 00:26 custom
drwx--x--x. 2 root root 4096 Sep 23 00:26 custom-snapshots
drwx--x--x. 2 root root 4096 Sep 23 00:26 images
drwx--x--x. 2 root root 4096 Sep 23 00:26 virtual-machines
drwx--x--x. 2 root root 4096 Sep 23 00:26 virtual-machines-snapshots
[root@incus ~]#[root@incus ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether bc:24:11:23:5d:ac brd ff:ff:ff:ff:ff:ff
[root@incus ~]# modprobe macvlan
[root@incus ~]# incus network create pubnet --type=macvlan parent=enp6s18
[root@incus ~]# incus network list
+---------+----------+---------+------+------+-------------+---------+---------+
| NAME | TYPE | MANAGED | IPV4 | IPV6 | DESCRIPTION | USED BY | STATE |
+---------+----------+---------+------+------+-------------+---------+---------+
| enp6s18 | physical | NO | | | | 1 | |
+---------+----------+---------+------+------+-------------+---------+---------+
| lo | loopback | NO | | | | 0 | |
+---------+----------+---------+------+------+-------------+---------+---------+
| pubnet | macvlan | YES | | | | 0 | CREATED |
+---------+----------+---------+------+------+-------------+---------+---------+
[root@incus ~]#あと再起動時にmacvlanをロードさせるために
[root@incus ~]# echo macvlan | tee /etc/modules-load.d/macvlan.confとします
複数の管理者アカウントを用意しても構いません. ここでは1つ作ります. 管理作業が必要ならこのアカウントにsuすればいいかなと.
useradd -s /bin/bash incus-supervisorローカルでユーザを作成するとUID/GIDマッピングが自動で作れれますが、修正します。rootにも用意することが大事みたい.
[root@incus ~]# cat /etc/subuid
root:1000000:65536
incus-supervisor:1100000:65536
[root@incus ~]# cat /etc/subgid
root:1000000:65536
incus-supervisor:1100000:65536
[root@incus ~]#次に作った管理者アカウント「incus-supervisor」をグループ「incus-admin」に加えます
[root@incus ~]# usermod -aG incus-admin incus-supervisor
[root@incus ~]# grep incus-admin /etc/group
incus-admin:x:995:incus-supervisor
[root@incus ~]#作成した管理者アカウント「incus-supervisor」でコンテナ作成と化します
現在のコンテナの状態は「incus list」で得られます
[incus-supervisor@incus ~]$ incus list
To start your first container, try: incus launch images:ubuntu/22.04
Or for a virtual machine: incus launch images:ubuntu/22.04 --vm
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
[incus-supervisor@incus ~]$っでコンテナを作ります
[incus-supervisor@incus ~]$ incus launch images:rockylinux/9 myapp1 --network pubnet
Launching myapp1
[incus-supervisor@incus ~]$
[incus-supervisor@incus ~]$ incus list
+--------+---------+------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------+---------+------+------+-----------+-----------+
| myapp1 | RUNNING | | | CONTAINER | 0 |
+--------+---------+------+------+-----------+-----------+
[incus-supervisor@incus ~]$残念なことに「IPV4」の値がないので、このコンテナは外部との接続ができないです。
原因は使用したrockylinux9のイメージが超軽量級で用意されているためみたい.
っで
[incus-supervisor@incus ~]$ incus exec myapp1 -- ip link set eth0 up
[incus-supervisor@incus ~]$ incus exec myapp1 -- dhclient eth0っとすればdhcp経由になりますが、ipが付与される。
そして「incus list」とすると
[incus-supervisor@incus ~]$ incus list
+--------+---------+----------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------+---------+----------------------+------+-----------+-----------+
| myapp1 | RUNNING | 192.168.0.222 (eth0) | | CONTAINER | 0 |
+--------+---------+----------------------+------+-----------+-----------+
[incus-supervisor@incus ~]$っが「incus restart myapp1」とコンテナを再起動すると再度ipが付与されず上がります。
それを防ぐには「incus exec myapp1 -- bash」でマシンに入って root の crontab に 「@reboot /usr/sbin/dhclient」を追記します。これで再起動後もあがるそうな.
[incus-supervisor@incus ~]$ incus stop myapp1 *強制停止は「incus stop myapp1 --force」
[incus-supervisor@incus ~]$ incus start myapp1
[incus-supervisor@incus ~]$ incus restart myapp1
[incus-supervisor@incus ~]$ incus snapshot create myapp1 myapp1-orig *スナップショット
[incus-supervisor@incus ~]$ incus snapshot list myapp1 *myapp1のスナップショット一覧
+-------------+----------------------+------------+----------+
| NAME | TAKEN AT | EXPIRES AT | STATEFUL |
+-------------+----------------------+------------+----------+
| myapp1-orig | 2025/09/23 03:48 JST | | NO |
+-------------+----------------------+------------+----------+
[incus-supervisor@incus ~]$ incus snapshot restore myapp1 myapp1-orig *スナップショットのリストア
[incus-supervisor@incus ~]$ incus snapshot delete myapp1 myapp1-orig *スナップショットの削除
[incus-supervisor@incus ~]$ incus snapshot list myapp1
+------+----------+------------+----------+
| NAME | TAKEN AT | EXPIRES AT | STATEFUL |
+------+----------+------------+----------+
[incus-supervisor@incus ~]$ incus export myapp1 ./myapp1-backup.tar.gz --instance-only *スナップショットなしでバックアップ
[incus-supervisor@incus ~]$ ls -hl ./myapp1-backup.tar.gz
-rw-r--r--. 1 incus-supervisor incus-supervisor 152M Sep 23 03:53 ./myapp1-backup.tar.gz
[incus-supervisor@incus ~]$ incus delete myapp1
[incus-supervisor@incus ~]$ incus list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
[incus-supervisor@incus ~]$ incus import ./myapp1-backup.tar.gz myapp1-backup *バックアップからのインポート
[incus-supervisor@incus ~]$ incus list
+---------------+---------+------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------------+---------+------+------+-----------+-----------+
| myapp1-backup | STOPPED | | | CONTAINER | 0 |
+---------------+---------+------+------+-----------+-----------+
[incus-supervisor@incus ~]$ incus rename myapp1-backup myapp1 *コンテナ名称変更
[incus-supervisor@incus ~]$ incus copy myapp1 myapp2 *コンテナのクローン作製
[incus-supervisor@incus ~]$ incus list
+--------+---------+------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------+---------+------+------+-----------+-----------+
| myapp1 | STOPPED | | | CONTAINER | 0 |
+--------+---------+------+------+-----------+-----------+
| myapp2 | STOPPED | | | CONTAINER | 0 |
+--------+---------+------+------+-----------+-----------+コンテナを特権モードで動かせば、コンテナ内でも直接mountできるみたい
でも、ここでは「ホスト」でrootがnfs-mountした場所を使うようにしてみた
[root@incus ~]# dnf install nfs-utils -y
[root@incus ~]# mkdir /Public
[root@incus ~]# mount qnap:/Public /Public
[root@incus ~]# df -ThF nfs4
Filesystem Type Size Used Avail Use% Mounted on
qnap:/Public nfs4 15T 13T 2.2T 86% /Public
[root@incus ~]#管理者アカウントになって nfs を張る
[root@incus ~]# su - incus-supervisor
[incus-supervisor@incus ~]$ incus start myapp1
[incus-supervisor@incus ~]$ incus list
+--------+---------+----------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------+---------+----------------------+------+-----------+-----------+
| myapp1 | RUNNING | 192.168.0.222 (eth0) | | CONTAINER | 0 |
+--------+---------+----------------------+------+-----------+-----------+
| myapp2 | STOPPED | | | CONTAINER | 0 |
+--------+---------+----------------------+------+-----------+-----------+
[incus-supervisor@incus ~]$
[incus-supervisor@incus ~]$ incus config device add myapp1 mynfs disk source=/Public path=/mnt/nfs *ホストの/Publicをコンテナの /mnt/nfs に繋げる
[incus-supervisor@incus ~]$ incus exec myapp1 -- bash
[root@myapp1 ~]# df -ThF nfs4
Filesystem Type Size Used Avail Use% Mounted on
qnap:/Public nfs4 15T 13T 2.2T 86% /mnt/nfs
[root@myapp1 ~]#rockylinux9イメージでは最小構成なので初めから openssh-server は入ってなくサービスもない。なのでコンテナ内にインストールします
[incus-supervisor@incus ~]$ incus exec myapp1 -- bash
[root@myapp1 ~]# dnf install openssh-server
[root@myapp1 ~]# vi /etc/ssh/sshd_config
:
PermitRootLogin yes
:
[root@myapp1 ~]#
[root@myapp1 ~]# systemctl restart sshd
[root@myapp1 ~]# passwd <-- ここではrootで入れるようにしてますっでホストではない別のマシンから入ってみた
[root@rockylinux9 ~]# ssh -l root 192.168.0.222
The authenticity of host '192.168.0.222 (192.168.0.222)' can't be established.
ED25519 key fingerprint is SHA256:VpXNDwbOSjLgvaxLi8hB1TET0peyiXb3e77o6YWIxEk.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.0.222' (ED25519) to the list of known hosts.
root@192.168.0.222's password:
Last login: Tue Sep 23 03:07:10 2025 from 192.168.0.3
[root@myapp1 ~]#と行けた。
だが、コンテナを主催するホストから接続を試みると
[incus-supervisor@incus ~]$ ssh -l root 192.168.0.222
ssh: connect to host 192.168.0.222 port 22: No route to host
You can find some explanations for typical errors at this link:
https://red.ht/support_rhel_ssh
[incus-supervisor@incus ~]$と弾かれます。
それへの対処としてはホストの特定ポートに特定のホストの22を割り当てるようにします。proxyデバイスの付与って言われるみたい.
incus config device add myapp1 sshproxy proxy \
listen=tcp:0.0.0.0:2222 \
connect=tcp:127.0.0.1:22
incus config device add myapp2 sshproxy proxy \
listen=tcp:0.0.0.0:2223 \
connect=tcp:127.0.0.1:22コンテナ myapp1 には localhost:2222 が コンテナの22にアサイン。
コンテナ myapp2 には localhost:2223 が コンテナの22にアサイン。
って感じにします。
[incus-supervisor@incus ~]$ incus config device add myapp1 sshproxy proxy \
listen=tcp:0.0.0.0:2222 \
connect=tcp:127.0.0.1:22
Device sshproxy added to myapp1
[incus-supervisor@incus ~]$
(確認)
[incus-supervisor@incus ~]$ incus config device list myapp1
eth0
mynfs
sshproxy
[incus-supervisor@incus ~]$っで接続してみる
[incus-supervisor@incus ~]$ ssh -l root -p 2222 localhost
root@localhost's password:
Last login: Tue Sep 23 11:42:35 2025 from 127.0.0.1
[root@myapp1 ~]#となる。
ここでは「dir」とファイルシステムをそのまま使っていますが、ストレージプールのサイズがコンテナのsystem disk容量となるみたい.
そして「dir」だと容量制限が付けられないようで、zfs, btrfs, lvmでストレージプールを作ったら制限ができるそうな.
動作は極めて良好。再起動も滅茶苦茶はやい