はじめに
コンテナ技術としてはDockerが有名だが、こちらはアプリケーションコンテナとなっている。 LXDはシステムコンテナという位置づけになっているが、これらがどう違っているのかわからなかった。
DockerとLXDの大きな違いはセッションのライフサイクルとなる。
Dockerでもbashを実行することでコンテナにログインすることができる。しかし、シェルからexitすると、コンテナそのものが終了してしまう。
LXDはシステムコンテナなのでbashでログインして作業し、そこからexitしてもコンテナそのものは起動したままになる。
つまり、Dockerはあるアプリケーションを実行するための実行環境としてコンテナを使用するもので、 LXDはVMのような仮想的な環境としてコンテナを使用するものという違いがある。
LXDでも下記のようにlxc execで特定のコマンドを実行することもできるが、コンテナ自体はずっと可動している。
$ lxc exec <container name> -- ls
lxdのインストール
Ubuntu 20.04環境ではsnapで導入するのが無難
$ sudo snap install lxd
コンテナ環境の初期化
$ sudo lxd init
初期のストレージプールの作成などが行われる。
グループの追加
root以外でlxcを実行可能にする。
$ sudo gpasswd -a ${USER} lxd
UID/GIDマッピングの準備
LXDコンテナ中でホストのホームディレクトリを読み書きする方法
ホーム以外にも、ホストのディレクトリをコンテナ内にマッピングしてアクセス可能にするために必要。
ホスト環境の/etc/subuid
と/etc/subgid
にマッピング情報が必要になる。
$ echo "root:$(id -u):1" | sudo tee -a /etc/subuid $ echo "root:$(id -g):1" | sudo tee -a /etc/subgid
IDのマッピングを許可する範囲を指定する。書式は下記。
USER:START:COUNT
上記の例ではマッピングを許可するのはコンテナのrootで、マッピングを許可されるのはホストの$(id -u)
のUIDを持つユーザーから1個と指定している。
コンテナの作成
手順を汎用化するために環境変数CONTAINER
にコンテナ名を設定しておく。
${CONTAINER}
の部分をコンテナ名直打ちにしても問題ない。
$ lxc init ubuntu:18.04 ${CONTAINER}
ubuntu:18.04
はインターネット経由で提供されているベースイメージ。
使用可能なものは下記のコマンドで確認できる。
$ lxc image list images:
下記のようにするとディストリビューションを絞って表示できる。
$ lxc image list images:ubuntu
コンテナの起動
$ lxc start ${CONTAINER} $ lxc exec ${CONTAINER} -- /bin/bash
一般ユーザーの作成
ユーザー名は任意、 コマンドの例では環境変数USERNAME
に設定してある。 ホストPCの${USER}と併せておくといろ都合がよい。
# adduser ${USERNAME}
ubuntu:18.04のコンテナは初期状態でubuntu
ユーザーがいるためここで作るユーザーのUIDは1001
になる。
sudo可能にする
一般ユーザーにsudo権限を追加する。
# gpasswd -a ${USERNAME} sudo
ubuntu 16.04や18.04ではこのままではsudo実行時に下記のエラーになる。
sudo: no tty present and no askpass program specified
/etc/sudoers.d/
にファイルを作成して、NOPASSWD
を設定する。
$ echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/${USERNAME}
2回目以降
一度抜けたあとに再度コンテナに入る場合は下記のようにする。
$ lxc exec ${CONTAINER} -- /bin/bash
上記では毎回rootでログインすることになるので、作成した一般ユーザーでログインしたい場合は下記のようにする。
$ lxc exec ${CONTAINER} -- su --login ${USER}
上記はコンテナの一般ユーザー名がホストの${USER}と一致していることを想定している。
コンテナの一般的な操作
起動
$ lxc start ${CONTAINER}
終了
$ lxc stop ${CONTAINER}
作成済みのコンテナの確認
$ lxc list
削除
$ lxc delete ${CONTAINER}
ホストのディレクトリのバインド
ホストとコンテナのUID/GIDを紐付ける
lxc config set <container name> raw.imap
で実際の紐付けを行う。
書式は下記のようになっている。
"(uid|gid|both) <ホスト側のID> <コンテナ側のID>"
UIDとGIDをどちらも紐付けしたい場合はboth
それぞれどちらかの場合はその値を指定する。
コンテナで一般ユーザーを追加した場合は1001
になるので、ホストの実行中のユーザーとコンテナの追加した一般ユーザーを紐付ける場合下記のようになる。
$ lxc config set ${CONTAINER} raw.idmap "both $(id -u) 1001"
この例ではホストのUIDとGIDが一致している場合を想定している。
ディレクトリのバインド
ディレクトリのバインドはlxc config device add
で行う。
書式は下記のようになっている。
lxc config device add <コンテナ名> <名前> disk source=<ホスト上のパス> path=<コンテナ上のパス>
コンテナの/mnt/hdd/work
を/home/${USER}/work
に紐付ける場合下記のようにする。
$ lxc config device add ${CONTAINER} work disk \ source="/mnt/hdd/work" \ path="/home/${USER}/work"
有効化するにはコンテナを再起動する必要がある。
$ lxc restart ${CONTAINER}
まとめ
Dockerでもbashを実行してコンテナの中にログインすることができるため、LXDを使用するモチベーションがわからなかったが、 コンテナにログインして、ホストのリソースをフルに間借りできる仮想環境として利用するにはLXDのほうが使いやすいということがわかった。
ちなみに、LXD自体はコンテナの他にも同じコマンド体系でVMを実行することもできる。