LXD で作る仮想化 GUI 環境 - Ubuntu 22.04 LTS 版

# 概要

下記の記事を参考にして、LXDを使用したGUI隔離環境の実践例と応用の手法を記載します。

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0627

以前 20.04 用のものを作成しましたが、今回は 22.04 版となります。

https://qiita.com/yoshi10ryu1/items/9bbe1434874b3cc88e57

基本的に色々なところから持ってきた手順を切った貼ったした感じのドキュメントになります。

まだ未完成のため、後日、追加・訂正予定です。

# 検証環境

* OS: Ubuntu 22.04 LTS AMD64


# LXDをインストールする。

```LXDのインストール
ubuntu@host:~$ sudo snap install lxd
ubuntu@host:~$ sudo lxd init
Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, dir, lvm, zfs, ceph) [default=zfs]: btrfs
Create a new BTRFS pool? (yes/no) [default=yes]: 
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=30GB]: 64GB
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none
Would you like the LXD server to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: 
```

あとからIPv6を無効にする場合
```
ubuntu@host:~$ lxc network set lxdbr0 ipv6.address none
```

### ユーザーをlxdグループに追加

通常はインストールを行ったユーザーは自動で追加されると思いますが、
もし追加されていない場合は「 /etc/group 」を編集する等して追加してください。

### UFWの設定

UFW を導入している場合，この先に進む前に LXD が用意してくれるブリッジである lxdbr0 を介しての通信を許可します。以下は ufw での例です。
```
ubuntu@host:~$ sudo ufw allow in on lxdbr0
ubuntu@host:~$ sudo ufw route allow in on lxdbr0
```


### 再起動

設定の反映等のためにホストを再起動してください。














# GUIアプリを動かせるコンテナを作成（基本）

やりやすいようにコンテナ名を変数に入れる。
```
ubuntu@host:~$ LXCNAME=kasou1
```

### コンテナの作成

```
ubuntu@host:~$ lxc launch ubuntu:22.04 $LXCNAME
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c "apt update && apt full-upgrade -y && apt autoremove -y"
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c "reboot"
```

### UID/GIDの設定
```
ubuntu@host:~$ lxc config set $LXCNAME raw.idmap 'both 1000 1000'
```

## 基本設定

### パッケージのインストール
```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'apt update && apt install -y \
  x11-apps pulseaudio dbus-x11 \
  language-pack-ja fonts-noto-cjk-extra \
  task-japanese-gnome-desktop language-pack-gnome-ja-base language-pack-gnome-ja gnome-user-docs-ja gnome-control-center\
  fonts-noto-color-emoji manpages-ja'
```

### 日本語環境の設定
```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'update-locale LANG=ja_JP.UTF-8'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'timedatectl set-timezone Asia/Tokyo'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'source /etc/default/locale'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'echo export LANG=ja_JP.UTF8 | tee --append /home/ubuntu/.profile'
```

### コンテナ再起動
```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'reboot'
```


### コンテナの中からホストのサウンドサーバーにアクセスできるようにする

```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'echo export PULSE_SERVER=unix:/tmp/.pulse-native | tee --append /home/ubuntu/.profile'
ubuntu@host:~$ lxc config device add $LXCNAME pa disk source=/run/user/1000/pulse/native path=/tmp/.pulse-native
```

### ホストのXサーバーとGPUデバイスにアクセス

コンテナからホストのXサーバーとGPUデバイスにアクセスできるようにします。

 Wayland の導入で書き方が少し異なっています。

また、事前にホストの「 /tmp/.X11-unix/ 」を確認して下さい。
環境によってこの中の「 X0 」が「 X1 」だったりするらしく、もし「 X1 」の場合は「 environment.DISPLAY 」は「:1」にして、その次の「 xorg 」も「 X1 」にしてください。

```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'usermod -aG video ubuntu'
ubuntu@host:~$ lxc config set $LXCNAME environment.DISPLAY :0
ubuntu@host:~$ lxc config device add $LXCNAME xorg disk source=/tmp/.X11-unix/X0 path=/tmp/.X11-unix/X0
ubuntu@host:~$ lxc config device add $LXCNAME mygpu gpu gid=`getent group video | cut -d: -f3`
```

