「Systemd-nspawn」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
 
 
(5人の利用者による、間の129版が非表示)
1行目: 1行目:
  +
{{Lowercase title}}
 
[[Category:仮想化]]
 
[[Category:仮想化]]
  +
[[Category:サンドボックス]]
[[en:Arch systemd container]]
 
  +
[[en:Systemd-nspawn]]
  +
[[es:Systemd-nspawn]]
  +
[[ru:Systemd-nspawn]]
 
{{Related articles start}}
 
{{Related articles start}}
{{Related2|systemd|systemd}}
+
{{Related|systemd}}
 
{{Related|Linux Containers}}
 
{{Related|Linux Containers}}
{{Related2|systemd-networkd|systemd-networkd}}
+
{{Related|systemd-networkd}}
{{Related2|Docker|Docker}}
+
{{Related|Docker}}
 
{{Related|Lxc-systemd}}
 
{{Related|Lxc-systemd}}
 
{{Related articles end}}
 
{{Related articles end}}
   
''systemd-nspawn'' は [[chroot|chroot]] コマンドに似ていますが、''chroot を強化したもの''です。
+
''systemd-nspawn'' は [[chroot]] コマンドに似ていますが、''chroot を強化したもの''です。
   
''systemd-nspawn'' を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため [[chroot|chroot]] よりも強力です。
+
''systemd-nspawn'' を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム階層だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため [[chroot]] よりも強力です。
   
''systemd-nspawn'' は {{ic|/sys}}, {{ic|/proc/sys}}, {{ic|/sys/fs/selinux}} などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノード作成することも不可能。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールロードすること制限され
+
''systemd-nspawn'' は {{ic|/sys}}, {{ic|/proc/sys}}, {{ic|/sys/fs/selinux}} などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノード作成きません。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールロードもできせん
   
仕組みとしては [[Lxc-systemd]] や [[libvirt|Libvirt]]-lxc と異なり、とてもシンプルなツールで設定を行います。
+
仕組みとしては [[Lxc-systemd]] や [[Libvirt]]-lxc と異なり、とてもシンプルなツールで設定を行います。
   
== pacstrap でインストール ==
+
== インストール ==
   
''systemd-nspawn'' 自体''systemd'' に含まれていますが、効果的に使用するには[[公式リポジトリ]]からパッケージ {{Pkg|arch-install-scripts}} を[[pacman|インストール]]する必要があります。
+
''systemd-nspawn'' は {{Pkg|systemd}} に含まれています。
そして、お好きな場所にディレクトリを作成してください。例えば: {{ic|$ mkdir ~/''MyContainer''}}。
 
   
  +
== サンプル ==
次のコマンドで {{Grp|base}} グループから全てのパッケージがインストールされます。{{Grp|base-devel}} グループのパッケージも全てインストールすることを強く推奨します。
 
# pacstrap -i -c -d ~/''MyContainer'' base
 
   
  +
