docker みたいなことをしたかったが docker よくわからんかったので systemd-nspawn に逃げてみたらいい感じだったので適当につかってみた。
その記録。
systemd-networkd がホストで動いていることが前提(っぽい)
systemd-nspawn は systemd-networkd の機能をガンガンつかっていく。
なので NetworkManager とか netctl とか使っていると痛い目をみる。
ホストからコンテナへの通信
ホストからコンテナへ通信するためには /etc/nsswitch.conf の
hosts: files resolve myhostname
を
hosts: files mymachines resolve myhostname
にする。これでコンテナのホスト名で名前解決ができる。
ポートフォワード
systemd-nspawn (もしかしたら systemd-networkd の範疇かもしれない)のポートフォワードは結構あてにならない(少なくとも私がやってみたところでは全然うごかなかった)。
web サーバとかを systemd-nspawn でやる場合、ホストでリバースプロキシとかを動かしておいてそこからコンテナにリクエストを転送するようにしたほうがよさそう。
コンテナをおくファイルシステム
ベースになるコンテナをひとつこさえて、いろいろやるコンテナを先のベースコンテナから派生して作りたいとなった場合、
$ machinectl clone <ベースコンテナの名前> <いろいろやる予定のコンテナの名前>
とやって派生したコンテナをつくるが、ここで作られるコンテナは Btrfs の subvolume をつかって作られているので、systemd-nspawn がデフォルトでコンテナを置くディレクトリである /var/lib/machines/ は Btrfs 上に作成されなくてはならない。
そうでないと
Failed transfer image: /var/lib/machines is not a btrfs file system. Operation is not supported on legacy file systems.
とかいわれてコンテナの複製に失敗する。
これを回避する方法として一度
$ sudo machinectl export-tar <ベースコンテナの名前> <適当な名前>
でベースコンテナをエクスポートし、
$ sudo machinectl import-tar <エクスポート先のアーカイブ名> <いろいろやる予定のコンテナの名前>
でイメージをインポートし、ここでいろいろやる、とものがある。ただこの方法はめんどくさいし時間もかかってよくない。
コンテナでは sshd を動かしておいたほうがいい
コンテナ起動後
$ machinectl shell <コンテナのホスト名>
とかでコンテナに入って操作ができるけど、ちまちま操作するのはめんどくさいので Ansible でササッとやってしまいたくなる。
このとき sshd が動いてないと困るので、コンテナをつくるときにあわせて sshd を入れておくのがよい。
(2018-04-01 追記:意地でも Ansible でコンテナをセットアップしたいとかでなければ mkosi をつかったほうが今は良いと思う。mkosi をつかって nspawn 用のコンテナイメージをつくる - テクニカルプア も参照のこと)