### 念の為ubuntuユーザーにパスワードを設定する。

```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash
root@kasou1:~# passwd ubuntu
New password: 
Retype new password: 
passwd: password updated successfully
root@kasou1:~# exit
```

また、その後の作業のために、いったんubuntuユーザーが sudo を使用できるか確認してください。







## 日本語入力の設定

ここも20.04と異なります。

基本的には新しい fcitx5-mozc を使いたいのですが、
これがうまく動かないソフトもあるので、それが入ったコンテナでは fcitx-mozc を使うように設定します。

### 日本語入力の設定 - fcitx5-mozcの場合

```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'apt update && apt install -y \
                 fcitx5-mozc ibus-mozc'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'localectl set-x11-keymap jp jp106'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'sh -c "dbus-uuidgen > /var/lib/dbus/machine-id"'

ubuntu@host:~$ lxc exec $LXCNAME -- /bin/su - ubuntu
ubuntu@kasou1:~$ im-config -n fcitx5
ubuntu@kasou1:~$ source /etc/default/locale
ubuntu@kasou1:~$ exit
```

Ubuntuユーザーの「~/.profile」に下記を追加する。
```
#Added by https://astherier.com/blog/2020/08/install-fcitx-mozc-on-wsl2-ubuntu2004/
export GTK_IM_MODULE=fcitx5
export QT_IM_MODULE=fcitx5
export XMODIFIERS=@im=fcitx5
export DefaultIMModule=fcitx5
if [ $SHLVL = 1 ] ; then
  (fcitx5 > /dev/null 2>&1 &)
  xset -r 49  > /dev/null 2>&1
fi
#end
```

インストールが完了したら、設定を反映させるため一旦コンテナを再起動します。
```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'reboot'
```


### gnomeの設定画面を開く

このとき「gnome-control-center」でも良いですが、音声関連のタブで落ちてしまい、起動できなくなってしまうので、次がいいです。
```
ubuntu@host:~$ lxc exec $LXCNAME -- sudo --user=ubuntu --login 'gnome-language-selector'
```

追加のインストールを求められた場合はインストールを行ってください。

あと、「キーボード入力に使うIMシステム」に Fcitx 5 を選択します。

![langconf1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117082/f536173e-70d3-5170-24db-2d9c055e5736.png)

また、「システム全体に適用」をクリックします。

入力設定確認のため、 fcitx5-configtool を実行します。

```
ubuntu@host:~$ lxc exec $LXCNAME -- sudo --user=ubuntu --login 'fcitx5-configtool'
```

もし、この段階で下記のような画面になって Fcitx 5 の実行を促された場合、
きちんと Fcitx 5 が動作していません。

![fi5ugokanai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117082/6a5591e1-71d8-71fd-573b-89e541638c45.png)

「 Fcitx 5 を実行する」のボタンをクリックすれば起動させられますが、
この状態の場合、コンテナを起動させるたびにこの動作をしないと、日本語入力ができません。

設定を見直して、コンテナを再起動してもすぐ下記の画面になるようにしてください。

![fx5ugoita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117082/1317bfb9-8543-f3ec-7f49-705976b43aaa.png)

まず、「入力メソッド」タブ内の「現在の入力メソッド」に「 Mozc 」が追加されているか確認してください。
ない場合は、追加してください。


続いて、「グローバルオプション」タブの中で、
「 入力メソッドの切り替え」の項目の「Control+スペース」の下に、「 全角半角 」が指定されているか確認してください。

ない場合は、「Control+スペース」をクリックして半角全角キーを押すと、「 全角半角  」と入力されると思います。

また、必要のないものは右のバケツのボタンをクリックして削除します。

![fx5guroopu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117082/ea6641ea-e6dc-da3b-acea-d9d09376abbd.png)

設定が終わったら、OKを押して閉じます。
これで日本語入力ができるはずです。



### 日本語入力の設定 - fcitx-mozcの場合