=== コンテナに最小限の Arch Linux を作成して起動 ===
{{Tip|'''-i''' オプションはパッケージ選択の自動確認を無効にします。コンテナ上に Linux カーネルをインストールする必要はないため、パッケージリストの選択から[[Pacman#使い方|削除]]することができます。}}
 
   
インストールが完了したら、コンテナを起動してください:
+
まず {{Pkg|arch-install-scripts}} パッケージを[[pacman|インストール]]してください
# systemd-nspawn -bD ~/''MyContainer''
 
   
  +
次に、コンテナを置くためのディレクトリを作成してください。この例では、{{ic|~/''MyContainer''}} を使用します。
これで終わりです。空のパスワードを使って "root" でログインしてください。
 
   
  +
そして、''pacstrap'' を使って最小限の arch システムをコンテナにインストールします。最低限でも {{Pkg|base}} パッケージはインストールする必要があります。
== 使用方法 ==
 
  +
  +
# pacstrap -c ~/MyContainer base [additional pkgs/groups]
  +
  +
{{Tip|{{Pkg|base}} パッケージは、{{Pkg|linux}} カーネルパッケージに依存せず、コンテナにも対応しています。}}
  +
  +
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。
  +
# systemd-nspawn -D ~/MyContainer
  +
# passwd
  +
# logout
  +
  +
最後に、コンテナを起動します。
  +
  +
# systemd-nspawn -b -D ~/MyContainer
  +
  +
{{ic|-b}} オプションはシェルを実行する代わりにコンテナを起動します (つまり PID=1 として {{ic|systemd}} を実行)。{{ic|-D}} にはコンテナのルートディレクトリにするディレクトリを指定します。
  +
  +
コンテナが開始したら、設定したパスワードを使って "root" でログインしてください。
  +
  +
{{Note|"Login incorrect" でログインが失敗する場合、問題は、{{ic|securetty}} TTY デバイスのホワイトリストである可能性があります。[[#root ログインが失敗する]] をご確認ください。}}
  +
  +
コンテナの電源を切りたいときはコンテナの中から {{ic|poweroff}} を実行することで出来ます。ホストからは、[[#machinectl|machinectl]] ツールでコンテナを制御できます。
  +
  +
{{Note|コンテナの中からセッションを終了するには {{ic|Ctrl}} を押しながら {{ic|]}} を素早く3回押してください。US キーボード以外の場合は {{ic|]}} の代わりに {{ic|%}} を使用します。}}
  +
  +
=== Debian や Ubuntu 環境の作成 ===
  +
  +
{{Pkg|debootstrap}} と {{Pkg|debian-archive-keyring}} か {{Pkg|ubuntu-keyring}} のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。
  +
  +
{{Note|systemd-nspawn を使用するにはコンテナ内の OS で systemd が PID 1 として動作している必要があります。Ubuntu 15.04 以前は、そのままでは動作せず、upstart から systemd への移行が必須です。また、コンテナ環境に {{ic|systemd-container}} パッケージをインストールしてください。}}
  +
  +
後は簡単に Debian や Ubuntu 環境をセットアップできます:
  +
  +
# cd /var/lib/machines
  +
# debootstrap --include=systemd-container --components=main,universe codename container-name repository-url
  +
  +
Debian の場合、コードネームとして指定するのは "stable" や "testing" などのローリングの名前か "stretch" や "sid" などのリリース名になります。Ubuntu の場合、"xenial" や "zesty" などのコードネームを使ってください。コードネームの完全なリストは {{ic|/usr/share/debootstrap/scripts}} にあります。Debian イメージの場合は "repository-url" には {{ic|<nowiki>http://deb.debian.org/debian/</nowiki>}} などを指定します。Ubuntu のイメージの場合は "repository-url" は {{ic|<nowiki>http://archive.ubuntu.com/ubuntu/</nowiki>}} などとなります。
  +
  +
Arch と同様に、Debian や Ubuntu ではパスワードなしでログインすることはできません。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:
  +
  +
# cd /var/lib/machines
  +
# systemd-nspawn -D myContainer
  +
# passwd
  +
# logout
  +
  +
=== パッケージのビルドおよびテスト ===
  +
  +
使用例については、[[他のディストリビューションのパッケージの作成]] を参照してください。
  +
  +
== 管理 ==
  +
  +
{{ic|/var/lib/machines/}} にあるコンテナは、''machinectl'' コマンドによって制御することができます。内部的には {{ic|systemd-nspawn@.service}} ユニットのインスタンスを制御しています。{{ic|/var/lib/machines/}} のサブディレクトリはコンテナ名に対応しています。
  +
  +
{{Note|なんらかの理由でコンテナを {{ic|/var/lib/machines/}} に移動できない場合、シンボリックリンクが使えます。{{man|1|machinectl|FILES AND DIRECTORIES}} を参照してください。}}
  +
  +
=== systemd-nspawn オプションのデフォルト値 ===
  +
  +
''machinectl'' や {{ic|systemd-nspawn@.service}} 経由で起動されたコンテナは ''systemd-nspawn'' コマンドで起動されたコンテナとはオプションの既定値が異なることを理解することが重要です。サービスが使用する追加オプションは以下の通りです。
  +
* {{ic|-b}}/{{ic|--boot}} – マネージドコンテナは自動的に init プログラムを検索し、PID 1 として起動します。
  +
* {{ic|--network-veth}} つまり {{ic|--private-network}} – マネージドコンテナは仮想ネットワークインターフェースを取得し、ホストネットワークから切り離されます。詳細は、[[#ネットワーキング]] を参照してください。
  +
* {{ic|-U}} – カーネルがサポートしている場合、マネージドコンテナはデフォルトで user_namespaces(7) 機能を使用します。詳細は、[[#非特権コンテナ]] を参照してください。
  +
* {{ic|1=--link-journal=try-guest}}
  +
この動作は、コンテナごとの設定ファイルでオーバーライドすることができます。
  +
詳細は、[[#設定]] を参照してください。
   
 
=== machinectl ===
 
=== machinectl ===
   
  +
{{Note|''machinectl'' ツールを使うには [[systemd]] と {{Pkg|dbus}} がコンテナにインストールされている必要があります。詳しくは [https://github.com/systemd/systemd/issues/685] を参照。}}
コンテナの管理は原則 {{ic|$ machinectl}} コマンドで行います。このサービスを使って仮想マシンやコンテナの状態を確認したり操作します。オプションの詳細なリストは {{ic|machinectl(1)}} を参照してください。
 
   
=== のブート時にコンテナを起動する ===
+
コンテナはコマンドで管理できます。例えば、コンテナを起動するには、次のようにします。
   
  +
$ machinectl start ''container-name''
コンテナを頻繁に使用したいのなら、マシンの [[Arch ブートプロセス|init]] で起動させるのが楽です。それから ''machinectl'' を使ってログインすることが出来ます。
 
   
  +
同様に、{{ic|poweroff}}, {{ic|reboot}}, {{ic|status}}, {{ic|show}} などのサブコマンドがあります。詳細な説明については、{{man|1|machinectl|Machine Commands}} を参照してください。
まず、ホストにコンテナを''登録''する必要があります。登録するには、{{ic|# mv /path/to/''MyContainer'' /var/lib/container/''MyContainer''}} を実行するか'''または'''ディレクトリのシンボリックリンクを作成してください:
 
   
  +
{{Tip|電源オフと再起動の操作は、{{ic|poweroff}} と {{ic|reboot}} コマンドを使用してコンテナ内から実行することができます。}}
# ln -s /path/to/''MyContainer'' /var/lib/container/''MyContainer''
 
   
  +
その他の一般的なコマンドは以下の通りです:
その後 {{ic|systemd-nspawn@''MyContainer''.service}} を[[systemd#systemctl の基本的な使い方|有効化・起動]]してください。コンテナが登録されていることを確認するために、次のコマンドを実行してください:
 
   
{{hc|$ machinectl list|
+
* {{ic|machinectl list}} – show a list of currently running containers
  +
* {{ic|machinectl login container-name}} - 実行中のコンテナに新しいシェルを起動
MACHINE CONTAINER SERVICE
 
  +
* {{ic|machinectl shell ''[username@]container-name''}} – コンテナで対話的なシェルセッションを開きます(コンテナ内のログインプロセスを経ずにユーザープロセスが即座に呼びだす)。
''MyContainer'' container nspawn
 
  +
* {{ic|machinectl enable container-name}} または {{ic|machinectl enable container-name}} - コンテナを有効または無効にして、起動時に開始します。詳細については、[[#PC起動時にコンテナを自動で開始する]] を参照してください。
   
  +
''machinectl'' にはコンテナ(または仮想マシン)イメージとイメージ転送を管理するためのサブコマンドもあります。詳細については、{{man|1|machinectl|Image Commands}} および、{{man|1|machinectl|Image Transfer Commands}} を参照してください。
1 machines listed.
 
  +
  +
=== systemd ツールチェイン ===
  +
  +
systemd のコアツールチェインは多くがコンテナでも使えるようにアップデートされています。コンテナの名前を引数とする {{ic|1=-M, --machine=}} オプションをツールに付けるだけです。
  +
  +
例:
  +
  +
* 特定のマシンの journal ログを表示: {{bc|$ journalctl -M MyContainer}}
  +
* control group の中身を表示: {{bc|$ systemd-cgls -M MyContainer}}
  +
* コンテナの起動時間を表示: {{bc|$ systemd-analyze -M MyContainer}}
  +
* リソース利用状況を表示: {{bc|$ systemd-cgtop}}
  +
  +
== 設定 ==
  +
  +
=== コンテナ毎の設定 ===
  +
  +
グローバル設定のオーバーライドではなく、コンテナ毎の設定を指定するには、''.nspawn'' ファイルを使用できます。詳細については、 {{man|5|systemd.nspawn}} を参照してください。
  +
  +
{{Note|
  +
* ''.nspawn'' ファイルは、{{ic|machinectl remove}} を実行した時に、{{ic|/etc/systemd/nspawn/}} から予期せずに削除される場合があります。
  +
* {{ic|systemd-nspawn@.service}} ファイルで指定されている、{{ic|1=--settings=override}} がある場合、''.nspawn'' ファイルで指定されているネットワークオプションとコマンドラインオプションの相互作用で正しく動作しません。回避策としてサービスが {{ic|1=--network-veth}} を指定している場合でも、{{ic|1=VirtualEthernet=on}} オプションを含める必要があります。
 
}}
 
}}
   
  +
=== PC起動時にコンテナを自動で開始する ===
{{Tip|
 
  +
* ''systemd-nspawn'' サービスは次のコマンドを実行します: {{ic|<nowiki>/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=guest --directory=/var/lib/container/%i </nowiki>}}。ディスクイメージファイルを使用したりコンテナに [[SELinux|SELinux]] セキュリティを設定するために、コンテナのディレクトリから {{ic|/var/lib/container/MyCoantainer}} にシンボリックリンクが貼られていない場合、このファイルを修正してオプションを追加する必要があります。コンテナのネットワーク設定を分離させたい場合、[[systemd-networkd|systemd-networkd]] を参照してください。さらに詳しいブートオプションの情報は {{ic|systemd-nspawn(1)}} に載っています。
 
  +
コンテナを頻繁に使用する場合は、PC起動時に開始することをおすすめします。
* {{ic|systemd-nspawn@.service}} を無効にすると、{{ic|# systemd-nspawn -bD /path/to/container}} を実行して手動でコンテナを起動することができます。コンテナにログインした後は、{{ic|# systemctl poweroff}} を実行すればシャットダウンします。
 
  +
  +
まず、{{ic|machines.target}} が[[systemd#ユニットを使う|有効]]になっている事を確認します。
  +
[[#machinectl|machinectl]] で検出可能なコンテナは、有効または無効にできます:
  +
  +
$ machinectl enable ''container-name''
  +
  +
{{Note|
  +
* まず {{ic|systemd-nspawn@''container-name''.service}} ユニットを有効にする効果があります。
  +
* [[#systemd-nspawn オプションのデフォルト値]] で説明されているように、''machinectl'' と入力し開始されたコンテナは仮想 Ethernet インタフェースを取得します。プライベートネットワークを無効にするには、 [[#ホストネットワークを使う]] を参照してください。
 
}}
 
}}
   
  +
=== リソース制御 ===
[[cgroups|control group]] の中身を表示したい場合は、{{ic|$ systemd-cgls}} を実行してください。
 
   
  +
{{ic|systemctl set-property}} でコンテナの制限やリソース管理を実装するために、コントロールグループを利用することができます。{{man|5|systemd.resource-control}} を参照してください。例えば、メモリ容量やCPU使用率を制限できます。コンテナのメモリ消費を2GiBに制限するには:
=== コンテナにログイン・ログアウト ===
 
==== systemd-nspawn コマンド ====
 
まだ {{ic|systemd-nspawn@''MyContainer''.service}} を[[systemd#systemctl の基本的な使い方|有効化・起動]]していない場合は、次のコマンドを実行してください:
 
   
  +
# systemctl set-property systemd-nspawn@''container-name''.service MemoryMax=2G
{{ic|# systemd-nspawn -bD /path_to/''MyContainer''}}
 
==== machinectl コマンド ====
 
新しいターミナルウィンドウを開いて次のコマンドを実行してください:
 
   
  +
または、CPU時間の使用量をだいたい2コア分に制限したい場合:
{{hc|# machinectl login ''MyContainer''|
 
  +
Connected to container ''MyContainer''. Press ^] three times within 1s to exit session.
 
  +
# systemctl set-property systemd-nspawn@''container-name''.service CPUQuota=200%
Arch Linux ''Custom Kernel'' (pts/1)
 
  +
''MyContainer'' login:
 
  +
これにより以下の永続ファイルが作成されます。
  +
{{ic|/etc/systemd/system.control/systemd-nspawn@''container-name''.service.d/}}.
  +
  +
ドキュメントによると、{{ic|MemoryHigh}} はメモリ消費をチェックするための推奨される方法ですが、{{ic|MemoryMax}} のように厳密に制限されることはありません。{{ic|MemoryMax}} を最終防衛戦として残して、両方のオプションを使用できます。また、コンテナが認識できるCPUの数を制限しないことも考慮に入れてください。ただし、CPU時間合計に対して、コンテナが最大で取得する時間を制限することで、同様の結果が得られます。
  +
  +
{{Tip|これらの変更を一時的なものにしたい場合は、{{ic|--runtime}} オプションを渡すことができます。その結果は、''systemd-cgtop'' で確認できます。}}
  +
  +
=== ネットワーキング ===
  +
  +
''systemd-nspawn'' コンテナは、''ホストネットワーク'' または ''プライベートネットワーク''のいずれかを使用できます。
  +
* ホストネットワークモードでは、コンテナはホストネットワークへのフルアクセスが可能です。これは、コンテナがホスト上のすべてのネットワークサービスにアクセスできるようになり、コンテナからのパケットがホストのパケットとして外部ネットワークに表示される事を意味します(つまり、同じIPアドレスを共有します)。
  +
* プライベートネットワークモードでは、コンテナはホストのネットワークから切断されています。これにより、ループバックデバイスとコンテナに明示的に割り当てられたものを除いて、すべてのネットワークインターフェイスがコンテナを使用できなくなります。コンテナのネットワークインターフェイスを設定するには、いくつかの方法があります。
  +
** 既存のインターフェイスをコンテナに割り当てることができます(たとえば、複数のイーサネットデバイスがある場合)。
  +
** 既存のインターフェース(つまり、[[VLAN]]インターフェース)に関連付けられた仮想ネットワークインターフェースを作成して、コンテナーに割り当てることができます。
  +
** ホストとコンテナの間に仮想イーサネットリンクを作成できます。
  +
: 後者の場合、コンテナのネットワークは、(外部ネットワークや他のコンテナから) 完全に分離されており、ホストとコンテナ間のネットワークを構成するのは管理者の責任です。これには通常、複数の(物理または仮想)インターフェイスを接続するための [[ネットワークブリッジ]] の作成、または複数のインターフェイス間の [[wikipedia:ja:ネットワークアドレス変換|ネットワークアドレス変換]] の設定が含まれます。
  +
  +
ホストネットワーキングモードは、コンテナに割り当てられたインターフェースを構成するネットワーキングソフトウェアを実行しない ''アプリケーションコンテナ'' に適しています。ホストネットワーキングは、シェルから ''systemd-nspawn'' を実行するときのデフォルトのモードです。
  +
  +
一方、プライベート・ネットワーキング・モードは、ホスト・システムから隔離されている必要がある ''システムコンテナ'' に適しています。仮想イーサネットリンクの作成は、複雑な仮想ネットワークの作成を可能にする非常に柔軟なツールです。これは ''machinectl'' や {{ic|systemd-nspawn@.service}} によって起動されたコンテナのデフォルトモードです。
  +
  +
次のサブセクションでは、一般的なシナリオについて説明します。使用可能な ''systemd-nspawn'' のオプションの詳細については、{{man|1|systemd-nspawn|Networking Options}} を参照してください。
  +
  +
==== ホストネットワークを使う ====
  +
  +
プライベートネットワークを無効にし、''machinectl'' で開始されたコンテナで使用される仮想イーサネットリンクを作成するには、次のオプションを指定して、''.nspawn'' ファイルを追加します:
  +
  +
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
  +
[Network]
  +
VirtualEthernet=no
 
}}
 
}}
   
  +
これにより、{{ic|systemd-nspawn@.service}} の {{ic|-n}}/{{ic|--network-veth}} オプションが上書きされ、新しく開始されたコンテナはホストネットワークモードを使用します。
他のターミナルからログインすることで複数のセッションを開くことができます。
 
   
  +
==== 仮想イーサネットリンクを使用する ====
{{Note|{{ic|^]}} は {{ic|Ctrl+]}} キーシーケンスに相当します。セッションを終了するには {{ic|Ctrl}} を押しながら {{ic|]}} を3回押します。コンテナは立ち上がったまま、コンテナからログアウトされます。}}
 
   
  +
コンテナが、{{ic|-n}}/{{ic|--network-veth}} オプションで起動された場合、''systemd-nspawn'' はホストとコンテナの間に仮想イーサネットリンクを作成します。リンクのホスト側は、{{ic|ve-''container-name''}} という名前のネットワークインターフェイスとして利用可能になります。リンクのコンテナ側は、{{ic|hosts0}} という名前になります。このオプションは、{{ic|--private-network}} を意味することに注意してください。
=== コンテナのシャットダウン ===
 
   
  +
{{Note|
{{ic|reboot}} や {{ic|poweroff}} など {{ic|systemctl}} と同じように {{ic|machinectl}} で同じオプションを使ってコンテナの状態を制御することができます。「仮想マシンやコンテナの全てのプロセスを終了し、そのインスタンスで使われていたリソースの割り当てを全て解除」する {{ic|terminate}} オプションもあります。
 
  +
* コンテナ名が長すぎる場合、インターフェイス名は、[https://stackoverflow.com/a/29398765 15文字制限] に収まるように短縮されます(例: {{ic|ve-long-container-name}} の代わりに {{ic|ve-long-conKQGh}})。フルネームはインターフェイスの {{ic|altname}} プロパティとして設定され({{man|8|ip-link}}を参照)、インターフェイスの参照に使用できます。
   
  +
* {{ic|ip link}} でインターフェイスを調べる場合、インターフェイス名は、{{ic|ve-''container-name''@if2}} や {{ic|host0@if9}} のようにサフィックスを付けて表示されます。{{ic|@if''N''}} は実際にはインターフェイス名の一部ではありません。その代わりに、{{ic|ip link}} はこの情報を追加して、仮想イーサネットケーブルが相手側のどの ''slot'' に接続しているかを示します
他のオプションについては [http://www.freedesktop.org/software/systemd/man/machinectl.html man machinectl] を見て下さい。
 
  +
: 例えば、{{ic|ve-''foo''@if2}} とし表示されているホスト仮想イーサネットインターフェイスはコンテナ {{ic|''foo''}} に接続され、コンテナ内で {{ic|ip link}} を実行しているときに、index 2 で示されている 2 番目のネットワークインタフェースに接続されています。同様に、コンテナ内の {{ic|host0@if9}} という名前のインターフェイスは、ホスト上の 9 番目のネットワークインターフェイス接続されています。}}
  +
  +
コンテナを起動する際には、ホストとコンテナの両方のインターフェイスにIPアドレスを割り当てなければなりません。ホストとコンテナの両方で [[systemd-networkd]] を使用している場合、初期状態で実行されます:
  +
  +
* ホスト上の {{ic|/usr/lib/systemd/network/80-container-ve.network}} ファイルは {{ic|ve-container-name}} インターフェイスと一致し、DHCP サーバーを起動します。DHCP サーバーは、IP アドレスをホストインターフェイスとコンテナーに割り当てます。
  +
* {{ic|/usr/lib/systemd/network/80-container-host0.network}} コンテナ内のファイルは {{ic|host0}} インターフェイスと一致し、ホストから IP アドレスを受信する DHCP クライアントを起動します。
  +
  +
[[systemd-networkd]] を使用しない場合は、静的IPアドレスを設定するか、ホストインターフェイスで、DHCP サーバを起動し、コンテナで DHCP クライアントを起動できます。詳細については、[[ネットワーク設定]] を参照してください。
  +
  +
コンテナに外部ネットワークへのアクセスを許可するには、[[インターネット共有#NAT の有効化]] の説明に従って NAT を設定します。[[systemd-networkd]] を使用する場合、これは、{{ic|/usr/lib/systemd/network/80-container-ve.network}} ファイルの {{ic|1=IPMasquerade=yes}} オプションを介して(部分的に)自動的に行われます。ただし、これは次のような [[iptables]] ルールのみを発行します。
  +
  +
-t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE
  +
  +
{{ic|filter}} テーブルは、[[インターネット共有#NAT の有効化]]のように手動で設定する必要があります。ワイルドカードを使用して、{{ic|ve-}} で始まるすべてのインターフェイスに一致させることができます:
  +
  +
# iptables -A FORWARD -i ve-+ -o ''internet0'' -j ACCEPT
  +
  +
{{Note|''systemd-networkd'' は、[https://tldp.org/HOWTO/Querying-libiptc-HOWTO/whatis.html libiptc] ライブラリを使用して、[[iptables]] と対話します。 [[nftables]] を使用する場合は、{{Pkg|iptables-nft}} 変換レイヤーをインストールします。[https://github.com/systemd/systemd/issues/13307 systemd issue 13307] も参照してください。}}
  +
  +
{{Accuracy|Investigate if/why the following is necessary.}}
  +
  +
また、[[インターネット共有#NAT の有効化]]で説明しているように、ルール {{ic|-A FORWARD -i ve-+ -o ''internet0'' -j ACCEPT}} が機能しない場合があります。その場合は、{{ic|-A FORWARD -i ve-+ -j ACCEPT}} を試してみてください。
  +
  +
==== ネットワークブリッジを使用する ====
  +
  +
ホストシステムに[[ネットワークブリッジ]]を構成している場合は、コンテナの仮想イーサネットリンクを作成し、そのホスト側をネットワークブリッジに追加できます。 これは、{{ic|1=--network-bridge=''bridge-name''}} オプションを使用して実行されます。{{ic|--network-bridge}} は {{ic|--network-veth}} を意味することに注意してください。つまり、仮想イーサネットリンクは自動的に作成されます。 ただし、リンクのホスト側は {{ic|ve-}} ではなく {{ic|vb-}} プリフィックスを使用するため、DHCP サーバーと IP マスカレードを起動するための systemd-networkd オプションは適用されません。
  +
  +
ブリッジの管理は管理者に任されています。例えば、ブリッジは物理インターフェースと仮想インターフェースを接続したり、複数のコンテナの仮想インターフェースのみを接続したりすることができます。[[systemd-networkd]] を使用した設定例については、[[systemd-networkd#Network bridge with DHCP]] と [[systemd-networkd#Network bridge with static IP addresses]] を参照してください。
  +
  +
また、{{ic|1=--network-zone=zone-name}} オプションは {{ic|--network-bridge}} と似ていますが、ネットワークブリッジは ''systemd-nspawn'' と ''systemd-networkd'' によって自動的に管理されます。{{ic|vz-zone-name}} という名前のブリッジインターフェースは、{{ic|1=--network-zone=zone-name}} を設定した最初のコンテナが起動したときに自動的に作成され、{{ic|1=--network-zone=zone-name}} を設定した最後のコンテナが終了したときに自動的に削除されます。したがって、このオプションを使用すると、複数の関連するコンテナを共通の仮想ネットワーク上に簡単に配置することができます。{{ic|vz-*}} インターフェースは、{{ic|/usr/lib/systemd/network/80-container-vz.network}} ファイルのオプションを使って、{{ic|ve-*}} インターフェースと同じように [[systemd-networkd]] によって管理されることに注意してください。
  +
  +
==== 「macvlan」または「ipvlan」インターフェースを使用する ====
  +
  +
仮想イーサネットリンク(ホスト側がブリッジに追加される場合とされない場合があります)を作成する代わりに、既存の物理インターフェイス(つまり、[[VLAN]] インターフェイス)上に仮想インターフェイスを作成し、それをコンテナに追加できます。仮想インターフェイスは、基盤となるホストインターフェイスとブリッジされるため、コンテナは外部ネットワークに公開されます。これにより、ホストが接続されているのと同じ LAN から DHCP を介して個別の IP アドレスを取得できます。
  +
  +
''systemd-nspawn'' には2つのオプションがあります:
  +
  +
* {{ic|1=--network-macvlan=''interface''}} – 仮想インターフェイスは、基盤となる物理インターフェイスとは異なるMACアドレスを持ち、{{ic|mv-''interface''}} という名前が付けられます。
  +
  +
* {{ic|1=--network-ipvlan=''interface''}} – 仮想インターフェイスは、基礎となる物理インターフェイスと同じMACアドレスを持ち、{{ic|iv-''interface''}} と名付けられます。
  +
  +
どちらのオプションも {{ic|--private-network}} を意味します。
  +
  +
==== 既存のインターフェイスを使用する ====
  +
  +
ホストシステムに複数の物理ネットワークインターフェイスがある場合は、 {{ic|1=--network-interface=''interface''}} を使用してコンテナにインターフェイスを割り当てることができます(コンテナが起動している間はホストからは利用できないようにします)。{{ic|--network-interface}} は{{ic|--private-network}} を意味することに注意してください。
  +
  +
{{Note|''systemd-nspawn'' コンテナにワイヤレスネットワークインターフェイスを渡すことは現在サポートされていません。[https://github.com/systemd/systemd/issues/7873]}}
  +
  +
=== ポートマッピング ===
  +
  +
プライベートネットワークが有効になっている場合、{{ic|-p}}/{{ic|--port}} オプションを使用するか、''.nspawn'' ファイルの {{ic|Port}} 設定を使用して、ホスト上の個々のポートをコンテナ上のポートにマップできます。これは {{ic|nat}} テーブルに [[iptables]] ルールを発行することで行いますが、フィルタテーブルの {{ic|FORWARD}} チェーンは [[#Use a virtual Ethernet link]] で示されているように、手動で設定する必要があります。
  +
  +
例えば、ホスト上のTCPポート8000をコンテナ内のTCPポート80にマッピングするには、次のように入力します:
  +
  +
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
  +
[Network]
  +
Port=tcp:8000:80
  +
}}
  +
  +
{{Note|
  +
* ''systemd-nspawn'' は、ポートをマッピングする際に {{ic|loopback}} インターフェイスを明示的に除外します。したがって、上記の例では、{{ic|localhost:8000}} はホストに接続し、コンテナには接続しません。他のインターフェイスへの接続のみがポートマッピングの対象となります。詳細は、[https://github.com/systemd/systemd/issues/6106] を参照してください。
  +
* ポートマッピングは IPv4 接続に対してのみ機能します。 [https://github.com/systemd/systemd/issues/10254]
  +
}}
  +
  +
=== ドメイン名前解決 ===
  +
  +
コンテナ内の [[ドメイン名前解決]] は ''systemd-nspawn'' の {{ic|--resolv-conf}} オプションか、''.nspawn'' ファイルの {{ic|1=ResolvConf=}} オプションで設定できます。{{man|1|systemd-nspawn|統合オプション}} に多くの値が記述されています。
  +
  +
デフォルト値は {{ic|auto}} で以下の事を意味します:
  +
  +
* {{ic|--private-network}} が有効になっている場合、{{ic|/etc/resolv.conf}} はコンテナ内のまま残ります。
  +
* あるいは、ホストで [[systemd-resolved]] が実行されている場合、そのスタブ {{ic|resolv.conf}} ファイルがコンテナにコピーまたはバインドマウントされます。
  +
* それ以外の場合、{{ic|/etc/resolv.conf}} ファイルはホストからコンテナにコピーされるか、バインドマウントされます。
  +
  +
最後の2つのケースでは、コンテナルートが書き込み可能な場合はファイルがコピーされ、読み取り専用の場合はバインドマウントされます。
  +
  +
== ヒントとテクニック ==
  +
  +
=== 非特権コンテナ ===
  +
  +
''systemd-nspawn'' は非特権コンテナをサポートしますが、コンテナは root として起動する必要があります。
  +
  +
{{Note|この機能には {{man|7|user_namespaces}} が必要です。詳細については、[[Linux Containers#Enable support to run unprivileged containers (optional)]] を参照してください。}}
  +
  +
これを行う最も簡単な方法は、{{ic|-U}} オプションを使用して ''systemd-nspawn'' が自動的に未使用の UIDs/GIDs の範囲を選択させることです:
  +
  +
# systemd-nspawn -bUD ~/MyContainer
  +
  +
カーネルがユーザー名前空間をサポートしている場合、{{ic|-U}} オプションは {{ic|1=--private-users=pick --private-users-chown}} と同等です。これはコンテナの開始時にコンテナ内のファイルとディレクトリが選択された範囲のプライベート UIDs/GIDs に変更される事を意味します。詳細は、
  +
{{man|1|systemd-nspawn|User Namespacing Options}} を参照してください。
  +
  +
{{Note|コンテナの UID/GID の範囲を手動で指定することもできますが、これが役立つことはほとんどありません。}}
  +
  +
プライベート UID/GID の範囲を持つコンテナを起動したら、パーミッションエラーを避けるために、そのコンテナを使い続ける必要があります。あるいは、{{ic|--private-users-chown}} (または {{ic|-U}}) のファイルシステムへの影響を元に戻すには、0で始まるIDの範囲を指定します:
  +
  +
# systemd-nspawn -D ~/MyContainer --private-users=0 --private-users-chown
   
 
=== X 環境 ===
 
=== X 環境 ===
90行目: 309行目:
 
新しいコンテナで X アプリケーションを動かす必要がある場合は [[Xhost]] を見て下さい。
 
新しいコンテナで X アプリケーションを動かす必要がある場合は [[Xhost]] を見て下さい。
   
  +
外部の X サーバーにコンテナのセッションを接続するには {{ic|DISPLAY}} 環境変数を設定する必要があります。
=== ネットワーク ===
 
   
  +
X は必要なファイルを {{ic|/tmp}} ディレクトリに保存します。コンテナから全てを表示させるには、{{ic|/tmp}} ディレクトリのファイルにアクセスできるようにしなくてはなりません。コンテナを起動するときに {{ic|--bind<nowiki>=</nowiki>/tmp/.X11-unix:/tmp/.X11-unix}} オプションを追加してください。
上で説明しているインストールでは、何も設定しなくてもネットワークが動作するコンテナが作られるので、追加の設定は必要ありません。もっと複雑なネットワークを設定してホストのネットワークからコンテナのネットワークを分離させたいときは、[[systemd-networkd|systemd-networkd]] を見て下さい。
 
  +
  +
{{Note|systemd バージョン 235 には [https://github.com/systemd/systemd/issues/7093 バグ] が存在し、{{ic|/tmp/.X11-unix}} がファイルシステムから消失することがあります。問題を回避するには {{ic|/tmp/.X11-unix}} を読み取り専用でバインドしてください: {{ic|--bind-ro<nowiki>=</nowiki>/tmp/.X11-unix/X0}}。{{ic|/run/user/1000}} もバインドしている場合は明示的に {{ic|/run/user/1000/bus}} を読み取り専用でバインドすることで dbus ソケットが削除されないように保護することができます。}}
  +
  +
==== xhost の回避 ====
  +
  +
{{ic|xhost}} は、Xサーバに対してかなり粗いアクセス権しか与えません。​{{ic|$XAUTHORITY}} ファイルを使用すると、より詳細なアクセス制御が可能になります。​残念ながら、コンテナ内の{{ic|$XAUTHORITY}} ファイルにアクセスできるようにしただけではうまくいきません。{{ic|$XAUTHORITY}} ファイルはホスト固有のものですが、コンテナは別のホストです。​stackoverflowを参考にした以下のトリックを使えば、Xサーバがコンテナ内で実行されているXアプリケーションから、{{ic|$XAUTHORITY}} ファイルを受け入れるようにすることができます:
  +
  +
$ XAUTH=/tmp/container_xauth
  +
$ xauth nextract - "$DISPLAY" | sed -e 's/^..../ffff/' | xauth -f "$XAUTH" nmerge -
  +
# systemd-nspawn -D myContainer --bind=/tmp/.X11-unix --bind="$XAUTH" -E DISPLAY="$DISPLAY" -E XAUTHORITY="$XAUTH" --as-pid2 /usr/bin/xeyes
  +
  +
上記の2行目では、接続ファミリーを ""FamilyWild""(値{{ic|65535}}) に設定しているため、エントリはすべての表示に一致します。​詳細は{{man|7|Xsecurity}} を参照。
  +
  +
==== Firefox を起動する ====
  +
  +
PID 1 として実行するには
  +
  +
# systemd-nspawn --setenv=DISPLAY=:0 \
  +
--setenv=XAUTHORITY=~/.Xauthority \
  +
--bind-ro=$HOME/.Xauthority:/root/.Xauthority \
  +
--bind=/tmp/.X11-unix \
  +
-D ~/containers/firefox \
  +
firefox
  +
  +
あるいは、コンテナを起動して、例えば、[[systemd-networkd]] に仮想ネットワークインターフェイスを設定することもできます。
  +
  +
# systemd-nspawn --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
  +
--bind=/tmp/.X11-unix \
  +
-D ~/containers/firefox \
  +
--network-veth -b
  +
  +
コンテナが起動したら、次のようにXorgバイナリを実行します:
  +
  +
# systemd-run -M firefox --setenv=DISPLAY=:0 firefox
  +
  +
=== ホストのファイルシステムにアクセス ===
  +
  +
例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:
  +
  +
# systemd-nspawn --bind=/var/cache/pacman/pkg
  +
  +
詳しくは {{man|1|systemd-nspawn}} の {{ic|--bind}} と {{ic|--bind-ro}} を参照してください。
  +
  +
ファイルを使ってコンテナごとにバインドを設定することもできます:
  +
  +
{{hc|/etc/systemd/nspawn/''my-container''.nspawn|<nowiki>
  +
[Files]
  +
Bind=/var/cache/pacman/pkg
  +
</nowiki>}}
  +
  +
[[#コンテナごとに設定を指定する]]を参照。
  +
  +
=== systemd を使っていない環境で動作させる ===
  +
  +
[[Init#systemd-nspawn]] を見て下さい。
  +
  +
=== Btrfs のサブボリュームをコンテナのルートとして使う ===
  +
  +
[[Btrfs#サブボリューム|Btrfs サブボリューム]]をコンテナのルートのテンプレートとして使うには、{{ic|--template}} フラグを使用します。サブボリュームのスナップショットを使ってコンテナのルートディレクトリが生成されます。
  +
  +
{{Note|指定されたテンプレートのパスがサブボリュームのルートでなかった場合、ツリー全体がコピーされます。その場合、非常に時間がかかります。}}
  +
  +
例えば、{{ic|/.snapshots/403/snapshot}} に存在するスナップショットを使うには:
  +
  +
# systemd-nspawn --template=/.snapshots/403/snapshots -b -D ''my-container''
  +
  +
{{ic|''my-container''}} は作成するコンテナのディレクトリの名前に置き換えてください。電源を切っても、新しく作成されたサブボリュームは消えません。
  +
  +
=== コンテナの一時的な Btrfs スナップショットを使う ===
  +
  +
{{ic|--ephemeral}} や {{ic|-x}} フラグを使ってコンテナの一時的な btrfs スナップショットを作成してコンテナのルートとして利用できます。コンテナの実行中に変更が加えられても保存されません。例:
  +
  +
# systemd-nspawn -D ''my-container'' -xb
  +
  +
''my-container'' はシステムに存在する既存のコンテナのディレクトリに置き換えてください。例えば {{ic|/}} が btrfs のサブボリュームだった場合、以下のコマンドで実行中のホスト環境の一時的なコンテナを作成することができます:
  +
  +
# systemd-nspawn -D / -xb
  +
  +
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。
  +
  +
=== system-nspawn で docker を実行 ===
  +
  +
[[Docker]] コンテナを実行するには、 {{ic|/sys/fs/cgroup}} の {{ic|rw}} 権限が必要です。このコンテナは、 cgroup 名前空間のため、デフォルトで「'システムn起動' 」によって読み取り専用でマウントされます。ただし,ホストシステムから bind-mounting {{ic|/sys/fs/cgroup}} を実行して,必要な機能と権限を有効にすることで, ''システムn起動'' コンテナ内で Docker を実行することは可能です。
  +
  +
{{Note|次の手順は、基本的に cgroup / user 名前空間をコンテナと共有し、カーネルキーリングのアクセス許可を付与して、それを特権付きコンテナにすることです。これにより、攻撃対象が増え、セキュリティレベルが低下する可能性があります。手順に従う前に、必ず実際のメリットを理解してください。}}
  +
  +
まず、cgroup 名前空間は {{ic|systemctl edit systemd-nspawn@myContainer}} によって無効にされている必要があります。
  +
  +
{{hc|systemctl edit systemd-nspawn@myContainer|<nowiki>
  +
[Service]
  +
Environment=SYSTEMD_NSPAWN_USE_CGNS=0
  +
</nowiki>}}
  +
  +
次に、{{ic|/etc/systemd/nspawn/myContainer.nspawn}} (存在しない場合は作成) を編集し、次の設定を追加します。
  +
  +
{{hc|/etc/systemd/nspawn/myContainer.nspawn|<nowiki>
  +
[Exec]
  +
Capability=all
  +
SystemCallFilter=add_key keyctl
  +
PrivateUsers=no
  +
  +
[Files]
  +
Bind=/sys/fs/cgroup
  +
</nowiki>}}
  +
  +
これにより、コンテナにすべての機能が付与され、ユーザーの名前空間が無効になり、2つのシステムコール {{ic|add_key}} と {{ic|keyctl}} (カーネルキーリングに関連し、Dockerで必要) がホワイトリストに追加され、ホストからコンテナへのバインドマウント {{ic|/sys/fs/cgroup}} が行われます。これらのファイルを編集したら、有効にするためにコンテナの電源をオフにして再起動する必要があります。この変更の前にコンテナでユーザネームスペースが有効になっていた場合 (これは、{{ic|systemd-nspawn@.service}} ユニットが使用されている場合のデフォルトです。) アクセス権エラーを回避するために、ユーザネームスペースによるアクセス権を元に戻す必要があります。詳細は、 [[systemd-nspawn#非特権コンテナ]] を参照してください。
  +
  +
{{Note|
  +
* systemd-nspawn 内で Docker を起動する前に、ホストに {{ic|overlay}} モジュールをロードして、 {{ic|overlay2}} ストレージドライバ (Docker のデフォルトストレージドライバ) を正しく使用する必要がある場合があります。ドライバをロードしないと、 Docker は非効率なドライバ {{ic|vfs}} を選択し、 Docker コンテナのすべてのレイヤのすべてをコピーします。モジュールを自動的にロードする方法については、 [https://wiki.archlinux.org/title/Systemd-nspawn#Unprivileged_containers Automatic module loading with systemd] を参照してください。
  +
* 2020年11月時点で, cgroups v2は ''systemd-nspawn'' 内の Docker を破壊する可能性があります。この方法で Docker を使用する場合は、カーネルパラメータ {{ic|1=systemd.unified_cgroup_hierarchy=1}} を設定しないでください。
  +
}}
  +
  +
=== root 権限なしで machinectl を使用する ===
  +
  +
machined が [[Polkit]] を有効にしている場合、polkit ルールを作成して、root ユーザ にならずに特定のアクションを実行できるようにします。パーミッションの違いは、{{ic|/usr/share/polkit-1/actions/org.freedesktop.machine1.policy}} で説明されており、すべて、{{ic|org.freedesktop.machine1.}} の下にあります。
  +
  +
"foo" という名前のユーザが root権限なしですべてのアクションを実行できるようにするには、ポリシーを追加します:
  +
  +
{{hc|/etc/polkit-1/rules.d/machined.rules|<nowiki>
  +
polkit.addRule(
  +
function(action, subject) {
  +
if (action.id.startsWith("org.freedesktop.machine1.") && subject.user == "foo") {
  +
return polkit.Result.YES;
  +
}
  +
}
  +
);
  +
</nowiki>}}
  +
  +
さらに、ユーザーは、{{ic|systemd-nspawn@}} コンテナーを開始および停止できるようにユニットを管理するためのアクセス許可を必要とします。これを許可するには、このポリシーを追加します:
  +
  +
{{hc|/etc/polkit-1/rules.d/machined.rules|<nowiki>
  +
polkit.addRule(
  +
function(action, subject) {
  +
if ((action.id.startsWith("org.freedesktop.machine1.") || (action.id == "org.freedesktop.systemd1.manage-units" && action.lookup("unit").startsWith("systemd-nspawn@"))) && subject.user == "foo") {
  +
return polkit.Result.YES;
  +
}
  +
}
  +
);
  +
</nowiki>}}
   
 
== トラブルシューティング ==
 
== トラブルシューティング ==
   
 
=== root ログインが失敗する ===
 
=== root ログインが失敗する ===
ログインしようとしたときに以下が表示される場合:
+
({{ic|machinectl login <name>}} を使用して) ログインしようとしたときに以下のエラーが表示される場合:
   
 
arch-nspawn login: root
 
arch-nspawn login: root
 
Login incorrect
 
Login incorrect
   
そして ''journalctl'' が以下のように表示する場合:
+
そして {{ic|journalctl}} が以下のように表示する場合:
   
 
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
 
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
   
コンテナのファイルシステムから [http://unix.stackexchange.com/questions/41840/effect-of-entries-in-etc-securetty/41939#41939 /etc/securetty を削除] しててください。
+
コンテナのファイルシステム上にある {{ic|/etc/securetty}} のターミナル名のリストに {{ic|pts/0}} を追加してください。詳しくは [https://unix.stackexchange.com/questions/41840/effect-of-entries-in-etc-securetty/41939#41939] を参照。また、コンテナの {{ic|/etc/securetty}} を削除して root で全ての tty にログインできるようにするという方法もあります。[https://github.com/systemd/systemd/issues/852] を見てください。
  +
  +
=== execv(...) failed: Permission denied ===
  +
  +
{{ic|systemd-nspawn -bD ''/path/to/container''}} によってコンテナを起動 (またはコンテナ内で何かを実行) しようとすると、以下のようなエラーが発生します:
  +
  +
execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Permission denied
  +
  +
問題のファイル (例えば {{ic|/lib/systemd/systemd}}) のパーミッションが正しくても、コンテナが保存されているファイルシステムを非rootユーザーとしてマウントした結果である可能性があります。例えば、[[fstab]] に {{ic|noauto,user,...}} というオプションを指定して手動でディスクをマウントした場合、''systemd-nspawn'' は rootが所有するファイルであっても実行は許可しません。
  +
  +
=== TERM の端末タイプが間違っている (色が壊れている) ===
  +
  +
{{ic|machinectl login}} でコンテナにログインすると、コンテナ内の端末の色とキーストロークが壊れることがあります。これは、{{ic|TERM}} 環境変数の端末タイプが正しくないことが原因である可能性があります。環境変数はホストのシェルから継承されませんが、明示的に設定されていない限り、systemd ({{ic|vt220}}) で固定されたデフォルトに戻ります。設定するには、コンテナ内の {{ic|container-getty@.service}} サービス用のオーバーレイを作成して、{{ic|machinectl login}} の login getty を起動し、ログインしているホスト端末と一致する値を {{ic|TERM}} に設定してください。
  +
  +
{{hc|/etc/systemd/system/container-getty@.service.d/term.conf|2=
  +
[Service]
  +
Environment=TERM=xterm-256color
  +
}}
  +
  +
もしくは、{{ic|machinectl shell}} を使用してください。端末から {{ic|TERM}} 環境変数を適切に継承します。
  +
  +
=== コンテナ内へのNFS共有のマウント ===
  +
  +
現時点(2019年6月)では利用できません。
   
 
== 参照 ==
 
== 参照 ==
   
* [http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html systemd-nspawn man ページ]
+
* [https://www.freedesktop.org/software/systemd/man/machinectl.html machinectl man ページ]
* [http://lwn.net/Articles/572957/ Creating containers with systemd-nspawn]
+
* [https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html systemd-nspawn man ページ]
  +
* [https://lwn.net/Articles/572957/ Creating containers with systemd-nspawn]
* [http://www.freedesktop.org/software/systemd/man/machinectl.html machinectl man ページ]
 
  +
* [https://www.youtube.com/results?search_query=systemd-nspawn&aq=f Lennart Pottering による systemd-nspawn のプレゼンテーション]
  +
* [http://dabase.com/e/12009/ Running Firefox in a systemd-nspawn container]

2021年6月1日 (火) 17:59時点における最新版

関連記事

systemd-nspawnchroot コマンドに似ていますが、chroot を強化したものです。

systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム階層だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため chroot よりも強力です。

systemd-nspawn/sys, /proc/sys, /sys/fs/selinux などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードが作成はできません。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールのロードもできません。

仕組みとしては Lxc-systemdLibvirt-lxc と異なり、とてもシンプルなツールで設定を行います。

目次

インストール

systemd-nspawnsystemd に含まれています。

サンプル

コンテナに最小限の Arch Linux を作成して起動

まず arch-install-scripts パッケージをインストールしてください。

次に、コンテナを置くためのディレクトリを作成してください。この例では、~/MyContainer を使用します。

そして、pacstrap を使って最小限の arch システムをコンテナにインストールします。最低限でも base パッケージはインストールする必要があります。

# pacstrap -c ~/MyContainer base [additional pkgs/groups]
ヒント: base パッケージは、linux カーネルパッケージに依存せず、コンテナにも対応しています。

インストールが完了したら、コンテナに chroot し、root パスワードを設定します。

# systemd-nspawn -D ~/MyContainer
# passwd
# logout

最後に、コンテナを起動します。

# systemd-nspawn -b -D ~/MyContainer

-b オプションはシェルを実行する代わりにコンテナを起動します (つまり PID=1 として systemd を実行)。-D にはコンテナのルートディレクトリにするディレクトリを指定します。

コンテナが開始したら、設定したパスワードを使って "root" でログインしてください。

ノート: "Login incorrect" でログインが失敗する場合、問題は、securetty TTY デバイスのホワイトリストである可能性があります。#root ログインが失敗する をご確認ください。

コンテナの電源を切りたいときはコンテナの中から poweroff を実行することで出来ます。ホストからは、machinectl ツールでコンテナを制御できます。

ノート: コンテナの中からセッションを終了するには Ctrl を押しながら ] を素早く3回押してください。US キーボード以外の場合は ] の代わりに % を使用します。

Debian や Ubuntu 環境の作成

debootstrapdebian-archive-keyringubuntu-keyring のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。

ノート: systemd-nspawn を使用するにはコンテナ内の OS で systemd が PID 1 として動作している必要があります。Ubuntu 15.04 以前は、そのままでは動作せず、upstart から systemd への移行が必須です。また、コンテナ環境に systemd-container パッケージをインストールしてください。

後は簡単に Debian や Ubuntu 環境をセットアップできます:

# cd /var/lib/machines
# debootstrap --include=systemd-container --components=main,universe codename container-name repository-url

Debian の場合、コードネームとして指定するのは "stable" や "testing" などのローリングの名前か "stretch" や "sid" などのリリース名になります。Ubuntu の場合、"xenial" や "zesty" などのコードネームを使ってください。コードネームの完全なリストは /usr/share/debootstrap/scripts にあります。Debian イメージの場合は "repository-url" には http://deb.debian.org/debian/ などを指定します。Ubuntu のイメージの場合は "repository-url" は http://archive.ubuntu.com/ubuntu/ などとなります。

Arch と同様に、Debian や Ubuntu ではパスワードなしでログインすることはできません。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:

# cd /var/lib/machines
# systemd-nspawn -D myContainer
# passwd
# logout

パッケージのビルドおよびテスト

使用例については、他のディストリビューションのパッケージの作成 を参照してください。

管理

/var/lib/machines/ にあるコンテナは、machinectl コマンドによって制御することができます。内部的には systemd-nspawn@.service ユニットのインスタンスを制御しています。/var/lib/machines/ のサブディレクトリはコンテナ名に対応しています。

ノート: なんらかの理由でコンテナを /var/lib/machines/ に移動できない場合、シンボリックリンクが使えます。machinectl(1) § FILES AND DIRECTORIES を参照してください。

systemd-nspawn オプションのデフォルト値

machinectlsystemd-nspawn@.service 経由で起動されたコンテナは systemd-nspawn コマンドで起動されたコンテナとはオプションの既定値が異なることを理解することが重要です。サービスが使用する追加オプションは以下の通りです。

  • -b/--boot – マネージドコンテナは自動的に init プログラムを検索し、PID 1 として起動します。
  • --network-veth つまり --private-network – マネージドコンテナは仮想ネットワークインターフェースを取得し、ホストネットワークから切り離されます。詳細は、#ネットワーキング を参照してください。
  • -U – カーネルがサポートしている場合、マネージドコンテナはデフォルトで user_namespaces(7) 機能を使用します。詳細は、#非特権コンテナ を参照してください。
  • --link-journal=try-guest

この動作は、コンテナごとの設定ファイルでオーバーライドすることができます。 詳細は、#設定 を参照してください。

machinectl

ノート: machinectl ツールを使うには systemddbus がコンテナにインストールされている必要があります。詳しくは [1] を参照。

コンテナはコマンドで管理できます。例えば、コンテナを起動するには、次のようにします。

$ machinectl start container-name

同様に、poweroff, reboot, status, show などのサブコマンドがあります。詳細な説明については、machinectl(1) § Machine Commands を参照してください。

ヒント: 電源オフと再起動の操作は、poweroffreboot コマンドを使用してコンテナ内から実行することができます。

その他の一般的なコマンドは以下の通りです:

  • machinectl list – show a list of currently running containers
  • machinectl login container-name - 実行中のコンテナに新しいシェルを起動
  • machinectl shell [username@]container-name – コンテナで対話的なシェルセッションを開きます(コンテナ内のログインプロセスを経ずにユーザープロセスが即座に呼びだす)。
  • machinectl enable container-name または machinectl enable container-name - コンテナを有効または無効にして、起動時に開始します。詳細については、#PC起動時にコンテナを自動で開始する を参照してください。

machinectl にはコンテナ(または仮想マシン)イメージとイメージ転送を管理するためのサブコマンドもあります。詳細については、machinectl(1) § Image Commands および、machinectl(1) § Image Transfer Commands を参照してください。

systemd ツールチェイン

systemd のコアツールチェインは多くがコンテナでも使えるようにアップデートされています。コンテナの名前を引数とする -M, --machine= オプションをツールに付けるだけです。

例:

  • 特定のマシンの journal ログを表示:
    $ journalctl -M MyContainer
  • control group の中身を表示:
    $ systemd-cgls -M MyContainer
  • コンテナの起動時間を表示:
    $ systemd-analyze -M MyContainer
  • リソース利用状況を表示:
    $ systemd-cgtop

設定

コンテナ毎の設定

グローバル設定のオーバーライドではなく、コンテナ毎の設定を指定するには、.nspawn ファイルを使用できます。詳細については、 systemd.nspawn(5) を参照してください。

ノート:
  • .nspawn ファイルは、machinectl remove を実行した時に、/etc/systemd/nspawn/ から予期せずに削除される場合があります。
  • systemd-nspawn@.service ファイルで指定されている、--settings=override がある場合、.nspawn ファイルで指定されているネットワークオプションとコマンドラインオプションの相互作用で正しく動作しません。回避策としてサービスが --network-veth を指定している場合でも、VirtualEthernet=on オプションを含める必要があります。

PC起動時にコンテナを自動で開始する

コンテナを頻繁に使用する場合は、PC起動時に開始することをおすすめします。

まず、machines.target有効になっている事を確認します。 machinectl で検出可能なコンテナは、有効または無効にできます:

$ machinectl enable container-name
ノート:

リソース制御

systemctl set-property でコンテナの制限やリソース管理を実装するために、コントロールグループを利用することができます。systemd.resource-control(5) を参照してください。例えば、メモリ容量やCPU使用率を制限できます。コンテナのメモリ消費を2GiBに制限するには:

# systemctl set-property systemd-nspawn@container-name.service MemoryMax=2G

または、CPU時間の使用量をだいたい2コア分に制限したい場合:

# systemctl set-property systemd-nspawn@container-name.service CPUQuota=200%

これにより以下の永続ファイルが作成されます。 /etc/systemd/system.control/systemd-nspawn@container-name.service.d/.

ドキュメントによると、MemoryHigh はメモリ消費をチェックするための推奨される方法ですが、MemoryMax のように厳密に制限されることはありません。MemoryMax を最終防衛戦として残して、両方のオプションを使用できます。また、コンテナが認識できるCPUの数を制限しないことも考慮に入れてください。ただし、CPU時間合計に対して、コンテナが最大で取得する時間を制限することで、同様の結果が得られます。

ヒント: これらの変更を一時的なものにしたい場合は、--runtime オプションを渡すことができます。その結果は、systemd-cgtop で確認できます。

ネットワーキング

systemd-nspawn コンテナは、ホストネットワーク または プライベートネットワークのいずれかを使用できます。

  • ホストネットワークモードでは、コンテナはホストネットワークへのフルアクセスが可能です。これは、コンテナがホスト上のすべてのネットワークサービスにアクセスできるようになり、コンテナからのパケットがホストのパケットとして外部ネットワークに表示される事を意味します(つまり、同じIPアドレスを共有します)。
  • プライベートネットワークモードでは、コンテナはホストのネットワークから切断されています。これにより、ループバックデバイスとコンテナに明示的に割り当てられたものを除いて、すべてのネットワークインターフェイスがコンテナを使用できなくなります。コンテナのネットワークインターフェイスを設定するには、いくつかの方法があります。
    • 既存のインターフェイスをコンテナに割り当てることができます(たとえば、複数のイーサネットデバイスがある場合)。
    • 既存のインターフェース(つまり、VLANインターフェース)に関連付けられた仮想ネットワークインターフェースを作成して、コンテナーに割り当てることができます。
    • ホストとコンテナの間に仮想イーサネットリンクを作成できます。
後者の場合、コンテナのネットワークは、(外部ネットワークや他のコンテナから) 完全に分離されており、ホストとコンテナ間のネットワークを構成するのは管理者の責任です。これには通常、複数の(物理または仮想)インターフェイスを接続するための ネットワークブリッジ の作成、または複数のインターフェイス間の ネットワークアドレス変換 の設定が含まれます。

ホストネットワーキングモードは、コンテナに割り当てられたインターフェースを構成するネットワーキングソフトウェアを実行しない アプリケーションコンテナ に適しています。ホストネットワーキングは、シェルから systemd-nspawn を実行するときのデフォルトのモードです。

一方、プライベート・ネットワーキング・モードは、ホスト・システムから隔離されている必要がある システムコンテナ に適しています。仮想イーサネットリンクの作成は、複雑な仮想ネットワークの作成を可能にする非常に柔軟なツールです。これは machinectlsystemd-nspawn@.service によって起動されたコンテナのデフォルトモードです。

次のサブセクションでは、一般的なシナリオについて説明します。使用可能な systemd-nspawn のオプションの詳細については、systemd-nspawn(1) § Networking Options を参照してください。

ホストネットワークを使う

プライベートネットワークを無効にし、machinectl で開始されたコンテナで使用される仮想イーサネットリンクを作成するには、次のオプションを指定して、.nspawn ファイルを追加します:

/etc/systemd/nspawn/container-name.nspawn
[Network]
VirtualEthernet=no

これにより、systemd-nspawn@.service-n/--network-veth オプションが上書きされ、新しく開始されたコンテナはホストネットワークモードを使用します。

仮想イーサネットリンクを使用する

コンテナが、-n/--network-veth オプションで起動された場合、systemd-nspawn はホストとコンテナの間に仮想イーサネットリンクを作成します。リンクのホスト側は、ve-container-name という名前のネットワークインターフェイスとして利用可能になります。リンクのコンテナ側は、hosts0 という名前になります。このオプションは、--private-network を意味することに注意してください。

ノート:
  • コンテナ名が長すぎる場合、インターフェイス名は、15文字制限 に収まるように短縮されます(例: ve-long-container-name の代わりに ve-long-conKQGh)。フルネームはインターフェイスの altname プロパティとして設定され(ip-link(8)を参照)、インターフェイスの参照に使用できます。
  • ip link でインターフェイスを調べる場合、インターフェイス名は、ve-container-name@if2host0@if9 のようにサフィックスを付けて表示されます。@ifN は実際にはインターフェイス名の一部ではありません。その代わりに、ip link はこの情報を追加して、仮想イーサネットケーブルが相手側のどの slot に接続しているかを示します
例えば、ve-foo@if2 とし表示されているホスト仮想イーサネットインターフェイスはコンテナ foo に接続され、コンテナ内で ip link を実行しているときに、index 2 で示されている 2 番目のネットワークインタフェースに接続されています。同様に、コンテナ内の host0@if9 という名前のインターフェイスは、ホスト上の 9 番目のネットワークインターフェイス接続されています。

コンテナを起動する際には、ホストとコンテナの両方のインターフェイスにIPアドレスを割り当てなければなりません。ホストとコンテナの両方で systemd-networkd を使用している場合、初期状態で実行されます:

  • ホスト上の /usr/lib/systemd/network/80-container-ve.network ファイルは ve-container-name インターフェイスと一致し、DHCP サーバーを起動します。DHCP サーバーは、IP アドレスをホストインターフェイスとコンテナーに割り当てます。
  • /usr/lib/systemd/network/80-container-host0.network コンテナ内のファイルは host0 インターフェイスと一致し、ホストから IP アドレスを受信する DHCP クライアントを起動します。

systemd-networkd を使用しない場合は、静的IPアドレスを設定するか、ホストインターフェイスで、DHCP サーバを起動し、コンテナで DHCP クライアントを起動できます。詳細については、ネットワーク設定 を参照してください。

コンテナに外部ネットワークへのアクセスを許可するには、インターネット共有#NAT の有効化 の説明に従って NAT を設定します。systemd-networkd を使用する場合、これは、/usr/lib/systemd/network/80-container-ve.network ファイルの IPMasquerade=yes オプションを介して(部分的に)自動的に行われます。ただし、これは次のような iptables ルールのみを発行します。

-t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE

filter テーブルは、インターネット共有#NAT の有効化のように手動で設定する必要があります。ワイルドカードを使用して、ve- で始まるすべてのインターフェイスに一致させることができます:

# iptables -A FORWARD -i ve-+ -o internet0 -j ACCEPT
ノート: systemd-networkd は、libiptc ライブラリを使用して、iptables と対話します。 nftables を使用する場合は、iptables-nft 変換レイヤーをインストールします。systemd issue 13307 も参照してください。
この記事またはセクションの正確性には問題があります。
理由: Investigate if/why the following is necessary. (議論: トーク:Systemd-nspawn#)

また、インターネット共有#NAT の有効化で説明しているように、ルール -A FORWARD -i ve-+ -o internet0 -j ACCEPT が機能しない場合があります。その場合は、-A FORWARD -i ve-+ -j ACCEPT を試してみてください。

ネットワークブリッジを使用する

ホストシステムにネットワークブリッジを構成している場合は、コンテナの仮想イーサネットリンクを作成し、そのホスト側をネットワークブリッジに追加できます。 これは、--network-bridge=bridge-name オプションを使用して実行されます。--network-bridge--network-veth を意味することに注意してください。つまり、仮想イーサネットリンクは自動的に作成されます。 ただし、リンクのホスト側は ve- ではなく vb- プリフィックスを使用するため、DHCP サーバーと IP マスカレードを起動するための systemd-networkd オプションは適用されません。

ブリッジの管理は管理者に任されています。例えば、ブリッジは物理インターフェースと仮想インターフェースを接続したり、複数のコンテナの仮想インターフェースのみを接続したりすることができます。systemd-networkd を使用した設定例については、systemd-networkd#Network bridge with DHCPsystemd-networkd#Network bridge with static IP addresses を参照してください。

また、--network-zone=zone-name オプションは --network-bridge と似ていますが、ネットワークブリッジは systemd-nspawnsystemd-networkd によって自動的に管理されます。vz-zone-name という名前のブリッジインターフェースは、--network-zone=zone-name を設定した最初のコンテナが起動したときに自動的に作成され、--network-zone=zone-name を設定した最後のコンテナが終了したときに自動的に削除されます。したがって、このオプションを使用すると、複数の関連するコンテナを共通の仮想ネットワーク上に簡単に配置することができます。vz-* インターフェースは、/usr/lib/systemd/network/80-container-vz.network ファイルのオプションを使って、ve-* インターフェースと同じように systemd-networkd によって管理されることに注意してください。

「macvlan」または「ipvlan」インターフェースを使用する

仮想イーサネットリンク(ホスト側がブリッジに追加される場合とされない場合があります)を作成する代わりに、既存の物理インターフェイス(つまり、VLAN インターフェイス)上に仮想インターフェイスを作成し、それをコンテナに追加できます。仮想インターフェイスは、基盤となるホストインターフェイスとブリッジされるため、コンテナは外部ネットワークに公開されます。これにより、ホストが接続されているのと同じ LAN から DHCP を介して個別の IP アドレスを取得できます。

systemd-nspawn には2つのオプションがあります:

  • --network-macvlan=interface – 仮想インターフェイスは、基盤となる物理インターフェイスとは異なるMACアドレスを持ち、mv-interface という名前が付けられます。
  • --network-ipvlan=interface – 仮想インターフェイスは、基礎となる物理インターフェイスと同じMACアドレスを持ち、iv-interface と名付けられます。

どちらのオプションも --private-network を意味します。

既存のインターフェイスを使用する

ホストシステムに複数の物理ネットワークインターフェイスがある場合は、 --network-interface=interface を使用してコンテナにインターフェイスを割り当てることができます(コンテナが起動している間はホストからは利用できないようにします)。--network-interface--private-network を意味することに注意してください。

ノート: systemd-nspawn コンテナにワイヤレスネットワークインターフェイスを渡すことは現在サポートされていません。[2]

ポートマッピング

プライベートネットワークが有効になっている場合、-p/--port オプションを使用するか、.nspawn ファイルの Port 設定を使用して、ホスト上の個々のポートをコンテナ上のポートにマップできます。これは nat テーブルに iptables ルールを発行することで行いますが、フィルタテーブルの FORWARD チェーンは #Use a virtual Ethernet link で示されているように、手動で設定する必要があります。

例えば、ホスト上のTCPポート8000をコンテナ内のTCPポート80にマッピングするには、次のように入力します:

/etc/systemd/nspawn/container-name.nspawn
[Network]
Port=tcp:8000:80
ノート:
  • systemd-nspawn は、ポートをマッピングする際に loopback インターフェイスを明示的に除外します。したがって、上記の例では、localhost:8000 はホストに接続し、コンテナには接続しません。他のインターフェイスへの接続のみがポートマッピングの対象となります。詳細は、[3] を参照してください。
  • ポートマッピングは IPv4 接続に対してのみ機能します。 [4]

ドメイン名前解決

コンテナ内の ドメイン名前解決systemd-nspawn--resolv-conf オプションか、.nspawn ファイルの ResolvConf= オプションで設定できます。systemd-nspawn(1) § 統合オプション に多くの値が記述されています。

デフォルト値は auto で以下の事を意味します:

  • --private-network が有効になっている場合、/etc/resolv.conf はコンテナ内のまま残ります。
  • あるいは、ホストで systemd-resolved が実行されている場合、そのスタブ resolv.conf ファイルがコンテナにコピーまたはバインドマウントされます。
  • それ以外の場合、/etc/resolv.conf ファイルはホストからコンテナにコピーされるか、バインドマウントされます。

最後の2つのケースでは、コンテナルートが書き込み可能な場合はファイルがコピーされ、読み取り専用の場合はバインドマウントされます。

ヒントとテクニック

非特権コンテナ

systemd-nspawn は非特権コンテナをサポートしますが、コンテナは root として起動する必要があります。

ノート: この機能には user_namespaces(7) が必要です。詳細については、Linux Containers#Enable support to run unprivileged containers (optional) を参照してください。

これを行う最も簡単な方法は、-U オプションを使用して systemd-nspawn が自動的に未使用の UIDs/GIDs の範囲を選択させることです:

# systemd-nspawn -bUD ~/MyContainer

カーネルがユーザー名前空間をサポートしている場合、-U オプションは --private-users=pick --private-users-chown と同等です。これはコンテナの開始時にコンテナ内のファイルとディレクトリが選択された範囲のプライベート UIDs/GIDs に変更される事を意味します。詳細は、 systemd-nspawn(1) § User Namespacing Options を参照してください。

ノート: コンテナの UID/GID の範囲を手動で指定することもできますが、これが役立つことはほとんどありません。

プライベート UID/GID の範囲を持つコンテナを起動したら、パーミッションエラーを避けるために、そのコンテナを使い続ける必要があります。あるいは、--private-users-chown (または -U) のファイルシステムへの影響を元に戻すには、0で始まるIDの範囲を指定します:

# systemd-nspawn -D ~/MyContainer --private-users=0 --private-users-chown

X 環境

新しいコンテナで X アプリケーションを動かす必要がある場合は Xhost を見て下さい。

外部の X サーバーにコンテナのセッションを接続するには DISPLAY 環境変数を設定する必要があります。

X は必要なファイルを /tmp ディレクトリに保存します。コンテナから全てを表示させるには、/tmp ディレクトリのファイルにアクセスできるようにしなくてはなりません。コンテナを起動するときに --bind=/tmp/.X11-unix:/tmp/.X11-unix オプションを追加してください。

ノート: systemd バージョン 235 には バグ が存在し、/tmp/.X11-unix がファイルシステムから消失することがあります。問題を回避するには /tmp/.X11-unix を読み取り専用でバインドしてください: --bind-ro=/tmp/.X11-unix/X0/run/user/1000 もバインドしている場合は明示的に /run/user/1000/bus を読み取り専用でバインドすることで dbus ソケットが削除されないように保護することができます。

xhost の回避

xhost は、Xサーバに対してかなり粗いアクセス権しか与えません。​$XAUTHORITY ファイルを使用すると、より詳細なアクセス制御が可能になります。​残念ながら、コンテナ内の$XAUTHORITY ファイルにアクセスできるようにしただけではうまくいきません。$XAUTHORITY ファイルはホスト固有のものですが、コンテナは別のホストです。​stackoverflowを参考にした以下のトリックを使えば、Xサーバがコンテナ内で実行されているXアプリケーションから、$XAUTHORITY ファイルを受け入れるようにすることができます:

$ XAUTH=/tmp/container_xauth
$ xauth nextract - "$DISPLAY" | sed -e 's/^..../ffff/' | xauth -f "$XAUTH" nmerge -
# systemd-nspawn -D myContainer --bind=/tmp/.X11-unix --bind="$XAUTH" -E DISPLAY="$DISPLAY" -E XAUTHORITY="$XAUTH" --as-pid2 /usr/bin/xeyes

上記の2行目では、接続ファミリーを ""FamilyWild""(値65535) に設定しているため、エントリはすべての表示に一致します。​詳細はXsecurity(7) を参照。

Firefox を起動する

PID 1 として実行するには

 # systemd-nspawn --setenv=DISPLAY=:0 \
              --setenv=XAUTHORITY=~/.Xauthority \
              --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
              --bind=/tmp/.X11-unix \
              -D ~/containers/firefox \
              firefox

あるいは、コンテナを起動して、例えば、systemd-networkd に仮想ネットワークインターフェイスを設定することもできます。

# systemd-nspawn --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
              --bind=/tmp/.X11-unix \
              -D ~/containers/firefox \
              --network-veth -b

コンテナが起動したら、次のようにXorgバイナリを実行します:

# systemd-run -M firefox --setenv=DISPLAY=:0 firefox

ホストのファイルシステムにアクセス

例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:

# systemd-nspawn --bind=/var/cache/pacman/pkg

詳しくは systemd-nspawn(1)--bind--bind-ro を参照してください。

ファイルを使ってコンテナごとにバインドを設定することもできます:

/etc/systemd/nspawn/my-container.nspawn
[Files]
Bind=/var/cache/pacman/pkg

#コンテナごとに設定を指定するを参照。

systemd を使っていない環境で動作させる

Init#systemd-nspawn を見て下さい。

Btrfs のサブボリュームをコンテナのルートとして使う

Btrfs サブボリュームをコンテナのルートのテンプレートとして使うには、--template フラグを使用します。サブボリュームのスナップショットを使ってコンテナのルートディレクトリが生成されます。

ノート: 指定されたテンプレートのパスがサブボリュームのルートでなかった場合、ツリー全体がコピーされます。その場合、非常に時間がかかります。

例えば、/.snapshots/403/snapshot に存在するスナップショットを使うには:

# systemd-nspawn --template=/.snapshots/403/snapshots -b -D my-container

my-container は作成するコンテナのディレクトリの名前に置き換えてください。電源を切っても、新しく作成されたサブボリュームは消えません。

コンテナの一時的な Btrfs スナップショットを使う

--ephemeral-x フラグを使ってコンテナの一時的な btrfs スナップショットを作成してコンテナのルートとして利用できます。コンテナの実行中に変更が加えられても保存されません。例:

# systemd-nspawn -D my-container -xb

my-container はシステムに存在する既存のコンテナのディレクトリに置き換えてください。例えば / が btrfs のサブボリュームだった場合、以下のコマンドで実行中のホスト環境の一時的なコンテナを作成することができます:

# systemd-nspawn -D / -xb 

コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。

system-nspawn で docker を実行

Docker コンテナを実行するには、 /sys/fs/cgrouprw 権限が必要です。このコンテナは、 cgroup 名前空間のため、デフォルトで「'システムn起動' 」によって読み取り専用でマウントされます。ただし,ホストシステムから bind-mounting /sys/fs/cgroup を実行して,必要な機能と権限を有効にすることで, システムn起動 コンテナ内で Docker を実行することは可能です。

ノート: 次の手順は、基本的に cgroup / user 名前空間をコンテナと共有し、カーネルキーリングのアクセス許可を付与して、それを特権付きコンテナにすることです。これにより、攻撃対象が増え、セキュリティレベルが低下する可能性があります。手順に従う前に、必ず実際のメリットを理解してください。

まず、cgroup 名前空間は systemctl edit systemd-nspawn@myContainer によって無効にされている必要があります。

systemctl edit systemd-nspawn@myContainer
[Service]
Environment=SYSTEMD_NSPAWN_USE_CGNS=0

次に、/etc/systemd/nspawn/myContainer.nspawn (存在しない場合は作成) を編集し、次の設定を追加します。

/etc/systemd/nspawn/myContainer.nspawn
[Exec]
Capability=all
SystemCallFilter=add_key keyctl
PrivateUsers=no

[Files]
Bind=/sys/fs/cgroup

これにより、コンテナにすべての機能が付与され、ユーザーの名前空間が無効になり、2つのシステムコール add_keykeyctl (カーネルキーリングに関連し、Dockerで必要) がホワイトリストに追加され、ホストからコンテナへのバインドマウント /sys/fs/cgroup が行われます。これらのファイルを編集したら、有効にするためにコンテナの電源をオフにして再起動する必要があります。この変更の前にコンテナでユーザネームスペースが有効になっていた場合 (これは、systemd-nspawn@.service ユニットが使用されている場合のデフォルトです。) アクセス権エラーを回避するために、ユーザネームスペースによるアクセス権を元に戻す必要があります。詳細は、 systemd-nspawn#非特権コンテナ を参照してください。

ノート:
  • systemd-nspawn 内で Docker を起動する前に、ホストに overlay モジュールをロードして、 overlay2 ストレージドライバ (Docker のデフォルトストレージドライバ) を正しく使用する必要がある場合があります。ドライバをロードしないと、 Docker は非効率なドライバ vfs を選択し、 Docker コンテナのすべてのレイヤのすべてをコピーします。モジュールを自動的にロードする方法については、 Automatic module loading with systemd を参照してください。
  • 2020年11月時点で, cgroups v2は systemd-nspawn 内の Docker を破壊する可能性があります。この方法で Docker を使用する場合は、カーネルパラメータ systemd.unified_cgroup_hierarchy=1 を設定しないでください。

root 権限なしで machinectl を使用する

machined が Polkit を有効にしている場合、polkit ルールを作成して、root ユーザ にならずに特定のアクションを実行できるようにします。パーミッションの違いは、/usr/share/polkit-1/actions/org.freedesktop.machine1.policy で説明されており、すべて、org.freedesktop.machine1. の下にあります。

"foo" という名前のユーザが root権限なしですべてのアクションを実行できるようにするには、ポリシーを追加します:

/etc/polkit-1/rules.d/machined.rules
polkit.addRule(
  function(action, subject) {
    if (action.id.startsWith("org.freedesktop.machine1.") && subject.user == "foo") {
      return polkit.Result.YES;
    }
  }
);

さらに、ユーザーは、systemd-nspawn@ コンテナーを開始および停止できるようにユニットを管理するためのアクセス許可を必要とします。これを許可するには、このポリシーを追加します:

/etc/polkit-1/rules.d/machined.rules
polkit.addRule(
  function(action, subject) {
    if ((action.id.startsWith("org.freedesktop.machine1.") || (action.id == "org.freedesktop.systemd1.manage-units" && action.lookup("unit").startsWith("systemd-nspawn@"))) && subject.user == "foo") {
      return polkit.Result.YES;
    }
  }
);

トラブルシューティング

root ログインが失敗する

(machinectl login <name> を使用して) ログインしようとしたときに以下のエラーが表示される場合:

arch-nspawn login: root
Login incorrect

そして journalctl が以下のように表示する場合:

pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !

コンテナのファイルシステム上にある /etc/securetty のターミナル名のリストに pts/0 を追加してください。詳しくは [5] を参照。また、コンテナの /etc/securetty を削除して root で全ての tty にログインできるようにするという方法もあります。[6] を見てください。

execv(...) failed: Permission denied

systemd-nspawn -bD /path/to/container によってコンテナを起動 (またはコンテナ内で何かを実行) しようとすると、以下のようなエラーが発生します:

execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Permission denied

問題のファイル (例えば /lib/systemd/systemd) のパーミッションが正しくても、コンテナが保存されているファイルシステムを非rootユーザーとしてマウントした結果である可能性があります。例えば、fstabnoauto,user,... というオプションを指定して手動でディスクをマウントした場合、systemd-nspawn は rootが所有するファイルであっても実行は許可しません。

TERM の端末タイプが間違っている (色が壊れている)

machinectl login でコンテナにログインすると、コンテナ内の端末の色とキーストロークが壊れることがあります。これは、TERM 環境変数の端末タイプが正しくないことが原因である可能性があります。環境変数はホストのシェルから継承されませんが、明示的に設定されていない限り、systemd (vt220) で固定されたデフォルトに戻ります。設定するには、コンテナ内の container-getty@.service サービス用のオーバーレイを作成して、machinectl login の login getty を起動し、ログインしているホスト端末と一致する値を TERM に設定してください。

/etc/systemd/system/container-getty@.service.d/term.conf
[Service]
Environment=TERM=xterm-256color

もしくは、machinectl shell を使用してください。端末から TERM 環境変数を適切に継承します。

コンテナ内へのNFS共有のマウント

現時点(2019年6月)では利用できません。

参照