「Systemd-nspawn」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) |
Kusanaginoturugi (トーク | 投稿記録) (→ヒントとテクニック: 英語版より節を追加(5.7, 5.8)) |
||
444行目: | 444行目: | ||
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。 |
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。 |
||
+ | |||
+ | === Use temporary Btrfs snapshot of container === |
||
+ | |||
+ | One can use the {{ic|--ephemeral}} or {{ic|-x}} flag to create a temporary btrfs snapshot of the container and use it as the container root. Any changes made while booted in the container will be lost. For example: |
||
+ | |||
+ | # systemd-nspawn -D ''my-container'' -xb |
||
+ | |||
+ | where ''my-container'' is the directory of an '''existing''' container or system. For example, if {{ic|/}} is a btrfs subvolume one could create an ephemeral container of the currently running host system by doing: |
||
+ | |||
+ | # systemd-nspawn -D / -xb |
||
+ | |||
+ | After powering off the container, the btrfs subvolume that was created is immediately removed. |
||
+ | |||
+ | === Run docker in systemd-nspawn === |
||
+ | |||
+ | [[Docker]] requires {{ic|rw}} permission of {{ic|/sys/fs/cgroup}} to run its containers, which is mounted read-only by ''systemd-nspawn'' by default due to cgroup namespace. However, it is possible to run Docker in a ''systemd-nspawn'' container by bind-mounting {{ic|/sys/fs/cgroup}} from the host system and enabling necessary capabilities and permissions. |
||
+ | |||
+ | {{Note|The following steps are essentially sharing the cgroup / user namespace to the container, giving kernel keyring permissions and making it a privileged container, which is likely to increase the attack surface and decrease security level. You should always evaluate the actual benefits by doing so before following the steps.}} |
||
+ | |||
+ | First, cgroup namespace should be disabled by {{ic|systemctl edit systemd-nspawn@myContainer}} |
||
+ | |||
+ | {{hc|systemctl edit systemd-nspawn@myContainer|<nowiki> |
||
+ | [Service] |
||
+ | Environment=SYSTEMD_NSPAWN_USE_CGNS=0 |
||
+ | </nowiki>}} |
||
+ | |||
+ | Then, edit {{ic|/etc/systemd/nspawn/myContainer.nspawn}} (create if absent) and add the following configurations. |
||
+ | |||
+ | {{hc|/etc/systemd/nspawn/myContainer.nspawn|<nowiki> |
||
+ | [Exec] |
||
+ | Capability=all |
||
+ | SystemCallFilter=add_key keyctl |
||
+ | PrivateUsers=no |
||
+ | |||
+ | [Files] |
||
+ | Bind=/sys/fs/cgroup |
||
+ | </nowiki>}} |
||
+ | |||
+ | This grants all capabilities to the container, disables user namespacing, whitelists two system calls {{ic|add_key}} and {{ic|keyctl}} (related to kernel keyring and required by Docker), and bind-mounts {{ic|/sys/fs/cgroup}} from host to the container. After editing these files, you need to poweroff and restart your container for them to take effect. If your container had user namespaces enabled before this change (which is the default if the {{ic|systemd-nspawn@.service}} unit is used), you will also need to undo permission changes caused by user namespacing to avoid permission errors. See [[#Unprivileged containers]] for details. |
||
+ | |||
+ | {{Note| |
||
+ | * You might need to load the {{ic|overlay}} module on the host before starting Docker inside the systemd-nspawn to use the {{ic|overlay2}} storage driver (default storage driver of Docker) properly. Failure to load the driver will cause Docker to choose the inefficient driver {{ic|vfs}} which copies everything for every layer of Docker containers. Consult [[Kernel modules#Automatic module loading with systemd]] on how to load the module automatically. |
||
+ | * As of November 2020, cgroups v2 seems to break Docker inside ''systemd-nspawn''. If you want to use Docker in this way, do not set the kernel parameter {{ic|1=systemd.unified_cgroup_hierarchy=1}}. |
||
+ | }} |
||
+ | |||
+ | === Using machinectl without root permissions === |
||
+ | |||
+ | machined is [[Polkit]] enabled, this allows the creation of polkit rules to allow certain actions to be performed without becoming the root user. The different permissions are described in {{ic|/usr/share/polkit-1/actions/org.freedesktop.machine1.policy}} and all live underneath {{ic|org.freedesktop.machine1.}}. |
||
+ | |||
+ | To allow a user named "foo" to perform all actions without root permissions, add a policy: |
||
+ | |||
+ | {{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>}} |
||
+ | |||
+ | Additionally, the user will require permissions to manage the {{ic|systemd-nspawn@}} units to be able to start and stop nspawn containers, add this policy to allow this: |
||
+ | |||
+ | {{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>}} |
||
== トラブルシューティング == |
== トラブルシューティング == |
2021年1月24日 (日) 15:01時点における版
systemd-nspawn は chroot コマンドに似ていますが、chroot を強化したものです。
systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム階層だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため chroot よりも強力です。
systemd-nspawn は /sys
, /proc/sys
, /sys/fs/selinux
などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードが作成はできません。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールのロードもできません。
仕組みとしては Lxc-systemd や Libvirt-lxc と異なり、とてもシンプルなツールで設定を行います。
目次
- 1 インストール
- 2 サンプル
- 3 管理
- 4 設定
- 5 ヒントとテクニック
- 6 トラブルシューティング
- 7 参照
インストール
systemd-nspawn は systemd に含まれています。
サンプル
コンテナに最小限の Arch Linux を作成して起動
まず arch-install-scripts パッケージをインストールしてください。
次に、コンテナを置くためのディレクトリを作成してください。この例では、~/MyContainer
を使用します。
そして、pacstrap を使って最小限の arch システムをコンテナにインストールします。最低限でも base パッケージはインストールする必要があります。
# pacstrap -c ~/MyContainer base [additional pkgs/groups]
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。
# systemd-nspawn -D ~/MyContainer # passwd # logout
最後に、コンテナを起動します。
# systemd-nspawn -b -D ~/MyContainer
-b
オプションはシェルを実行する代わりにコンテナを起動します (つまり PID=1 として systemd
を実行)。-D
にはコンテナのルートディレクトリにするディレクトリを指定します。
コンテナが開始したら、設定したパスワードを使って "root" でログインしてください。
コンテナの電源を切りたいときはコンテナの中から poweroff
を実行することで出来ます。ホストからは、machinectl ツールでコンテナを制御できます。
Debian や Ubuntu 環境の作成
debootstrap と debian-archive-keyring か ubuntu-keyring のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。
後は簡単に 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/
のサブディレクトリはコンテナ名に対応しています。
systemd-nspawn オプションのデフォルト値
machinectl や systemd-nspawn@.service
経由で起動されたコンテナは systemd-nspawn コマンドで起動されたコンテナとはオプションの既定値が異なることを理解することが重要です。サービスが使用する追加オプションは以下の通りです。
-b
/--boot
– マネージドコンテナは自動的に init プログラムを検索し、PID 1 として起動します。--network-veth
つまり--private-network
– マネージドコンテナは仮想ネットワークインターフェースを取得し、ホストネットワークから切り離されます。詳細は、#ネットワーキング を参照してください。-U
– カーネルがサポートしている場合、マネージドコンテナはデフォルトで user_namespaces(7) 機能を使用します。詳細は、#非特権コンテナ を参照してください。--link-journal=try-guest
この動作は、コンテナごとの設定ファイルでオーバーライドすることができます。 詳細は、#設定 を参照してください。
machinectl
コンテナはコマンドで管理できます。例えば、コンテナを起動するには、次のようにします。
$ machinectl start container-name
同様に、poweroff
, reboot
, status
, show
などのサブコマンドがあります。詳細な説明については、machinectl(1) § Machine Commands を参照してください。
その他の一般的なコマンドは以下の通りです:
machinectl list
– show a list of currently running containersmachinectl 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) を参照してください。
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時間合計に対して、コンテナが最大で取得する時間を制限することで、同様の結果が得られます。
ネットワーキング
systemd-nspawn コンテナは、ホストネットワーク または プライベートネットワークのいずれかを使用できます。
- ホストネットワークモードでは、コンテナはホストネットワークへのフルアクセスが可能です。これは、コンテナがホスト上のすべてのネットワークサービスにアクセスできるようになり、コンテナからのパケットがホストのパケットとして外部ネットワークに表示される事を意味します(つまり、同じIPアドレスを共有します)。
- プライベートネットワークモードでは、コンテナはホストのネットワークから切断されています。これにより、ループバックデバイスとコンテナに明示的に割り当てられたものを除いて、すべてのネットワークインターフェイスがコンテナを使用できなくなります。コンテナのネットワークインターフェイスを設定するには、いくつかの方法があります。
- 既存のインターフェイスをコンテナに割り当てることができます(たとえば、複数のイーサネットデバイスがある場合)。
- 既存のインターフェース(つまり、VLANインターフェース)に関連付けられた仮想ネットワークインターフェースを作成して、コンテナーに割り当てることができます。
- ホストとコンテナの間に仮想イーサネットリンクを作成できます。
- 後者の場合、コンテナのネットワークは、(外部ネットワークや他のコンテナから) 完全に分離されており、ホストとコンテナ間のネットワークを構成するのは管理者の責任です。これには通常、複数の(物理または仮想)インターフェイスを接続するための ネットワークブリッジ の作成、または複数のインターフェイス間の ネットワークアドレス変換 の設定が含まれます。
ホストネットワーキングモードは、コンテナに割り当てられたインターフェースを構成するネットワーキングソフトウェアを実行しない アプリケーションコンテナ に適しています。ホストネットワーキングは、シェルから systemd-nspawn を実行するときのデフォルトのモードです。
一方、プライベート・ネットワーキング・モードは、ホスト・システムから隔離されている必要がある システムコンテナ に適しています。仮想イーサネットリンクの作成は、複雑な仮想ネットワークの作成を可能にする非常に柔軟なツールです。これは machinectl や systemd-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
を意味することに注意してください。
コンテナを起動する際には、ホストとコンテナの両方のインターフェイスに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
Additionally, the rule -A FORWARD -i ve-+ -o internet0 -j ACCEPT
may not work as described in Internet sharing#Enable NAT. If that is the case, try -A FORWARD -i ve-+ -j ACCEPT
.
Use a network bridge
ホストシステムにネットワークブリッジを構成している場合は、コンテナの仮想イーサネットリンクを作成し、そのホスト側をネットワークブリッジに追加できます。 これは、--network-bridge=bridge-name
オプションを使用して実行されます。--network-bridge
は --network-veth
を意味することに注意してください。つまり、仮想イーサネットリンクは自動的に作成されます。 ただし、リンクのホスト側は ve-
ではなく vb-
プリフィックスを使用するため、DHCP サーバーと IP マスカレードを起動するための systemd-networkd オプションは適用されません。
ブリッジの管理は管理者に任されています。例えば、ブリッジは物理インターフェースと仮想インターフェースを接続したり、複数のコンテナの仮想インターフェースのみを接続したりすることができます。systemd-networkd を使用した設定例については、systemd-networkd#Network bridge with DHCP と systemd-networkd#Network bridge with static IP addresses を参照してください。
There is also a --network-zone=zone-name
option which is similar to --network-bridge
but the network bridge is managed automatically by systemd-nspawn and systemd-networkd. The bridge interface named vz-zone-name
is automatically created when the first container configured with --network-zone=zone-name
is started, and is automatically removed when the last container configured with --network-zone=zone-name
exits. Hence, this option makes it easy to place multiple related containers on a common virtual network. Note that vz-*
interfaces are managed by systemd-networkd same way as ve-*
interfaces using the options from the /usr/lib/systemd/network/80-container-vz.network
file.
「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
を意味することに注意してください。
ポートマッピング
プライベートネットワークが有効になっている場合、-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 の --resolv-conf
オプションか、.nspawn ファイルの ResolvConf=
オプションで設定できます。systemd-nspawn(1) § 統合オプション に多くの値が記述されています。
デフォルト値は auto
で以下の事を意味します:
--private-network
が有効になっている場合、/etc/resolv.conf
はコンテナ内のまま残ります。- あるいは、ホストで systemd-resolved が実行されている場合、そのスタブ
resolv.conf
ファイルがコンテナにコピーまたはバインドマウントされます。 - それ以外の場合、
/etc/resolv.conf
ファイルはホストからコンテナにコピーされるか、バインドマウントされます。
最後の2つのケースでは、コンテナルートが書き込み可能な場合はファイルがコピーされ、読み取り専用の場合はバインドマウントされます。
ヒントとテクニック
非特権コンテナ
systemd-nspawn は非特権コンテナをサポートしますが、コンテナは root として起動する必要があります。
これを行う最も簡単な方法は、-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 の範囲を持つコンテナを起動したら、パーミッションエラーを避けるために、そのコンテナを使い続ける必要があります。あるいは、--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
オプションを追加してください。
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-networkd を使用して DNS に systemd-resolved
を使用する、インターネットに接続できる最も簡単な設定:
# systemctl enable --now systemd-networkd systemd-resolved # ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf # let systemd-resolved manage /etc/resolv.conf
上記の設定を使うには -n
スイッチを使って systemd-nspawn
を実行して、ホストに仮想イーサネットリンクを作成する必要があります。
systemd-resolved
を使わないでコンテナの /etc/resolv.conf
を手動で編集して DNS サーバーの IP アドレスを追加することも可能です。
基本的な systemd-networkd のホストとコンテナの .network
ファイルは https://github.com/systemd/systemd/tree/master/network にあります。
もっと複雑なネットワークを設定する方法は、systemd-networkd#コンテナでの使用方法を見て下さい。
nsswitch.conf
ホストからコンテナへの接続を楽にするために、コンテナの名前のローカル DNS 解決を有効にすることができます。/etc/nsswitch.conf
の hosts:
セクションに mymachines
を追加してください:
hosts: files mymachines dns myhostname
こうすると、ホスト上でホストネーム foo
の DNS ルックアップで /etc/hosts
が参照され、それからローカルコンテナの名前、上流の DNS などが参照されます。
ホストのネットワークを使用
machinectl start MyContainer
で起動したコンテナによって使用されるプライベートネットワークを無効化するには systemctl edit systemd-nspawn@.service
を実行して systemd-nspawn@.service
サービスファイルの設定を編集してください。--network-veth
パラメータを削除するように ExecStart=
オプションを設定します:
/etc/systemd/system/systemd-nspawn@.service.d/override.conf
[Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I
次に起動したコンテナはホストのネットワークを使用するようになります。
仮想イーサネットインターフェイス
コンテナを systemd-nspawn ... -n
で起動した場合、systemd は自動的にホストとコンテナに仮想イーサネットインターフェイスを作成して、仮想イーサネットケーブルで接続します。
コンテナの名前が foo
ならば、仮想イーサネットインターフェイスのホストにおける名前は ve-foo
になり、コンテナではどんな場合でも名前は host0
です。
ip link
でインターフェイスを確認すると、インターフェイスの名前には ve-foo@if2
や host0@if9
のように接尾辞が付きます。@ifN
は実際はインターフェイスの名前には含まれていません。仮想イーサネットケーブルが他の端末に接続されていることを示すために ip link
によって情報が加えられています。
例えば、ホストの仮想イーサネットインターフェイス ve-foo@if2
がコンテナ foo
に接続、コンテナの中の2番目のネットワークインターフェイスに接続する場合、コンテナの中から ip link
を実行するとインデックス 2 が付きます。同じように、コンテナの host0@if9
という名前のインターフェイスはホストの9番目のインターフェイスに接続します。
ネットワークブリッジを使用
ローカルネットワークの物理マシンのようにコンテナに IP アドレスを割り当てるためにホスト環境にネットワークブリッジを設定している場合 (詳しくは systemd-networkd#2つの別々な IP で DHCP を使うや systemd-networkd#固定 IP ネットワークを参照)、--network-bridge=br0
オプションを使って systemd-nspawn から利用することができます。
systemd を使っていない環境で動作させる
Init#systemd-nspawn を見て下さい。
コンテナごとに設定を指定する
全体設定を上書きすることなく各コンテナの設定を指定したい場合 (例: どれかひとつのコンテナにディレクトリをバインドする場合)、.nspawn
ファイルを使うことで設定できます [5]。systemd.nspawn(5) を見てください [6]。
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 サブボリュームはすぐに削除されます。
Use temporary Btrfs snapshot of container
One can use the --ephemeral
or -x
flag to create a temporary btrfs snapshot of the container and use it as the container root. Any changes made while booted in the container will be lost. For example:
# systemd-nspawn -D my-container -xb
where my-container is the directory of an existing container or system. For example, if /
is a btrfs subvolume one could create an ephemeral container of the currently running host system by doing:
# systemd-nspawn -D / -xb
After powering off the container, the btrfs subvolume that was created is immediately removed.
Run docker in systemd-nspawn
Docker requires rw
permission of /sys/fs/cgroup
to run its containers, which is mounted read-only by systemd-nspawn by default due to cgroup namespace. However, it is possible to run Docker in a systemd-nspawn container by bind-mounting /sys/fs/cgroup
from the host system and enabling necessary capabilities and permissions.
First, cgroup namespace should be disabled by systemctl edit systemd-nspawn@myContainer
systemctl edit systemd-nspawn@myContainer
[Service] Environment=SYSTEMD_NSPAWN_USE_CGNS=0
Then, edit /etc/systemd/nspawn/myContainer.nspawn
(create if absent) and add the following configurations.
/etc/systemd/nspawn/myContainer.nspawn
[Exec] Capability=all SystemCallFilter=add_key keyctl PrivateUsers=no [Files] Bind=/sys/fs/cgroup
This grants all capabilities to the container, disables user namespacing, whitelists two system calls add_key
and keyctl
(related to kernel keyring and required by Docker), and bind-mounts /sys/fs/cgroup
from host to the container. After editing these files, you need to poweroff and restart your container for them to take effect. If your container had user namespaces enabled before this change (which is the default if the systemd-nspawn@.service
unit is used), you will also need to undo permission changes caused by user namespacing to avoid permission errors. See #Unprivileged containers for details.
Using machinectl without root permissions
machined is Polkit enabled, this allows the creation of polkit rules to allow certain actions to be performed without becoming the root user. The different permissions are described in /usr/share/polkit-1/actions/org.freedesktop.machine1.policy
and all live underneath org.freedesktop.machine1.
.
To allow a user named "foo" to perform all actions without root permissions, add a policy:
/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; } } );
Additionally, the user will require permissions to manage the systemd-nspawn@
units to be able to start and stop nspawn containers, add this policy to allow this:
/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
を追加してください。詳しくは [7] を参照。また、コンテナの /etc/securetty
を削除して root で全ての tty にログインできるようにするという方法もあります。[8] を見てください。
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ユーザーとしてマウントした結果である可能性があります。例えば、fstab に noauto,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月)では利用できません。