```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'apt update && apt install -y \
                 fcitx-mozc ibus-mozc'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'localectl set-x11-keymap jp jp106'
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'sh -c "dbus-uuidgen > /var/lib/dbus/machine-id"'

ubuntu@host:~$ lxc exec $LXCNAME -- /bin/su - ubuntu
ubuntu@kasou1:~$ im-config -n ibus
ubuntu@kasou1:~$ gsettings set org.gnome.desktop.interface gtk-im-module "mozc"
ubuntu@kasou1:~$ source /etc/default/locale
ubuntu@kasou1:~$ exit
```

Ubuntuユーザーの「~/.profile」に下記を追加する。
```
#Added by https://astherier.com/blog/2020/08/install-fcitx-mozc-on-wsl2-ubuntu2004/
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
export DefaultIMModule=fcitx
if [ $SHLVL = 1 ] ; then
  (fcitx > /dev/null 2>&1 &)
  xset -r 49  > /dev/null 2>&1
fi
#end
```

インストールが完了したら、設定を反映させるため一旦コンテナを再起動します。
```
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'reboot'
```

この後はとくに何も設定しなくても動くはずです。

もし動作しない場合は、 fcitx5-mozc の手順の「gnomeの設定画面を開く」から行えば問題ないと思います。
ただし、 fcitx5-configtool はないので fcitx-config-gtk3 を使用して下さい。
操作方法については過去の20.04用の記事を参考にして下さい。




## その他の設定

### コンテナの自動起動を停止

コンテナの起動はホストのGUIが起動するよりも早いため、
このままだとコンテナは起動に失敗します。

あとで必要なコンテナをそれぞれ起動させる形にするので、
コンテナの自動起動はOffにします。

```
ubuntu@host:~$ lxc config set $LXCNAME boot.autostart false
ubuntu@host:~$ lxc exec $LXCNAME -- /bin/bash -c 'reboot'
```

### ユーザーに sudo をさせないようにする。

デフォルトだとコンテナのubuntuユーザーはパスワードなしでsudoが使えるので、使えないようにします。

```
lxc exec $LXCNAME -- /bin/bash
rm /etc/sudoers.d/90-cloud-init-users
exit
```

### AppImage 形式のソフトへの対応

FUSE が必要なのでインストールします。

```
lxc exec $LXCNAME -- /bin/bash -c 'apt update && apt install -y fuse'
```



## テンプレートを作成する。

ここまで作成したら、
今回作成した $LXCNAME を自作コンテナイメージとして登録します。

これで次回からは作業時間を短縮できます。

まず、コンテナを停止させてスナップショットを作成します。

```
ubuntu@host:~$ lxc stop $LXCNAME
ubuntu@host:~$ lxc snapshot $LXCNAME bk-install1
```

スナップショットからコンテナイメージを作成します。
```
ubuntu@host:~$ lxc publish ${LXCNAME}/bk-install1 --alias base1
Instance published with fingerprint: cb6262c4dc01fd4d65f9beb86572cf85c1d015e500d2271ec8072f3d820dd1cb
```

コンテナイメージができているか確認します。(出力結果は長いので一部抜粋)
```
ubuntu@host:~$ lxc image list base1
+-------+--------------+--------+--------------+-----------+-----------+
| ALIAS | FINGERPRINT  | PUBLIC | ARCHITECTURE |   TYPE    |   SIZE    |
+-------+--------------+--------+--------------+-----------+-----------+
| base1 | cb6262c4dc01 | no     | x86_64       | CONTAINER | 1882.77MB |
+-------+--------------+--------+--------------+-----------+-----------+
```

次回からは、「 base1 」で設定済みのコンテナを作成できます。
```
ubuntu@host:~$ lxc launch base1 voivo1
Creating voivo1
Starting voivo1  
```

ただし、すべての設定をコピーしてくれるわけではなく、
「  lxc config show voivo1 」の内容がデフォルトのままのようなので、下記の設定だけ行う必要があります。
( lxc config で始まるコマンドは実施する必要があるようです。)
```
ubuntu@host:~$ LXCNAME=voivo1
ubuntu@host:~$ lxc config set $LXCNAME raw.idmap 'both 1000 1000'
ubuntu@host:~$ lxc config device add $LXCNAME pa disk source=/run/user/1000/pulse/native path=/tmp/.pulse-native
ubuntu@host:~$ lxc config set $LXCNAME environment.DISPLAY :0
ubuntu@host:~$ lxc config device add $LXCNAME xorg disk source=/tmp/.X11-unix/X0 path=/tmp/.X11-unix/X0
ubuntu@host:~$ lxc config device add $LXCNAME mygpu gpu gid=`getent group video | cut -d: -f3`
ubuntu@host:~$ lxc config set $LXCNAME boot.autostart false
ubuntu@host:~$ lxc exec $LXCNAME -- sh -c "reboot"
```











# コンテナとソフトの自動起動

コンテナは自動起動してくれないので、PCを再起動した際にはコンテナも手動起動する必要があります。

それはメンドクサイので、私は柴田氏のスクリプトを簡易化したものを利用しています。

### 例（Google Chromeの場合）

下記のスクリプトをホスト側で作成します。

```lxc-chrome.sh
#!/bin/sh

# 指定したアプリのあるコンテナでアプリを起動する。
# コンテナが停止しているときには起動させる。
# 参考
# https://gihyo.jp/admin/serial/01/ubuntu-recipe/0627?page=3

##### 変数 ######################################
# コンテナ名
CONTAINER="chrome1"

# タイトル
TITLE="Google Chrome"

# ソフト起動時のコマンド
EXEC_COM="/home/ubuntu/bin/google-chrome.sh"


##### メイン処理 ######################################

if [ -z "${CONTAINER}" ]; then
    notify-send "${TITLE}" "Please specify container name"
    exit 1
fi

# check and start container
status=$(lxc list --format csv -c s "^${CONTAINER}$")
if [ "$status" != "RUNNING" ]; then
    lxc start "${CONTAINER}"
    lxc exec "${CONTAINER}" -- cloud-init status --wait

    status=$(lxc list --format csv -c s "^${CONTAINER}$")
    if [ "$status" != "RUNNING" ]; then
        notify-send "${TITLE}" "Failed to start \"${CONTAINER}\" container"
        exit 1
    fi
fi


lxc exec "${CONTAINER}" -- sudo --user=ubuntu --login "${EXEC_COM}"
```

使用したい際にはこのスクリプトを実行して起動させています。
違うソフトを起動したい場合は、変数の部分の内容を変更したスクリプトを作成してください。





# 各アプリケーションのインストール・設定

まだ未完成ではありますが、だいたい問題は解決したので、自分の環境を移行し始める予定です。

基本的には 20.04 と同じでも問題ないはずですが、下記のような問題が発生しています。

 - FireFox はまだインストール失敗する。（進捗20%で止まってしっぱいする）
 - ディスプレイ関係の設定不足？バグ？








# 参考URL

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0627

https://booth.pm/ja/items/1575615

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0521

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0479

https://www.fixes.pub/program/417137.html
https://qiita.com/mt08/items/c8b8187b1000382d77ae
http://bluearth.cocolog-nifty.com/blog/2020/04/post-8db9b1.html
https://astherier.com/blog/2020/08/install-fcitx-mozc-on-wsl2-ubuntu2004/
https://blog.goo.ne.jp/cinemaesprit/e/8805efd176e54a131c57bdb98c3a8b15
https://zenn.dev/tantan_tanuki/articles/7796a4f1d6d1b0
https://postgresweb.com/ubuntu-20-04-japanese
https://www.linux-setting.tokyo/2021/11/ubuntu-2110-impish-indri-ibus-mozc.html
https://matoken.org/blog/2019/07/19/direct-access-to-https-repository-with-apt-cacher-ng/
https://gihyo.jp/admin/serial/01/linux_containers/0015
https://qiita.com/yakitatata/items/a3070b13982999631d0e
https://matoken.org/blog/2019/07/19/direct-access-to-https-repository-with-apt-cacher-ng/

https://wiki.ubuntu.com/JammyJellyfish/ReleaseNotes/Ja
https://gihyo.jp/admin/clip/01/ubuntu-topics/202204/22
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0717
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0689
https://www.server-world.info/query?os=Ubuntu_22.04&p=japanese
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0520