「Systemd-nspawn」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎トラブルシューティング: 英語版より節を追加)
(→‎machinectl: 校正)
 
(2人の利用者による、間の150版が非表示)
10行目: 10行目:
 
{{Related|systemd-networkd}}
 
{{Related|systemd-networkd}}
 
{{Related|Docker}}
 
{{Related|Docker}}
{{Related|Lxc-systemd}}
 
 
{{Related articles end}}
 
{{Related articles end}}
   
 
''systemd-nspawn'' は [[chroot]] コマンドに似ていますが、''chroot を強化したもの''です。
 
''systemd-nspawn'' は [[chroot]] コマンドに似ていますが、''chroot を強化したもの''です。
   
''systemd-nspawn'' を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため [[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]]-lxc と異な、とてシンプルなツールで設定を行います。
+
''systemd-nspawn'' は [[LXC]] や [[Libvirt]] りも設定が簡単なツールです。
   
 
== インストール ==
 
== インストール ==
   
''systemd-nspawn'' は {{Pkg|systemd}} に含まれています。
+
''systemd-nspawn'' は systemd の一部であり、{{Pkg|systemd}} に含まれています。
   
 
== サンプル ==
 
== サンプル ==
   
=== コンテナに最小限の Arch Linux ディストリビューションを作成して起動 ===
+
=== コンテナに最小限の Arch Linux を作成して起動 ===
   
 
まず {{Pkg|arch-install-scripts}} パッケージを[[pacman|インストール]]してください。
 
まず {{Pkg|arch-install-scripts}} パッケージを[[pacman|インストール]]してください。
   
そして、お好きな場所にディレクトリを作成してください。例えば: {{ic|$ mkdir ~/''MyContainer''}}。
+
、コンテナを置くためのディレクトリを作成してください。このでは、{{ic|~/''MyContainer''}} を使用します
   
pacstrap を使って最小限の arch システムをコンテナにインストールします。最低限でも {{Pkg|base}} グルはインストールする必要があります。
+
そして、''pacstrap'' を使って最小限の arch システムをコンテナにインストールします。最低限でも {{Pkg|base}} パッケはインストールする必要があります。
   
# pacstrap -c ~/MyContainer base [additional pkgs/groups]
+
# pacstrap -K -c ~/MyContainer base [additional pkgs/groups]
   
{{Tip|{{Pkg|base}} パッケージは、{{Pkg|linux}} パッケージに依存せず、コンテナにも対応しています。}}
+
{{Tip|{{Pkg|base}} パッケージは、{{Pkg|linux}} カーネルパッケージに依存せず、コンテナにも対応しています。}}
  +
{{Note|''pacstrap'' が利用できない異なるオペレーティングシステムから作成する場合、[[既存の Linux からインストール#方法 A: ブートストラップイメージを使う (推奨)|bootstrap tarball]] をコンテナイメージとして使用することができます。pacman キーリングはコンテナ内で初期化する必要があります。詳細は [[既存の Linux からインストール#pacman キーリングの初期化]] を参照してください。}}
   
 
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。
 
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。
43行目: 43行目:
 
# passwd
 
# passwd
 
# logout
 
# logout
  +
  +
{{Tip|Setting root password is optional. You can get a root shell in a booted container directly without having to log in by running {{ic|machinectl shell root@MyContainer}}. See [[#machinectl]].}}
   
 
最後に、コンテナを起動します。
 
最後に、コンテナを起動します。
48行目: 50行目:
 
# systemd-nspawn -b -D ~/MyContainer
 
# systemd-nspawn -b -D ~/MyContainer
   
({{ic|-b}} はシェルを実行する代わりにコンテナを起動します (つまり PID=1 として {{ic|systemd}} を実行)。{{ic|-D}} にはコンテナのルートディレクトリにするディレクトリを指定します):
+
{{ic|-b}} オプションはシェルを実行する代わりにコンテナを起動します (つまり PID=1 として {{ic|systemd}} を実行)。{{ic|-D}} にはコンテナのルートディレクトリにするディレクトリを指定します
   
 
コンテナが開始したら、設定したパスワードを使って "root" でログインしてください。
 
コンテナが開始したら、設定したパスワードを使って "root" でログインしてください。
62行目: 64行目:
 
{{Pkg|debootstrap}} と {{Pkg|debian-archive-keyring}} か {{Pkg|ubuntu-keyring}} のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。
 
{{Pkg|debootstrap}} と {{Pkg|debian-archive-keyring}} か {{Pkg|ubuntu-keyring}} のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。
   
{{Note|systemd-nspawn を使用するにはコンテナ内の OS で systemd PID 1 として動作ている必要があります。Ubuntu 15.04 以前は、そままで動作せず、upstart から systemd への移行が必須です。また、コンテナ環境に {{ic|systemd-container}} パッケージをインストールしてください。}}
+
{{Note|systemd-nspawn はコンテナ内のオペレーティングシステムが systemd init を使用し (PID 1 として動作する)、systemd-nspawn がコンテナにインストールされている必要があります。要件は、コンテナ環境に systemd-container パッケージをインストールすることで満たされます。systemd-container パッケージは dbus に依存しますが、dbus または dbus-broker パッケージがコンテナシステムにインストールされていることを確認してください。}}
   
 
後は簡単に Debian や Ubuntu 環境をセットアップできます:
 
後は簡単に Debian や Ubuntu 環境をセットアップできます:
   
 
# cd /var/lib/machines
 
# cd /var/lib/machines
# debootstrap <codename> myContainer <repository-url>
+
# debootstrap --include=dbus-broker,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>}} などとなります。
+
Debian の場合、コードネームとして指定するのは "stable" や "testing" などのローリングの名前か "stretch" や "sid" などのリリース名になります。Ubuntu の場合、"xenial" や "zesty" などのコードネームを使ってください。コードネームの完全なリストは {{ic|/usr/share/debootstrap/scripts}} にあります。Debian イメージの場合は "repository-url" には https://deb.debian.org/debian/ などを指定します。Ubuntu のイメージの場合は "repository-url" は http://archive.ubuntu.com/ubuntu/ などとなります。
   
Arch と違って、Debian や Ubuntu は最初のログイン時にパスワードが要ることになってい。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:
+
Arch と同様に、Debian や Ubuntu はパスワードなしでログインすることはできせん。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:
   
  +
# cd /var/lib/machines
 
# systemd-nspawn -D myContainer
 
# systemd-nspawn -D myContainer
 
# passwd
 
# passwd
 
# logout
 
# logout
   
  +
=== Fedora または AlmaLinux 環境の作成 ===
上記のコマンドで上手く行かない場合、コンテナを起動してから以下のコマンドを使ってみてください:
 
   
  +
{{Pkg|dnf}} をインストールし、必要な Fedora リポジトリを追加するために {{ic|/etc/dnf/dnf.conf}} ファイルを編集します。
# systemd-nspawn -b -D myContainer #Starts the container
 
# machinectl shell root@myContainer /bin/bash #Get a root bash shell
 
# passwd
 
# logout
 
   
  +
{{hc|/etc/dnf/dnf.conf|output=<nowiki>
=== パッケージのビルドおよびテスト ===
 
  +
[fedora]
  +
name=Fedora $releasever - $basearch
  +
metalink=https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch
  +
gpgkey=https://getfedora.org/static/fedora.gpg
   
  +
[updates]
使用例については、[[他のディストリビューションのパッケージの作成]] を参照してください。
 
  +
name=Fedora $releasever - $basearch - Updates
  +
metalink=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch
  +
gpgkey=https://getfedora.org/static/fedora.gpg</nowiki>
  +
}}
   
  +
''fedora.gpg'' ファイルには最新の Fedora リリース用の gpg キーが含まれています https://getfedora.org/security/ 。Fedora 37 の最小コンテナを設定するには:
=== プライベートユーザーの作成 (非特権コンテナ) ===
 
   
  +
# cd /var/lib/machines
''systemd-nspawn'' は非特権コンテナをサポートしていますが、コンテナは root で起動する必要があります。
 
  +
# mkdir ''container-name''
  +
# dnf --releasever=37 --best --setopt=install_weak_deps=False --repo=fedora --repo=updates --installroot=/var/lib/machines/''container-name'' install dhcp-client dnf fedora-release glibc glibc-langpack-en iputils less ncurses passwd systemd systemd-networkd systemd-resolved util-linux vim-default-editor
   
  +
{{note|異なる Fedora リリースをインストールしたい場合は、異なるリリースが [https://docs.fedoraproject.org/en-US/fedora-server/containerization/systemd-nspawn-setup/#_2_1_creating_a_container_directory_tree 独自のパッケージ要件] を持つことを考慮してください。
{{Note|非特権コンテナは {{man|7|user_namespaces}} を必要とします。詳しくは [[Linux Containers#非特権コンテナのサポートを有効化 (任意)]] を参照してください。}}
 
   
  +
btrfs ファイルシステムを使用している場合は、ディレクトリを作成する代わりにサブボリュームを作成してください。
非特権コンテナを使うときは ''systemd-nspawn'' に全てを決めさせるのが一番簡単です:
 
  +
}}
   
  +
AlmaLinux のようなエンタープライズ Linux 派生物は、デフォルトで三つのリポジトリが有効になっています。''BaseOS'' は、すべてのインストールの基盤となるコアセットを含み、''AppStream'' は追加アプリケーション、言語パッケージなどを含み、''Extras'' は RHEL に含まれないパッケージを含んでいます。したがって、最小限のコンテナには {{ic|/etc/dnf/dnf.conf}} に BaseOS リポジトリのみを追加する必要があります。
# systemd-nspawn -UD myContainer
 
# passwd
 
# logout
 
# systemd-nspawn -bUD myContainer
 
   
  +
{{hc|/etc/dnf/dnf.conf|output=<nowiki>
上記のコマンドで ''systemd-nspawn'' はディレクトリの所有者が使われているかどうか確認して、使われていない場合は所有者をベースとしてそれを上回る 65536 の ID が使われます。一方で UID/GID が使用中の場合はランダムに 524288 - 1878982656 の範囲から 65536 の ID を選択します。
 
  +
[baseos]
 
  +
name=AlmaLinux $releasever - BaseOS
{{Note|
 
  +
mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/baseos
* ランダムに選ばれるベース ID は必ず 65536 の倍数です。
 
  +
gpgkey=https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-$releasever</nowiki>
* カーネルがユーザー名前空間をサポートしている場合、{{ic|-U}} と {{ic|1=--private-users=pick}} は同じです。{{ic|1=--private-users=pick}} には {{ic|1=--private-users-chown}} が暗黙的に含まれます。詳しくは {{man|1|systemd-nspawn}} を参照してください。
 
 
}}
 
}}
   
コンテナの UID/GID 手動で指定することも可能です:
+
AlmaLinux 9 の最小コンテナを作成するには:
   
  +
# dnf --repo=baseos --releasever=9 --best --installroot=/var/lib/machines/''container-name'' --setopt=install_weak_deps=False install almalinux-release dhcp-client dnf glibc-langpack-en iproute iputils less passwd systemd vim-minimal
# systemd-nspawn -D myContainer --private-users=1354956800:65536 --private-users-chown
 
# passwd
 
# logout
 
# systemd-nspawn -bUD myContainer
 
   
  +
これにより、AlmaLinux 9 の最新マイナーバージョンがインストールされますが、特定のポイントリリースをインストールすることもできますが、その場合は ''gpgpkey'' エントリを手動で ''RPM-GPG-KEY-AlmaLinux-9'' を指すように変更する必要があります。
コンテナの起動時に {{ic|1=--private-users=1354956800:65536}} と {{ic|--private-users-chown}} を使うこともできますが、無駄に複雑なので、ID を割り当てた後に {{ic|-U}} を使うようにしてください。
 
   
  +
Arch、Fedora、AlmaLinux のように、root パスワードを設定しない限り、root としてログインすることは許可されません。root パスワードを設定するには、{{ic|-b}} オプションなしで ''systemd-nspawn'' を実行してください:
=== マシンのブート時にコンテナを起動する ===
 
   
  +
# systemd-nspawn -D /var/lib/machines/''container-name'' passwd
コンテナを頻繁に使用する場合、ブート時に systemd でコンテナを起動できます。まず {{ic|systemd}} ターゲットの {{ic|machines.target}} を有効化してください:
 
   
  +
=== パッケージのビルドおよびテスト ===
# systemctl enable machines.target
 
   
  +
使用例については、[[他のディストリビューションのパッケージの作成]] を参照してください。
それから以下を実行してください:
 
   
  +
== 管理 ==
# mv ~/MyContainer /var/lib/machines/MyContainer
 
# systemctl enable systemd-nspawn@MyContainer.service
 
# systemctl start systemd-nspawn@MyContainer.service
 
   
{{Note|{{ic|systemd-nspawn@.service}} は nspawn コテナが {{ic|/var/lib/machines}} にあることを想定したテンプユニットです。}}
+
{{ic|/var/lib/machines/}} にあるコンテナは、''machinectl'' コマンドによって制御することができます。内部的には {{ic|systemd-nspawn@.service}} ユニットのイスタンスを制御しています。{{ic|/var/lib/machines/}} のサブディリはコンテナ名に対応しています。
   
  +
{{Note|なんらかの理由でコンテナを {{ic|/var/lib/machines/}} に移動できない場合、シンボリックリンクが使えます。{{man|1|machinectl|FILES AND DIRECTORIES}} を参照してください。}}
{{Tip|
 
* {{Pkg|systemd}} v229 現在 {{ic|/var/lib/machines}} にコンテナのシンボリックリンクを作成しても動作しません。[https://github.com/systemd/systemd/issues/2001] を参照。
 
* コンテナの起動をカスタマイズする場合、{{ic|/etc/systemd/nspawn/''myContainer''.nspawn}} ユニットを[[systemd#ユニットファイルの編集|編集]]してください。利用可能なオプションは {{man|5|systemd.nspawn}} を参照。
 
}}
 
   
  +
=== systemd-nspawn オプションのデフォルト値 ===
[[cgroups|control group]] の中身を表示したい場合は、{{ic|$ systemd-cgls}} を実行してください。
 
   
  +
''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 ===
使用例は[[他のディストリビューションのパッケージの作成]]を参照。
 
   
  +
{{Note|''machinectl'' ツールを使うには [[systemd]] と {{Pkg|dbus}} がコンテナにインストールされている必要があります。詳しくは [https://github.com/systemd/systemd/issues/685] を参照。}}
=== Default systemd-nspawn options ===
 
   
  +
コンテナはコマンドで管理できます。例えば、コンテナを起動するには、次のようにします。
It is important to realize that containers started via ''machinectl'' or {{ic|systemd-nspawn@.service}} use different default options than containers started manually by the ''systemd-nspawn'' command. The extra options used by the service are:
 
   
  +
$ machinectl start ''container-name''
* {{ic|-b}}/{{ic|--boot}} – Managed containers automatically search for an init program and invoke it as PID 1.
 
* {{ic|--network-veth}} which implies {{ic|--private-network}} – Managed containers get a virtual network interface and are disconnected from the host network. See [[#Networking]] for details.
 
* {{ic|-U}} – Managed containers use the {{man|7|user_namespaces}} feature by default if supported by the kernel. See [[#Unprivileged containers]] for implications.
 
* {{ic|1=--link-journal=try-guest}}
 
   
  +
{{Note|''machinectl'' は、コンテナ名が有効な[[ホスト名]]であるように、ASCII 文字、数字、ハイフンのみで構成されていることを要求します。例えば、コンテナ名にアンダースコアが含まれている場合、それは単に認識されず、 {{ic|machinectl start container_name}} を実行すると、エラー {{ic|Invalid machine name container_name}} となります。詳しくは[https://github.com/systemd/systemd/issues/11765]と[https://github.com/systemd/systemd/commit/d65652f1f21a4b0c59711320f34266c635393c89]を参照してください。}}
The behaviour can be overridden in per-container configuration files, see [[#Configuration]] for details.
 
   
  +
同様に、{{ic|poweroff}}, {{ic|reboot}}, {{ic|status}}, {{ic|show}} などのサブコマンドがあります。詳細な説明については、{{man|1|machinectl|Machine Commands}} を参照してください。
=== machinectl ===
 
   
  +
{{Tip|電源オフと再起動の操作は、{{ic|poweroff}} と {{ic|reboot}} コマンドを使用してコンテナ内から実行することができます。}}
{{Note|''machinectl'' ツールを使うには [[systemd]] と {{Pkg|dbus}} がコンテナにインストールされている必要があります。詳しくは [https://github.com/systemd/systemd/issues/685] を参照。}}
 
   
  +
その他の一般的なコマンドは以下の通りです:
コンテナの管理は原則 {{ic|$ machinectl}} コマンドで行います。このサービスを使って仮想マシンやコンテナの状態を確認したり操作します。オプションの詳細なリストは {{ic|machinectl(1)}} を参照してください。
 
   
  +
* {{ic|machinectl list}} – 現在実行中のコンテナの一覧を表示する
例:
 
  +
* {{ic|machinectl login container-name}} - 実行中のコンテナに新しいシェルを起動
  +
* {{ic|machinectl shell ''[username@]container-name''}} – コンテナで対話的なシェルセッションを開きます(コンテナ内のログインプロセスを経ずにユーザープロセスが即座に呼びだす)。
  +
* {{ic|machinectl enable container-name}} または {{ic|machinectl disable container-name}} - コンテナを有効または無効にして、起動時に開始します。詳細については、[[#PC起動時にコンテナを自動で開始する]] を参照してください。
   
  +
''machinectl'' にはコンテナ(または仮想マシン)イメージとイメージ転送を管理するためのサブコマンドもあります。詳細については、{{man|1|machinectl|Image Commands}} および、{{man|1|machinectl|Image Transfer Commands}} を参照してください。2023Q1 時点で、{{man|1|machinectl|EXAMPLES}} にある最初の 3 つの例はイメージ転送コマンドを示しています。{{man|1|machinectl|FILES AND DIRECTORIES}} では、適切なイメージをどこで見つけるかについて説明しています。
* 実行中のコンテナに新しいシェルを起動: {{bc|$ machinectl login MyContainer}}
 
* コンテナの詳細情報を表示: {{bc|$ machinectl status MyContainer}}
 
* コンテナを再起動: {{bc|$ machinectl reboot MyContainer}}
 
* コンテナを電源オフ: {{bc|$ machinectl poweroff MyContainer}}
 
:{{Tip|電源オフや再起動は ''systemctl'' の {{ic|reboot}} や {{ic|poweroff}} コマンドをコンテナのセッションの中から実行することでも可能です。}}
 
* イメージをダウンロード: {{bc|# machinectl pull-tar ''URL'' ''name''}}
 
   
 
=== systemd ツールチェイン ===
 
=== systemd ツールチェイン ===
179行目: 180行目:
 
* リソース利用状況を表示: {{bc|$ systemd-cgtop}}
 
* リソース利用状況を表示: {{bc|$ systemd-cgtop}}
   
== Configuration ==
+
== 設定 ==
   
=== Per-container settings ===
+
=== コンテナ毎の設定 ===
   
  +
グローバル設定のオーバーライドではなく、コンテナ毎の設定を指定するには、''.nspawn'' ファイルを使用できます。詳細については、 {{man|5|systemd.nspawn}} を参照してください。
To specify per-container settings and not global overrides, the ''.nspawn'' files can be used. See {{man|5|systemd.nspawn}} for details.
 
   
 
{{Note|
 
{{Note|
  +
* ''.nspawn'' ファイルは、{{ic|machinectl remove}} を実行した時に、{{ic|/etc/systemd/nspawn/}} から予期せずに削除される場合があります。
* ''.nspawn'' files may be removed unexpectedly from {{ic|/etc/systemd/nspawn/}} when you run {{ic|machinectl remove}}. [https://github.com/systemd/systemd/issues/15900]
 
  +
* {{ic|systemd-nspawn@.service}} ファイルで指定されている、{{ic|1=--settings=override}} がある場合、''.nspawn'' ファイルで指定されているネットワークオプションとコマンドラインオプションの相互作用で正しく動作しません。回避策としてサービスが {{ic|1=--network-veth}} を指定している場合でも、{{ic|1=VirtualEthernet=on}} オプションを含める必要があります。
* The interaction of network options specified in the ''.nspawn'' file and on the command line does not work correctly when there is {{ic|1=--settings=override}} (which is specified in the {{ic|systemd-nspawn@.service}} file). [https://github.com/systemd/systemd/issues/12313#issuecomment-681116926] As a workaround, you need to include the option {{ic|1=VirtualEthernet=on}}, even though the service specifies {{ic|1=--network-veth}}.
 
 
}}
 
}}
   
  +
=== PC起動時にコンテナを自動で開始する ===
=== Enable container to start at boot ===
 
 
When using a container frequently, you may want to start it at boot.
 
   
  +
コンテナを頻繁に使用する場合は、PC起動時に開始することをおすすめします。
First make sure that the {{ic|machines.target}} is [[enabled]].
 
   
  +
まず、{{ic|machines.target}} が[[systemd#ユニットを使う|有効]]になっている事を確認します。
Containers discoverable by [[#machinectl|machinectl]] can be enabled or disabled:
 
  +
[[#machinectl|machinectl]] で検出可能なコンテナは、有効または無効にできます:
   
 
$ machinectl enable ''container-name''
 
$ machinectl enable ''container-name''
   
 
{{Note|
 
{{Note|
* This has the effect of enabling the {{ic|systemd-nspawn@''container-name''.service}} systemd unit.
+
* まず {{ic|systemd-nspawn@''container-name''.service}} ユニットを有効にする効果があります。
  +
* [[#systemd-nspawn オプションのデフォルト値]] で説明されているように、''machinectl'' と入力し開始されたコンテナは仮想 Ethernet インタフェースを取得します。プライベートネットワークを無効にするには、 [[#ホストネットワークを使う]] を参照してください。
* As mentioned in [[#Default systemd-nspawn options]], containers started by ''machinectl'' get a virtual Ethernet interface. To disable private networking, see [[#Use host networking]].
 
 
}}
 
}}
   
=== Resource control ===
+
=== リソース制御 ===
   
  +
{{ic|systemctl set-property}} でコンテナの制限やリソース管理を実装するために、コントロールグループを利用することができます。{{man|5|systemd.resource-control}} を参照してください。例えば、メモリ容量やCPU使用率を制限できます。コンテナのメモリ消費を2GiBに制限するには:
You can take advantage of control groups to implement limits and resource management of your containers with {{ic|systemctl set-property}}, see {{man|5|systemd.resource-control}}. For example, you may want to limit the memory amount or CPU usage. To limit the memory consumption of your container to 2 GiB:
 
   
 
# systemctl set-property systemd-nspawn@''container-name''.service MemoryMax=2G
 
# systemctl set-property systemd-nspawn@''container-name''.service MemoryMax=2G
   
  +
または、CPU時間の使用量をだいたい2コア分に制限したい場合:
Or to limit the CPU time usage to roughly the equivalent of 2 cores:
 
   
 
# systemctl set-property systemd-nspawn@''container-name''.service CPUQuota=200%
 
# systemctl set-property systemd-nspawn@''container-name''.service CPUQuota=200%
   
  +
これにより以下の永続ファイルが作成されます。
This will create permanent files in {{ic|/etc/systemd/system.control/systemd-nspawn@''container-name''.service.d/}}.
 
  +
{{ic|/etc/systemd/system.control/systemd-nspawn@''container-name''.service.d/}}.
   
  +
ドキュメントによると、{{ic|MemoryHigh}} はメモリ消費をチェックするための推奨される方法ですが、{{ic|MemoryMax}} のように厳密に制限されることはありません。{{ic|MemoryMax}} を最終防衛戦として残して、両方のオプションを使用できます。また、コンテナが認識できるCPUの数を制限しないことも考慮に入れてください。ただし、CPU時間合計に対して、コンテナが最大で取得する時間を制限することで、同様の結果が得られます。
According to the documentation, {{ic|MemoryHigh}} is the preferred method to keep in check memory consumption, but it will not be hard-limited as is the case with {{ic|MemoryMax}}. You can use both options leaving {{ic|MemoryMax}} as the last line of defense. Also take in consideration that you will not limit the number of CPUs the container can see, but you will achieve similar results by limiting how much time the container will get at maximum, relative to the total CPU time.
 
   
  +
{{Tip|これらの変更を一時的なものにしたい場合は、{{ic|--runtime}} オプションを渡すことができます。その結果は、''systemd-cgtop'' で確認できます。}}
{{Tip|If you want these changes to be only temporary, you can pass the option {{ic|--runtime}}. You can check their results with ''systemd-cgtop''.}}
 
   
=== Networking ===
+
=== ネットワーキング ===
   
  +
''systemd-nspawn'' コンテナは、''ホストネットワーク'' または ''プライベートネットワーク''のいずれかを使用できます。
''systemd-nspawn'' containers can use either ''host networking'' or ''private networking'':
 
  +
* ホストネットワークモードでは、コンテナはホストネットワークへのフルアクセスが可能です。これは、コンテナがホスト上のすべてのネットワークサービスにアクセスできるようになり、コンテナからのパケットがホストのパケットとして外部ネットワークに表示される事を意味します(つまり、同じIPアドレスを共有します)。
  +
* プライベートネットワークモードでは、コンテナはホストのネットワークから切断されています。これにより、ループバックデバイスとコンテナに明示的に割り当てられたものを除いて、すべてのネットワークインターフェイスがコンテナを使用できなくなります。コンテナのネットワークインターフェイスを設定するには、いくつかの方法があります。
  +
** 既存のインターフェイスをコンテナに割り当てることができます(たとえば、複数のイーサネットデバイスがある場合)。
  +
** 既存のインターフェース(つまり、[[VLAN]]インターフェース)に関連付けられた仮想ネットワークインターフェースを作成して、コンテナーに割り当てることができます。
  +
** ホストとコンテナの間に仮想イーサネットリンクを作成できます。
  +
: 後者の場合、コンテナのネットワークは、(外部ネットワークや他のコンテナから) 完全に分離されており、ホストとコンテナ間のネットワークを構成するのは管理者の責任です。これには通常、複数の(物理または仮想)インターフェイスを接続するための [[ネットワークブリッジ]] の作成、または複数のインターフェイス間の [[wikipedia:ja:ネットワークアドレス変換|ネットワークアドレス変換]] の設定が含まれます。
   
  +
ホストネットワーキングモードは、コンテナに割り当てられたインターフェースを構成するネットワーキングソフトウェアを実行しない ''アプリケーションコンテナ'' に適しています。ホストネットワーキングは、シェルから ''systemd-nspawn'' を実行するときのデフォルトのモードです。
* In the host networking mode, the container has full access to the host network. This means that the container will be able to access all network services on the host and packets coming from the container will appear to the outside network as coming from the host (i.e. sharing the same IP address).
 
* In the private networking mode, the container is disconnected from the host's network. This makes all network interfaces unavailable to the container, with the exception of the loopback device and those explicitly assigned to the container. There is a number of different ways to set up network interfaces for the container:
 
** an existing interface can be assigned to the container (e.g. if you have multiple Ethernet devices),
 
** a virtual network interface associated with an existing interface (i.e. [[VLAN]] interface) can be created and assigned to the container,
 
** a virtual Ethernet link between the host and the container can be created.
 
: In the latter case the container's network is fully isolated (from the outside network as well as other containers) and it is up to the administrator to configure networking between the host and the containers. This typically involves creating a [[network bridge]] to connect multiple (physical or virtual) interfaces or setting up a [[Wikipedia:Network Address Translation|Network Address Translation]] between multiple interfaces.
 
   
  +
一方、プライベート・ネットワーキング・モードは、ホスト・システムから隔離されている必要がある ''システムコンテナ'' に適しています。仮想イーサネットリンクの作成は、複雑な仮想ネットワークの作成を可能にする非常に柔軟なツールです。これは ''machinectl'' や {{ic|systemd-nspawn@.service}} によって起動されたコンテナのデフォルトモードです。
The host networking mode is suitable for ''application containers'' which do not run any networking software that would configure the interface assigned to the container. Host networking is the default mode when you run ''systemd-nspawn'' from the shell.
 
   
  +
次のサブセクションでは、一般的なシナリオについて説明します。使用可能な ''systemd-nspawn'' のオプションの詳細については、{{man|1|systemd-nspawn|Networking Options}} を参照してください。
On the other hand, the private networking mode is suitable for ''system containers'' that should be isolated from the host system. The creation of virtual Ethernet links is a very flexible tool allowing to create complex virtual networks. This is the default mode for containers started by ''machinectl'' or {{ic|systemd-nspawn@.service}}.
 
   
  +
==== ホストネットワークを使う ====
The following subsections describe common scenarios. See {{man|1|systemd-nspawn|Networking Options}} for details about the available ''systemd-nspawn'' options.
 
   
  +
プライベートネットワークを無効にし、''machinectl'' で開始されたコンテナで使用される仮想イーサネットリンクを作成するには、次のオプションを指定して、''.nspawn'' ファイルを追加します:
==== Use host networking ====
 
 
To disable private networking and the creation of a virtual Ethernet link used by containers started with ''machinectl'', add a ''.nspawn'' file with the following option:
 
   
 
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
 
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
247行目: 247行目:
 
}}
 
}}
   
  +
これにより、{{ic|systemd-nspawn@.service}} の {{ic|-n}}/{{ic|--network-veth}} オプションが上書きされ、新しく開始されたコンテナはホストネットワークモードを使用します。
This will override the {{ic|-n}}/{{ic|--network-veth}} option used in {{ic|systemd-nspawn@.service}} and the newly started containers will use the host networking mode.
 
   
  +
==== 仮想イーサネットリンクを使用する ====
==== Use a virtual Ethernet link ====
 
   
  +
コンテナが、{{ic|-n}}/{{ic|--network-veth}} オプションで起動された場合、''systemd-nspawn'' はホストとコンテナの間に仮想イーサネットリンクを作成します。リンクのホスト側は、{{ic|ve-''container-name''}} という名前のネットワークインターフェイスとして利用可能になります。リンクのコンテナ側は、{{ic|hosts0}} という名前になります。このオプションは、{{ic|--private-network}} を意味することに注意してください。
If a container is started with the {{ic|-n}}/{{ic|--network-veth}} option, ''systemd-nspawn'' will create a virtual Ethernet link between the host and the container. The host side of the link will be available as a network interface named {{ic|ve-''container-name''}}. The container side of the link will be named {{ic|host0}}. Note that this option implies {{ic|--private-network}}.
 
   
 
{{Note|
 
{{Note|
  +
* コンテナ名が長すぎる場合、インターフェイス名は、[https://stackoverflow.com/a/29398765 15文字制限] に収まるように短縮されます(例: {{ic|ve-long-container-name}} の代わりに {{ic|ve-long-conKQGh}})。フルネームはインターフェイスの {{ic|altname}} プロパティとして設定され({{man|8|ip-link}}を参照)、インターフェイスの参照に使用できます。
* If the container name is too long, the interface name will be shortened (e.g. {{ic|ve-long-conKQGh}} instead of {{ic|ve-long-container-name}}) to fit into the [https://stackoverflow.com/a/29398765 15-characters limit]. The full name will be set as the {{ic|altname}} property of the interface (see {{man|8|ip-link}}) and can be still used to reference the interface.
 
  +
* When examining the interfaces with {{ic|ip link}}, interface names will be shown with a suffix, such as {{ic|ve-''container-name''@if2}} and {{ic|host0@if9}}. The {{ic|@if''N''}} is not actually part of the interface name; instead, {{ic|ip link}} appends this information to indicate which "slot" the virtual Ethernet cable connects to on the other end.
 
  +
* {{ic|ip link}} でインターフェイスを調べる場合、インターフェイス名は、{{ic|ve-''container-name''@if2}} や {{ic|host0@if9}} のようにサフィックスを付けて表示されます。{{ic|@if''N''}} は実際にはインターフェイス名の一部ではありません。その代わりに、{{ic|ip link}} はこの情報を追加して、仮想イーサネットケーブルが相手側のどの ''slot'' に接続しているかを示します
: For example, a host virtual Ethernet interface shown as {{ic|ve-''foo''@if2}} is connected to the container {{ic|''foo''}}, and inside the container to the second network interface – the one shown with index 2 when running {{ic|ip link}} inside the container. Similarly, the interface named {{ic|host0@if9}} in the container is connected to the 9th network interface on the host.
 
  +
: 例えば、{{ic|ve-''foo''@if2}} とし表示されているホスト仮想イーサネットインターフェイスはコンテナ {{ic|''foo''}} に接続され、コンテナ内で {{ic|ip link}} を実行しているときに、index 2 で示されている 2 番目のネットワークインタフェースに接続されています。同様に、コンテナ内の {{ic|host0@if9}} という名前のインターフェイスは、ホスト上の 9 番目のネットワークインターフェイス接続されています。}}
}}
 
   
  +
コンテナを起動する際には、ホストとコンテナの両方のインターフェイスにIPアドレスを割り当てなければなりません。ホストとコンテナの両方で [[systemd-networkd]] を使用している場合、初期状態で実行されます:
When you start the container, an IP address has to be assigned to both interfaces (on the host and in the container). If you use [[systemd-networkd]] on the host as well as in the container, this is done out-of-the-box:
 
   
* the {{ic|/usr/lib/systemd/network/80-container-ve.network}} file on the host matches the {{ic|ve-''container-name''}} interface and starts a DHCP server, which assigns IP addresses to the host interface as well as the container,
+
* ホスト上の {{ic|/usr/lib/systemd/network/80-container-ve.network}} ファイルは {{ic|ve-container-name}} インターフェイスと一致し、DHCP サーバーを起動します。DHCP サーバーは、IP アドレスをホストインターフェイスとコンテナーに割り当てます。
* the {{ic|/usr/lib/systemd/network/80-container-host0.network}} file in the container matches the {{ic|host0}} interface and starts a DHCP client, which receives an IP address from the host.
+
* {{ic|/usr/lib/systemd/network/80-container-host0.network}} コンテナ内のファイルは {{ic|host0}} インターフェイスと一致し、ホストから IP アドレスを受信する DHCP クライアントを起動します。
   
  +
[[systemd-networkd]] を使用しない場合は、静的IPアドレスを設定するか、ホストインターフェイスで、DHCP サーバを起動し、コンテナで DHCP クライアントを起動できます。詳細については、[[ネットワーク設定]] を参照してください。
If you do not use [[systemd-networkd]], you can configure static IP addresses or start a DHCP server on the host interface and a DHCP client in the container. See [[Network configuration]] for details.
 
   
  +
コンテナに外部ネットワークへのアクセスを許可するには、[[インターネット共有#NAT の有効化]] の説明に従って NAT を設定します。[[systemd-networkd]] を使用する場合、これは、{{ic|/usr/lib/systemd/network/80-container-ve.network}} ファイルの {{ic|1=IPMasquerade=yes}} オプションを介して(部分的に)自動的に行われます。ただし、これは次のような [[iptables]] ルールのみを発行します。
To give the container access to the outside network, you can configure NAT as described in [[Internet sharing#Enable NAT]]. If you use [[systemd-networkd]], this is done (partially) automatically via the {{ic|1=IPMasquerade=yes}} option in {{ic|/usr/lib/systemd/network/80-container-ve.network}}. However, this issues just one [[iptables]] rule such as
 
   
 
-t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE
 
-t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE
   
  +
{{ic|filter}} テーブルは、[[インターネット共有#NAT の有効化]]のように手動で設定する必要があります。ワイルドカードを使用して、{{ic|ve-}} で始まるすべてのインターフェイスに一致させることができます:
The {{ic|filter}} table has to be configured manually as shown in [[Internet sharing#Enable NAT]]. You can use a wildcard to match all interfaces starting with {{ic|ve-}}:
 
   
 
# iptables -A FORWARD -i ve-+ -o ''internet0'' -j ACCEPT
 
# iptables -A FORWARD -i ve-+ -o ''internet0'' -j ACCEPT
   
{{Note|''systemd-networkd'' uses the [https://tldp.org/HOWTO/Querying-libiptc-HOWTO/whatis.html libiptc] library to interact with [[iptables]]. If you use [[nftables]], install the {{Pkg|iptables-nft}} translation layer. See also [https://github.com/systemd/systemd/issues/13307 systemd issue 13307].}}
+
{{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] も参照してください。}}
   
  +
さらに、DHCP サーバー(''systemd-networkd'' によって運用される)への着信接続用に {{ic|ve-+}} インターフェースの UDP ポート 67 を開く必要があります:
{{Accuracy|Investigate if/why the following is necessary.}}
 
   
  +
# iptables -A INPUT -i ve-+ -p udp -m udp --dport 67 -j ACCEPT
Additionally, the rule {{ic|-A FORWARD -i ve-+ -o ''internet0'' -j ACCEPT}} may not work as described in [[Internet sharing#Enable NAT]]. If that is the case, try {{ic|-A FORWARD -i ve-+ -j ACCEPT}}.
 
   
  +
==== ネットワークブリッジを使用する ====
==== Use a network bridge ====
 
   
  +
ホストシステムに[[ネットワークブリッジ]]を構成している場合は、コンテナの仮想イーサネットリンクを作成し、そのホスト側をネットワークブリッジに追加できます。 これは、{{ic|1=--network-bridge=''bridge-name''}} オプションを使用して実行されます。{{ic|--network-bridge}} は {{ic|--network-veth}} を意味することに注意してください。つまり、仮想イーサネットリンクは自動的に作成されます。 ただし、リンクのホスト側は {{ic|ve-}} ではなく {{ic|vb-}} プリフィックスを使用するため、DHCP サーバーと IP マスカレードを起動するための systemd-networkd オプションは適用されません。
If you have configured a [[network bridge]] on the host system, you can create a virtual Ethernet link for the container and add its host side to the network bridge. This is done with the {{ic|1=--network-bridge=''bridge-name''}} option. Note that {{ic|--network-bridge}} implies {{ic|--network-veth}}, i.e. the virtual Ethernet link is created automatically. However, the host side of the link will use the {{ic|vb-}} prefix instead of {{ic|ve-}}, so the [[systemd-networkd]] options for starting the DHCP server and IP masquerading will not be applied.
 
   
The bridge management is left to the administrator. For example, the bridge can connect virtual interfaces with a physical interface, or it can connect only virtual interfaces of several containers. See [[systemd-networkd#Network bridge with DHCP]] and [[systemd-networkd#Network bridge with static IP addresses]] for example configurations using [[systemd-networkd]].
+
ブリッジの管理は管理者に任されています。例えば、ブリッジは物理インターフェースと仮想インターフェースを接続したり、複数のコンテナの仮想インターフェースのみを接続したりすることができます。[[systemd-networkd]] を使用した設定例については、[[systemd-networkd#Network bridge with DHCP]] [[systemd-networkd#Network bridge with static IP addresses]] を参照してください。
   
There is also a {{ic|1=--network-zone=''zone-name''}} option which is similar to {{ic|--network-bridge}} but the network bridge is managed automatically by ''systemd-nspawn'' and ''systemd-networkd''. The bridge interface named {{ic|vz-''zone-name''}} is automatically created when the first container configured with {{ic|1=--network-zone=''zone-name''}} is started, and is automatically removed when the last container configured with {{ic|1=--network-zone=''zone-name''}} exits. Hence, this option makes it easy to place multiple related containers on a common virtual network. Note that {{ic|vz-*}} interfaces are managed by [[systemd-networkd]] same way as {{ic|ve-*}} interfaces using the options from the {{ic|/usr/lib/systemd/network/80-container-vz.network}} file.
+
また、{{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]] によって管理されることに注意してください。
   
==== Use a "macvlan" or "ipvlan" interface ====
+
==== macvlan」または「ipvlan」インターフェースを使用する ====
   
  +
仮想イーサネットリンク(ホスト側がブリッジに追加される場合とされない場合があります)を作成する代わりに、既存の物理インターフェイス(つまり、[[VLAN]] インターフェイス)上に仮想インターフェイスを作成し、それをコンテナに追加できます。仮想インターフェイスは、基盤となるホストインターフェイスとブリッジされるため、コンテナは外部ネットワークに公開されます。これにより、ホストが接続されているのと同じ LAN から DHCP を介して個別の IP アドレスを取得できます。
Instead of creating a virtual Ethernet link (whose host side may or may not be added to a bridge), you can create a virtual interface on an existing physical interface (i.e. [[VLAN]] interface) and add it to the container. The virtual interface will be bridged with the underlying host interface and thus the container will be exposed to the outside network, which allows it to obtain a distinct IP address via DHCP from the same LAN as the host is connected to.
 
   
''systemd-nspawn'' offers 2 options:
+
''systemd-nspawn'' には2つのオプションがあります:
   
* {{ic|1=--network-macvlan=''interface''}} – the virtual interface will have a different MAC address than the underlying physical {{ic|''interface''}} and will be named {{ic|mv-''interface''}}.
+
* {{ic|1=--network-macvlan=''interface''}} – 仮想インターフェイスは、基盤となる物理インターフェイスとは異なるMACアドレスを持ち、{{ic|mv-''interface''}} という名前が付けられます。
* {{ic|1=--network-ipvlan=''interface''}} – the virtual interface will have the same MAC address as the underlying physical {{ic|''interface''}} and will be named {{ic|iv-''interface''}}.
 
   
  +
* {{ic|1=--network-ipvlan=''interface''}} – 仮想インターフェイスは、基礎となる物理インターフェイスと同じMACアドレスを持ち、{{ic|iv-''interface''}} と名付けられます。
Both options imply {{ic|--private-network}}.
 
   
  +
どちらのオプションも {{ic|--private-network}} を意味します。
==== Use an existing interface ====
 
   
  +
{{Note|ホストがコンテナと通信できるようにするために、ホストに macvlan または ipvlan インターフェースを作成し、それをコンテナが使用している同じ物理インターフェースに接続し、その上でネットワーク接続を設定してください。仮想インターフェース名が ''systemd-nspawn'' によって作成された仮想インターフェースと衝突しないことを確認してください。''systemd-networkd'' を使用した例については、[[systemd-networkd#MACVLAN bridge]] を参照してください。}}
If the host system has multiple physical network interfaces, you can use the {{ic|1=--network-interface=''interface''}} to assign {{ic|''interface''}} to the container (and make it unavailable to the host while the container is started). Note that {{ic|--network-interface}} implies {{ic|--private-network}}.
 
   
  +
==== 既存のインターフェイスを使用する ====
{{Note|Passing wireless network interfaces to ''systemd-nspawn'' containers is currently not supported. [https://github.com/systemd/systemd/issues/7873]}}
 
   
  +
ホストシステムに複数の物理ネットワークインターフェイスがある場合は、 {{ic|1=--network-interface=''interface''}} を使用してコンテナにインターフェイスを割り当てることができます(コンテナが起動している間はホストからは利用できないようにします)。{{ic|--network-interface}} は{{ic|--private-network}} を意味することに注意してください。
=== Port mapping ===
 
   
  +
{{Note|''systemd-nspawn'' コンテナにワイヤレスネットワークインターフェイスを渡すことは現在サポートされていません。[https://github.com/systemd/systemd/issues/7873]}}
When private networking is enabled, individual ports on the host can be mapped to ports on the container using the {{ic|-p}}/{{ic|--port}} option or by using the {{ic|Port}} setting in an ''.nspawn'' file. This is done by issuing [[iptables]] rules to the {{ic|nat}} table, but the {{ic|FORWARD}} chain in the {{ic|filter}} table needs to be configured manually as shown in [[#Use a virtual Ethernet link]].
 
   
  +
=== ポートマッピング ===
For example, to map a TCP port 8000 on the host to the TCP port 80 in the container:
 
  +
  +
プライベートネットワークが有効になっている場合、ホストの個々のポートは、{{ic|-p}}/{{ic|--port}} オプションを使用するか、または ''.nspawn'' ファイルの {{ic|Port}} 設定を使用してコンテナのポートにマッピングすることができます。たとえば、ホストの TCP ポート 8000 をコンテナの TCP ポート 80 にマッピングするには:
   
 
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
 
{{hc|/etc/systemd/nspawn/''container-name''.nspawn|2=
315行目: 316行目:
 
Port=tcp:8000:80
 
Port=tcp:8000:80
 
}}
 
}}
  +
  +
これは、{{ic|nat}} テーブルに [[iptables]] ルールを発行することで機能しますが、{{ic|filter}} テーブルの {{ic|FORWARD}} チェインは、[[#仮想イーサネットリンクを使用する]]に示されているように手動で設定する必要があります。さらに、[[シンプルなステートフルファイアウォール]]に従った場合、ホストの {{ic|''wan_interface''}} で転送されたポートへの新しい接続を許可するには、次のコマンドを実行してください:
  +
  +
# iptables -A FORWARD -i ''wan_interface'' -o ve-+ -p tcp --syn --dport 8000 -m conntrack --ctstate NEW -j ACCEPT
   
 
{{Note|
 
{{Note|
* ''systemd-nspawn'' explicitly excludes the {{ic|loopback}} interface when mapping ports. Hence, for the example above, {{ic|localhost:8000}} connects to the host and not to the container. Only connections to other interfaces are subjected to port mapping. See [https://github.com/systemd/systemd/issues/6106] for details.
+
* ''systemd-nspawn'' は、ポートをマッピングする際に {{ic|loopback}} インターフェイスを明示的に除外します。したがって、上記の例では、{{ic|localhost:8000}} はホストに接続し、コンテナには接続しません。他のインターフェイスへの接続のみがポートマッピングの対象となります。詳細は、[https://github.com/systemd/systemd/issues/6106] を参照してください。
* Port mapping works only for IPv4 connections. [https://github.com/systemd/systemd/issues/10254]
+
* ポートマッピングは IPv4 接続に対してのみ機能します。 [https://github.com/systemd/systemd/issues/10254]
 
}}
 
}}
   
=== Domain name resolution ===
+
=== ドメイン名前解決 ===
   
[[Domain name resolution]] in the container can be configured by the {{ic|--resolv-conf}} option of ''systemd-nspawn'' or the corresponding option {{ic|1=ResolvConf=}} for the ''.nspawn'' files. There are many possible values which are described in {{man|1|systemd-nspawn|Integration Options}}.
+
コンテナ内の [[ドメイン名前解決]] ''systemd-nspawn'' {{ic|--resolv-conf}} オプションか、''.nspawn'' ファイルの {{ic|1=ResolvConf=}} オプションで設定できます。{{man|1|systemd-nspawn|統合オプション}} に多くの値が記述されています。
   
  +
デフォルト値は {{ic|auto}} で以下の事を意味します:
The default value is {{ic|auto}}, which means that:
 
   
* If {{ic|--private-network}} is enabled, the {{ic|/etc/resolv.conf}} is left as it is in the container.
+
* {{ic|--private-network}} が有効になっている場合、{{ic|/etc/resolv.conf}} はコンテナ内のまま残ります。
* Otherwise, if [[systemd-resolved]] is running on the host, its stub {{ic|resolv.conf}} file is copied or bind-mounted into the container.
+
* あるいは、ホストで [[systemd-resolved]] が実行されている場合、そのスタブ {{ic|resolv.conf}} ファイルがコンテナにコピーまたはバインドマウントされます。
  +
* それ以外の場合、{{ic|/etc/resolv.conf}} ファイルはホストからコンテナにコピーされるか、バインドマウントされます。
* Otherwise, the {{ic|/etc/resolv.conf}} file is copied or bind-mounted from the host to the container.
 
   
  +
最後の2つのケースでは、コンテナルートが書き込み可能な場合はファイルがコピーされ、読み取り専用の場合はバインドマウントされます。
In the last two cases, the file is copied, if the container root is writeable, and bind-mounted if it is read-only.
 
  +
  +
ホスト上で [[systemd-resolved]] が実行される 2 番目のケースでは、コンテナがホストからのスタブ symlink ファイル {{ic|/etc/resolv.conf}} を使用できるように ''systemd-nspawn'' がコンテナ内でも実行されることを期待します。そうでない場合、デフォルト値の {{ic|auto}} はもはや機能しませんので、{{ic|replace-*}} オプションのいずれかを使ってシンボリックリンクを置き換える必要があります。
   
 
== ヒントとテクニック ==
 
== ヒントとテクニック ==
  +
  +
=== シェル/init 以外のコマンドを実行する ===
  +
  +
{{man|1|systemd-nspawn|Execution Options}} より。
  +
  +
:"'' [オプション] --as-pid2 [呼び出し] シェルまたは指定されたプログラムを、PID 1(init)ではなくプロセス ID(PID)2 として使用します。[...] PID 1として正しく実行されるように変更されていない限り、コンテナ内で任意のコマンドを呼び出すにはこのモードを使用することが推奨されます。言い換えれば、このスイッチは、コマンドが init やシェルの実装を参照している場合を除き、ほとんどすべてのコマンドに使用すべきです。[...] このオプションは {{ic|--boot}} と組み合わせることはできません。
  +
  +
=== 非特権コンテナ ===
  +
  +
''systemd-nspawn'' は非特権コンテナをサポートしますが、コンテナは root として起動する必要があります。
  +
  +
{{Note|この機能には {{man|7|user_namespaces}} が必要です。詳細については、[[Linux Containers#非特権コンテナのサポートを有効化 (任意)]] を参照してください。}}
  +
  +
これを行う最も簡単な方法は、{{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 環境 ===
345行目: 377行目:
 
{{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 ソケットが削除されないように保護することができます。}}
 
{{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 ソケットが削除されないように保護することができます。}}
   
=== nspawn コンテナ中で Firefox を実行 ===
+
==== xhost回避 ====
   
  +
{{ic|xhost}} は、Xサーバに対してかなり粗いアクセス権しか与えません。​{{ic|$XAUTHORITY}} ファイルを使用すると、より詳細なアクセス制御が可能になります。​残念ながら、コンテナ内の{{ic|$XAUTHORITY}} ファイルにアクセスできるようにしただけではうまくいきません。{{ic|$XAUTHORITY}} ファイルはホスト固有のものですが、コンテナは別のホストです。​stackoverflowを参考にした以下のトリックを使えば、Xサーバがコンテナ内で実行されているXアプリケーションから、{{ic|$XAUTHORITY}} ファイルを受け入れるようにすることができます:
[[Firefox 設定#nspawn コンテナの中で Firefox を実行]]を見て下さい。
 
   
  +
$ 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}} を参照。
例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:
 
   
  +
==== X nesting/Xephyr を使用====
# systemd-nspawn --bind=/var/cache/pacman/pkg
 
   
  +
X アプリケーションを実行し、共有 X デスクトップのリスクを回避するもう1つの簡単な方法は、X nesting を使用することです。
詳しくは {{man|1|systemd-nspawn}} の {{ic|--bind}} と {{ic|--bind-ro}} を参照してください。
 
  +
ここでの利点は、コンテナ内アプリケーションと非コンテナアプリケーションの間の相互作用を完全に回避し、異なる [[デスクトップ環境]] または [[ウィンドウマネージャ]] を実行できることです。 欠点はパフォーマンスの低下と [[Xephyr]] を使用した場合のハードウェアアクセラレーションの欠如です。
   
ファイル使ってコンテナごとにバインドを設定することもできます:
+
Xephyr をコンテナの外で起動するには以下の方法があります
   
  +
# Xephyr :1 -resizeable
{{hc|/etc/systemd/nspawn/''my-container''.nspawn|<nowiki>
 
[Files]
 
Bind=/var/cache/pacman/pkg
 
</nowiki>}}
 
   
[[#コンテナごとに設定指定る]]を参照
+
その後、以下のオプションでコンテナを起動します。
   
  +
--setenv=DISPLAY=:1 --bind-ro<nowiki>=</nowiki>/tmp/.X11-unix/X1
=== ネットワーク ===
 
   
  +
他のバインドは必要ありません。
ネットワーク管理に [[systemd-networkd]] を使用して DNS に {{ic|systemd-resolved}} を使用する、インターネットに接続できる最も簡単な設定:
 
   
  +
状況によっては、コンテナ内で {{ic|1=DISPLAY=:1}} を手動で設定する必要があるかもしれません(主に {{ic|-b}} と併用する場合)
# systemctl enable --now systemd-networkd systemd-resolved
 
# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf # let systemd-resolved manage /etc/resolv.conf
 
   
  +
==== Firefox を起動する ====
上記の設定を使うには {{ic|-n}} スイッチを使って {{ic|systemd-nspawn}} を実行して、ホストに仮想イーサネットリンクを作成する必要があります。
 
   
  +
PID 1 として実行するには
{{ic|systemd-resolved}} を使わないでコンテナの {{ic|/etc/resolv.conf}} を手動で編集して DNS サーバーの IP アドレスを追加することも可能です。
 
   
  +
# systemd-nspawn --setenv=DISPLAY=:0 \
基本的な [[systemd-networkd]] のホストとコンテナの {{ic|.network}} ファイルは https://github.com/systemd/systemd/tree/master/network にあります。
 
  +
--setenv=XAUTHORITY=~/.Xauthority \
  +
--bind-ro=$HOME/.Xauthority:/root/.Xauthority \
  +
--bind=/tmp/.X11-unix \
  +
-D ~/containers/firefox \
  +
firefox
   
  +
{{Note|そのため、firefox は root ユーザーとして実行されますが、[[#非特権コンテナ]]を使用していない場合には独自のリスクが伴います。その場合、まずコンテナ内で[[ユーザーとグループ#ユーザーを追加する例|ユーザーを追加]]し、その後 ''systemd-nspawn'' の呼び出しで {{ic|--user <username>}} オプションを追加することができます。}}
もっと複雑なネットワークを設定する方法は、[[systemd-networkd#コンテナでの使用方法]]を見て下さい。
 
   
  +
あるいは、コンテナを起動して、例えば、[[systemd-networkd]] に仮想ネットワークインターフェイスを設定することもできます。
==== nsswitch.conf ====
 
   
  +
# systemd-nspawn --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
ホストからコンテナへの接続を楽にするために、コンテナの名前のローカル DNS 解決を有効にすることができます。{{ic|/etc/nsswitch.conf}} の {{ic|hosts:}} セクションに {{ic|mymachines}} を追加してください:
 
  +
--bind=/tmp/.X11-unix \
  +
-D ~/containers/firefox \
  +
--network-veth -b
   
  +
コンテナが起動したら、次のようにXorgバイナリを実行します:
hosts: files mymachines dns myhostname
 
   
  +
# systemd-run -M firefox --setenv=DISPLAY=:0 firefox
こうすると、ホスト上でホストネーム {{ic|foo}} の DNS ルックアップで {{ic|/etc/hosts}} が参照され、それからローカルコンテナの名前、上流の DNS などが参照されます。
 
   
==== ホストのネトワーを使用 ====
+
==== 3D グラフィックスアクセラレーション ====
   
  +
3Dグラフィックスアクセラレーションを有効にするためには、''.nspawn'' ファイルに以下の行を追加して、マウント {{ic|/dev/dri}} をコンテナにバインドする必要があるかもしれません。
{{ic|machinectl start MyContainer}} で起動したコンテナによって使用されるプライベートネットワークを無効化するには {{ic|systemctl edit systemd-nspawn@.service}} を実行して {{ic|systemd-nspawn@.service}} サービスファイルの設定を編集してください。{{ic|--network-veth}} パラメータを削除するように {{ic|1=ExecStart=}} オプションを設定します:
 
   
  +
Bind=/dev/dri
{{hc|/etc/systemd/system/systemd-nspawn@.service.d/override.conf|<nowiki>
 
  +
  +
この方法は [https://web.archive.org/web/20190925003151/https://patrickskiba.com/sysytemd-nspawn/2019/03/21/graphical-applications-in-systemd-nspawn.html patrickskiba.com] から引用しました。これにより、以下の問題が解決されます。
  +
  +
libGL error: MESA-LOADER: failed to retrieve device information
  +
libGL error: Version 4 or later of flush extension not found
  +
libGL error: failed to load driver: i915
  +
  +
{{ic|glxinfo}} または {{ic|glxgears}} を実行して、有効になっているか確認してください。
  +
  +
===== NVIDIA GPUs =====
  +
  +
コンテナ上にホストと同じバージョンの NVIDIA ドライバをインストールできない場合、ドライバライブラリファイルもバインドする必要がある場合があります。ホスト上で {{ic|pacman -Ql nvidia-utils}} を実行すると、含まれている全てのファイルを確認することができます。全てをコピーする必要はありません。以下の systemd override ファイルは、コンテナを {{ic|machinectl start ''container-name''}} で実行する際に必要なファイルを全てバインドします。
  +
  +
{{Accuracy|No reason to bind from {{ic|/usr/lib/}} into {{ic|/usr/lib/x86_64-linux-gnu/}}.}}
  +
  +
{{hc|/etc/systemd/system/systemd-nspawn@.service.d/nvidia-gpu.conf|2=
 
[Service]
 
[Service]
 
ExecStart=
 
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I
+
ExecStart=systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%i \
  +
--bind=/dev/dri \
</nowiki>}}
 
  +
--bind=/dev/shm \
  +
--bind=/dev/nvidia0 \
  +
--bind=/dev/nvidiactl \
  +
--bind=/dev/nvidia-modeset \
  +
--bind=/usr/bin/nvidia-bug-report.sh:/usr/bin/nvidia-bug-report.sh \
  +
--bind=/usr/bin/nvidia-cuda-mps-control:/usr/bin/nvidia-cuda-mps-control \
  +
--bind=/usr/bin/nvidia-cuda-mps-server:/usr/bin/nvidia-cuda-mps-server \
  +
--bind=/usr/bin/nvidia-debugdump:/usr/bin/nvidia-debugdump \
  +
--bind=/usr/bin/nvidia-modprobe:/usr/bin/nvidia-modprobe \
  +
--bind=/usr/bin/nvidia-ngx-updater:/usr/bin/nvidia-ngx-updater \
  +
--bind=/usr/bin/nvidia-persistenced:/usr/bin/nvidia-persistenced \
  +
--bind=/usr/bin/nvidia-powerd:/usr/bin/nvidia-powerd \
  +
--bind=/usr/bin/nvidia-sleep.sh:/usr/bin/nvidia-sleep.sh \
  +
--bind=/usr/bin/nvidia-smi:/usr/bin/nvidia-smi \
  +
--bind=/usr/bin/nvidia-xconfig:/usr/bin/nvidia-xconfig \
  +
--bind=/usr/lib/gbm/nvidia-drm_gbm.so:/usr/lib/x86_64-linux-gnu/gbm/nvidia-drm_gbm.so \
  +
--bind=/usr/lib/libEGL_nvidia.so:/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so \
  +
--bind=/usr/lib/libGLESv1_CM_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLESv1_CM_nvidia.so \
  +
--bind=/usr/lib/libGLESv2_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLESv2_nvidia.so \
  +
--bind=/usr/lib/libGLX_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so \
  +
--bind=/usr/lib/libcuda.so:/usr/lib/x86_64-linux-gnu/libcuda.so \
  +
--bind=/usr/lib/libnvcuvid.so:/usr/lib/x86_64-linux-gnu/libnvcuvid.so \
  +
--bind=/usr/lib/libnvidia-allocator.so:/usr/lib/x86_64-linux-gnu/libnvidia-allocator.so \
  +
--bind=/usr/lib/libnvidia-cfg.so:/usr/lib/x86_64-linux-gnu/libnvidia-cfg.so \
  +
--bind=/usr/lib/libnvidia-egl-gbm.so:/usr/lib/x86_64-linux-gnu/libnvidia-egl-gbm.so \
  +
--bind=/usr/lib/libnvidia-eglcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-eglcore.so \
  +
--bind=/usr/lib/libnvidia-encode.so:/usr/lib/x86_64-linux-gnu/libnvidia-encode.so \
  +
--bind=/usr/lib/libnvidia-fbc.so:/usr/lib/x86_64-linux-gnu/libnvidia-fbc.so \
  +
--bind=/usr/lib/libnvidia-glcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so \
  +
--bind=/usr/lib/libnvidia-glsi.so:/usr/lib/x86_64-linux-gnu/libnvidia-glsi.so \
  +
--bind=/usr/lib/libnvidia-glvkspirv.so:/usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so \
  +
--bind=/usr/lib/libnvidia-ml.so:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so \
  +
--bind=/usr/lib/libnvidia-ngx.so:/usr/lib/x86_64-linux-gnu/libnvidia-ngx.so \
  +
--bind=/usr/lib/libnvidia-opticalflow.so:/usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so \
  +
--bind=/usr/lib/libnvidia-ptxjitcompiler.so:/usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so \
  +
--bind=/usr/lib/libnvidia-rtcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-rtcore.so \
  +
--bind=/usr/lib/libnvidia-tls.so:/usr/lib/x86_64-linux-gnu/libnvidia-tls.so \
  +
--bind=/usr/lib/libnvidia-vulkan-producer.so:/usr/lib/x86_64-linux-gnu/libnvidia-vulkan-producer.so \
  +
--bind=/usr/lib/libnvoptix.so:/usr/lib/x86_64-linux-gnu/libnvoptix.so \
  +
--bind=/usr/lib/modprobe.d/nvidia-utils.conf:/usr/lib/x86_64-linux-gnu/modprobe.d/nvidia-utils.conf \
  +
--bind=/usr/lib/nvidia/wine/_nvngx.dll:/usr/lib/x86_64-linux-gnu/nvidia/wine/_nvngx.dll \
  +
--bind=/usr/lib/nvidia/wine/nvngx.dll:/usr/lib/x86_64-linux-gnu/nvidia/wine/nvngx.dll \
  +
--bind=/usr/lib/nvidia/xorg/libglxserver_nvidia.so:/usr/lib/x86_64-linux-gnu/nvidia/xorg/libglxserver_nvidia.so \
  +
--bind=/usr/lib/vdpau/libvdpau_nvidia.so:/usr/lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so \
  +
--bind=/usr/lib/xorg/modules/drivers/nvidia_drv.so:/usr/lib/x86_64-linux-gnu/xorg/modules/drivers/nvidia_drv.so \
  +
--bind=/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf:/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf \
  +
--bind=/usr/share/dbus-1/system.d/nvidia-dbus.conf:/usr/share/dbus-1/system.d/nvidia-dbus.conf \
  +
--bind=/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json:/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json \
  +
--bind=/usr/share/glvnd/egl_vendor.d/10_nvidia.json:/usr/share/glvnd/egl_vendor.d/10_nvidia.json \
  +
--bind=/usr/share/licenses/nvidia-utils/LICENSE:/usr/share/licenses/nvidia-utils/LICENSE \
  +
--bind=/usr/share/vulkan/icd.d/nvidia_icd.json:/usr/share/vulkan/icd.d/nvidia_icd.json \
  +
--bind=/usr/share/vulkan/implicit_layer.d/nvidia_layers.json:/usr/share/vulkan/implicit_layer.d/nvidia_layers.json \
  +
DeviceAllow=/dev/dri rw
  +
DeviceAllow=/dev/shm rw
  +
DeviceAllow=/dev/nvidia0 rw
  +
DeviceAllow=/dev/nvidiactl rw
  +
DeviceAllow=/dev/nvidia-modeset rw
  +
}}
   
  +
{{Note|ホスト上で NVIDIA ドライバをアップグレードするたびに、コンテナを再起動する必要があり、ライブラリを更新するためにコンテナ内で {{ic|ldconfig}} を実行する必要がある場合があります。}}
次に起動したコンテナはホストのネットワークを使用するようになります。
 
   
==== 仮想イーサネッインターイス ====
+
=== ホスルシステムにアクセス ===
   
  +
例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:
コンテナを {{ic|systemd-nspawn ... -n}} で起動した場合、systemd は自動的にホストとコンテナに仮想イーサネットインターフェイスを作成して、仮想イーサネットケーブルで接続します。
 
   
  +
# systemd-nspawn --bind=/var/cache/pacman/pkg
コンテナの名前が {{ic|foo}} ならば、仮想イーサネットインターフェイスのホストにおける名前は {{ic|ve-foo}} になり、コンテナではどんな場合でも名前は {{ic|host0}} です。
 
   
  +
詳しくは {{man|1|systemd-nspawn}} の {{ic|--bind}} と {{ic|--bind-ro}} を参照してください。
{{ic|ip link}} でインターフェイスを確認すると、インターフェイスの名前には {{ic|ve-foo@if2}} や {{ic|host0@if9}} のように接尾辞が付きます。{{ic|@ifN}} は実際はインターフェイスの名前には含まれていません。仮想イーサネットケーブルが他の端末に接続されていることを示すために {{ic|ip link}} によって情報が加えられています。
 
   
  +
ファイルを使ってコンテナごとにバインドを設定することもできます:
例えば、ホストの仮想イーサネットインターフェイス {{ic|ve-foo@if2}} がコンテナ {{ic|foo}} に接続、コンテナの中の2番目のネットワークインターフェイスに接続する場合、コンテナの中から {{ic|ip link}} を実行するとインデックス 2 が付きます。同じように、コンテナの {{ic|host0@if9}} という名前のインターフェイスはホストの9番目のインターフェイスに接続します。
 
   
  +
{{hc|/etc/systemd/nspawn/''my-container''.nspawn|<nowiki>
==== ネットワークブリッジを使用 ====
 
  +
[Files]
  +
Bind=/var/cache/pacman/pkg
  +
</nowiki>}}
   
  +
[[#コンテナごとに設定を指定する]]を参照。
ローカルネットワークの物理マシンのようにコンテナに IP アドレスを割り当てるためにホスト環境にネットワークブリッジを設定している場合 (詳しくは [[systemd-networkd#2つの別々な IP で DHCP を使う]]や [[systemd-networkd#固定 IP ネットワーク]]を参照)、{{ic|1=--network-bridge=''br0''}} オプションを使って systemd-nspawn から利用することができます。
 
   
 
=== systemd を使っていない環境で動作させる ===
 
=== systemd を使っていない環境で動作させる ===
   
 
[[Init#systemd-nspawn]] を見て下さい。
 
[[Init#systemd-nspawn]] を見て下さい。
 
=== コンテナごとに設定を指定する ===
 
 
全体設定を上書きすることなく各コンテナの設定を指定したい場合 (例: どれかひとつのコンテナにディレクトリをバインドする場合)、{{ic|.nspawn}} ファイルを使うことで設定できます [https://github.com/systemd/systemd/issues/3442#issuecomment-223837408]。{{man|5|systemd.nspawn}} を見てください [https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html]。
 
   
 
=== Btrfs のサブボリュームをコンテナのルートとして使う ===
 
=== Btrfs のサブボリュームをコンテナのルートとして使う ===
446行目: 558行目:
   
 
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。
 
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。
  +
  +
=== system-nspawn で docker を実行 ===
  +
  +
[[Docker]] 20.10 以降、''cgroups v2'' を有効にした非特権 ''systemd-nspawn'' コンテナ内で Docker コンテナを実行することが可能になりました(Arch Linux ではデフォルト)。これにより、cgroups やユーザー名前空間を無効にすることなくセキュリティ対策を損なうことなく行えます。これを行うには、{{ic|/etc/systemd/nspawn/myContainer.nspawn}} を編集し(存在しない場合は作成)、以下の設定を追加します。
  +
  +
{{hc|/etc/systemd/nspawn/myContainer.nspawn|<nowiki>
  +
[Exec]
  +
SystemCallFilter=add_key keyctl bpf
  +
</nowiki>}}
  +
  +
その後、コンテナ内で Docker はそのまま機能するはずです。
  +
  +
{{Note|上記の設定では、コンテナに ''add_key''、''keyctl''、および ''bpf'' といった名前空間化されていないシステムコールを公開しています。これはユーザー名前空間を完全に無効にする以前の方法と比較するとセキュリティリスクは大幅に低いものの、依然としてセキュリティリスクになり得ます。}}
  +
  +
''overlayfs'' はユーザー名前空間と互換性がなく、デフォルトでは ''systemd-nspawn'' 内で使用できません。そのため、Docker は非効率な ''vfs'' をストレージドライバーとして使用することになります。これはコンテナを開始するたびにイメージのコピーを作成します。これを回避するためには、ストレージドライバーとして ''fuse-overlayfs'' を使用する必要があります。これを行うためには、まずコンテナに ''fuse'' を公開する必要があります:
  +
  +
{{hc|/etc/systemd/nspawn/myContainer.nspawn|<nowiki>
  +
[Files]
  +
Bind=/dev/fuse
  +
</nowiki>}}
  +
  +
そして、コンテナがデバイスノードを読み書きできるように設定します:
  +
  +
# systemctl set-property systemd-nspawn@myContainer DeviceAllow='/dev/fuse rwm'
  +
  +
最後に、コンテナ内に {{Pkg|fuse-overlayfs}} パッケージをインストールします。すべての設定を有効にするには、コンテナを再起動する必要があります。
   
 
== トラブルシューティング ==
 
== トラブルシューティング ==
455行目: 593行目:
 
Login incorrect
 
Login incorrect
   
そして {{ic|journalctl}} が以下のように表示する場合:
+
そして、コンテナの [[journal]] が以下のように表示する場合:
   
 
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
 
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
   
  +
{{Accuracy|Files in {{ic|/usr/lib}} should not be edited by users, the change in {{ic|/usr/lib/tmpfiles.d/arch.conf}} will be lost when {{pkg|filesystem}} is upgraded.}}
コンテナのファイルシステム上にある {{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] を見てください。
 
   
  +
'''コンテナ'''ファイルシステム上の、{{ic|/etc/securetty}}[https://unix.stackexchange.com/questions/41840/effect-of-entries-in-etc-securetty/41939#41939] と {{ic|/usr/share/factory/etc/securetty}} を削除するか、'''コンテナ'''ファイイルシステム上の {{ic|/etc/securetty}} に必要な pty 端末デバイス({{ic|pts/0}} のような)を追加します。変更は、次の起動時に上書きされるため、{{ic|/etc/securetty}} のエントリを削除する必要があります。{{Bug|63236}} を参照。削除を選択した場合は、{{ic|/etc/pacman.conf}} の [[pacman#Skip files from being installed to system|NoExtract]] にそれらを追加し、再インストールされないようにします。{{Bug|45903}} を参照してください。
   
 
=== execv(...) failed: Permission denied ===
 
=== execv(...) failed: Permission denied ===
   
  +
{{ic|systemd-nspawn -bD ''/path/to/container''}} によってコンテナを起動 (またはコンテナ内で何かを実行) しようとすると、以下のようなエラーが発生します:
When trying to boot the container via {{ic|systemd-nspawn -bD ''/path/to/container''}} (or executing something in the container), and the following error comes up:
 
   
 
execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Permission denied
 
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が所有するファイルであっても実行は許可しません。
even though the permissions of the files in question (i.e. {{ic|/lib/systemd/systemd}}) are correct, this can be the result of having mounted the file system on which the container is stored as non-root user. For example, if you mount your disk manually with an entry in [[fstab]] that has the options {{ic|noauto,user,...}}, ''systemd-nspawn'' will not allow executing the files even if they are owned by root.
 
   
  +
=== TERM の端末タイプが間違っている (色が壊れている) ===
=== Terminal type in TERM is incorrect (broken colors) ===
 
   
  +
{{ic|machinectl login}} でコンテナにログインすると、コンテナ内の端末の色とキーストロークが壊れることがあります。これは、{{ic|TERM}} 環境変数の端末タイプが正しくないことが原因である可能性があります。環境変数はホストのシェルから継承されませんが、明示的に設定されていない限り、systemd ({{ic|vt220}}) で固定されたデフォルトに戻ります。設定するには、コンテナ内の {{ic|container-getty@.service}} サービス用のオーバーレイを作成して、{{ic|machinectl login}} の login getty を起動し、ログインしているホスト端末と一致する値を {{ic|TERM}} に設定してください。
When logging into the container via {{ic|machinectl login}}, the colors and keystrokes in the terminal within the container might be broken. This may be due to an incorrect terminal type in {{ic|TERM}} environment variable. The environment variable is not inherited from the shell on the host, but falls back to a default fixed in systemd ({{ic|vt220}}), unless explicitly configured. To configure, within the container create a configuration overlay for the {{ic|container-getty@.service}} systemd service that launches the login getty for {{ic|machinectl login}}, and set {{ic|TERM}} to the value that matches the host terminal you are logging in from:
 
   
 
{{hc|/etc/systemd/system/container-getty@.service.d/term.conf|2=
 
{{hc|/etc/systemd/system/container-getty@.service.d/term.conf|2=
479行目: 618行目:
 
}}
 
}}
   
Alternatively use {{ic|machinectl shell}}. It properly inherits the {{ic|TERM}} environment variable from the terminal.
+
もしくは、{{ic|machinectl shell}} を使用してください。端末から {{ic|TERM}} 環境変数を適切に継承します。
   
  +
=== コンテナ内へのNFS共有のマウント ===
=== Mounting a NFS share inside the container ===
 
   
  +
現時点(2019年6月)では利用できません。
Not possible at this time (June 2019).
 
 
=== コンテナのパッケージをアップグレードできない ===
 
 
ときどきコンテナの特定のパッケージがアップグレードできなくなることがあります。{{Pkg|filesystem}} などが特にそうです。原因は {{ic|/sys}} が読み取り専用でマウントされていることにあります。{{ic|mount -o remount,rw -t sysfs sysfs /sys}} を実行してディレクトリを読み書き可能で再マウントしてから、アップグレードを行なって、コンテナを再起動してください。
 
   
 
== 参照 ==
 
== 参照 ==
   
  +
* [[Getty#Nspawn コンソール|自動コンソールログイン]]
* [https://www.freedesktop.org/software/systemd/man/machinectl.html machinectl man ページ]
 
* [https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html systemd-nspawn man ページ]
 
 
* [https://lwn.net/Articles/572957/ Creating containers with systemd-nspawn]
 
* [https://lwn.net/Articles/572957/ Creating containers with systemd-nspawn]
* [https://www.youtube.com/results?search_query=systemd-nspawn&aq=f Lennart Pottering による systemd-nspawn のプレゼンテーション]
+
* [https://www.youtube.com/results?search_query=systemd-nspawn&aq=f Presentation by Lennart Poettering on systemd-nspawn]
* [http://dabase.com/e/12009/ Running Firefox in a systemd-nspawn container]
+
* [https://dabase.com/e/12009/ Running Firefox in a systemd-nspawn container]
  +
* [https://web.archive.org/web/20190925003151/https://patrickskiba.com/sysytemd-nspawn/2019/03/21/graphical-applications-in-systemd-nspawn.html Graphical applications in systemd-nspawn]
  +
  +
{{TranslationStatus|Systemd-nspawn|2024/4/18|798804}}

2024年4月24日 (水) 10:23時点における最新版

関連記事

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

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

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

systemd-nspawnLXCLibvirt よりも設定が簡単なツールです。

目次

インストール

systemd-nspawn は systemd の一部であり、systemd に含まれています。

サンプル

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

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

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

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

# pacstrap -K -c ~/MyContainer base [additional pkgs/groups]
ヒント: base パッケージは、linux カーネルパッケージに依存せず、コンテナにも対応しています。
ノート: pacstrap が利用できない異なるオペレーティングシステムから作成する場合、bootstrap tarball をコンテナイメージとして使用することができます。pacman キーリングはコンテナ内で初期化する必要があります。詳細は 既存の Linux からインストール#pacman キーリングの初期化 を参照してください。

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

# systemd-nspawn -D ~/MyContainer
# passwd
# logout
ヒント: Setting root password is optional. You can get a root shell in a booted container directly without having to log in by running machinectl shell root@MyContainer. See #machinectl.

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

# 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 はコンテナ内のオペレーティングシステムが systemd init を使用し (PID 1 として動作する)、systemd-nspawn がコンテナにインストールされている必要があります。この要件は、コンテナ環境に systemd-container パッケージをインストールすることで満たされます。systemd-container パッケージは dbus に依存しますが、dbus または dbus-broker パッケージがコンテナシステムにインストールされていることを確認してください。

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

# cd /var/lib/machines
# debootstrap --include=dbus-broker,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" には https://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

Fedora または AlmaLinux 環境の作成

dnf をインストールし、必要な Fedora リポジトリを追加するために /etc/dnf/dnf.conf ファイルを編集します。

/etc/dnf/dnf.conf
[fedora]                                                                                            
name=Fedora $releasever - $basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch
gpgkey=https://getfedora.org/static/fedora.gpg

[updates]                                                                                           
name=Fedora $releasever - $basearch - Updates
metalink=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch
gpgkey=https://getfedora.org/static/fedora.gpg

fedora.gpg ファイルには最新の Fedora リリース用の gpg キーが含まれています https://getfedora.org/security/ 。Fedora 37 の最小コンテナを設定するには:

# cd /var/lib/machines
# mkdir container-name
# dnf --releasever=37 --best --setopt=install_weak_deps=False --repo=fedora --repo=updates --installroot=/var/lib/machines/container-name install dhcp-client dnf fedora-release glibc glibc-langpack-en iputils less ncurses passwd systemd systemd-networkd systemd-resolved util-linux vim-default-editor
ノート: 異なる Fedora リリースをインストールしたい場合は、異なるリリースが 独自のパッケージ要件 を持つことを考慮してください。

btrfs ファイルシステムを使用している場合は、ディレクトリを作成する代わりにサブボリュームを作成してください。

AlmaLinux のようなエンタープライズ Linux 派生物は、デフォルトで三つのリポジトリが有効になっています。BaseOS は、すべてのインストールの基盤となるコアセットを含み、AppStream は追加アプリケーション、言語パッケージなどを含み、Extras は RHEL に含まれないパッケージを含んでいます。したがって、最小限のコンテナには /etc/dnf/dnf.conf に BaseOS リポジトリのみを追加する必要があります。

/etc/dnf/dnf.conf
[baseos]                                                                                            
name=AlmaLinux $releasever - BaseOS                                          
mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/baseos       
gpgkey=https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-$releasever

AlmaLinux 9 の最小コンテナを作成するには:

# dnf --repo=baseos --releasever=9 --best --installroot=/var/lib/machines/container-name --setopt=install_weak_deps=False install almalinux-release dhcp-client dnf glibc-langpack-en iproute iputils less passwd systemd vim-minimal

これにより、AlmaLinux 9 の最新マイナーバージョンがインストールされますが、特定のポイントリリースをインストールすることもできますが、その場合は gpgpkey エントリを手動で RPM-GPG-KEY-AlmaLinux-9 を指すように変更する必要があります。

Arch、Fedora、AlmaLinux のように、root パスワードを設定しない限り、root としてログインすることは許可されません。root パスワードを設定するには、-b オプションなしで systemd-nspawn を実行してください:

# systemd-nspawn -D /var/lib/machines/container-name passwd

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

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

管理

/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
ノート: machinectl は、コンテナ名が有効なホスト名であるように、ASCII 文字、数字、ハイフンのみで構成されていることを要求します。例えば、コンテナ名にアンダースコアが含まれている場合、それは単に認識されず、 machinectl start container_name を実行すると、エラー Invalid machine name container_name となります。詳しくは[2][3]を参照してください。

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

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

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

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

machinectl にはコンテナ(または仮想マシン)イメージとイメージ転送を管理するためのサブコマンドもあります。詳細については、machinectl(1) § Image Commands および、machinectl(1) § Image Transfer Commands を参照してください。2023Q1 時点で、machinectl(1) § EXAMPLES にある最初の 3 つの例はイメージ転送コマンドを示しています。machinectl(1) § FILES AND DIRECTORIES では、適切なイメージをどこで見つけるかについて説明しています。

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 も参照してください。

さらに、DHCP サーバー(systemd-networkd によって運用される)への着信接続用に ve-+ インターフェースの UDP ポート 67 を開く必要があります:

# iptables -A INPUT -i ve-+ -p udp -m udp --dport 67 -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 を意味します。

ノート: ホストがコンテナと通信できるようにするために、ホストに macvlan または ipvlan インターフェースを作成し、それをコンテナが使用している同じ物理インターフェースに接続し、その上でネットワーク接続を設定してください。仮想インターフェース名が systemd-nspawn によって作成された仮想インターフェースと衝突しないことを確認してください。systemd-networkd を使用した例については、systemd-networkd#MACVLAN bridge を参照してください。

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

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

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

ポートマッピング

プライベートネットワークが有効になっている場合、ホストの個々のポートは、-p/--port オプションを使用するか、または .nspawn ファイルの Port 設定を使用してコンテナのポートにマッピングすることができます。たとえば、ホストの TCP ポート 8000 をコンテナの TCP ポート 80 にマッピングするには:

/etc/systemd/nspawn/container-name.nspawn
[Network]
Port=tcp:8000:80

これは、nat テーブルに iptables ルールを発行することで機能しますが、filter テーブルの FORWARD チェインは、#仮想イーサネットリンクを使用するに示されているように手動で設定する必要があります。さらに、シンプルなステートフルファイアウォールに従った場合、ホストの wan_interface で転送されたポートへの新しい接続を許可するには、次のコマンドを実行してください:

# iptables -A FORWARD -i wan_interface -o ve-+ -p tcp --syn --dport 8000 -m conntrack --ctstate NEW -j ACCEPT
ノート:
  • systemd-nspawn は、ポートをマッピングする際に loopback インターフェイスを明示的に除外します。したがって、上記の例では、localhost:8000 はホストに接続し、コンテナには接続しません。他のインターフェイスへの接続のみがポートマッピングの対象となります。詳細は、[5] を参照してください。
  • ポートマッピングは IPv4 接続に対してのみ機能します。 [6]

ドメイン名前解決

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

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

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

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

ホスト上で systemd-resolved が実行される 2 番目のケースでは、コンテナがホストからのスタブ symlink ファイル /etc/resolv.conf を使用できるように systemd-nspawn がコンテナ内でも実行されることを期待します。そうでない場合、デフォルト値の auto はもはや機能しませんので、replace-* オプションのいずれかを使ってシンボリックリンクを置き換える必要があります。

ヒントとテクニック

シェル/init 以外のコマンドを実行する

systemd-nspawn(1) § Execution Options より。

" [オプション] --as-pid2 [呼び出し] シェルまたは指定されたプログラムを、PID 1(init)ではなくプロセス ID(PID)2 として使用します。[...] PID 1として正しく実行されるように変更されていない限り、コンテナ内で任意のコマンドを呼び出すにはこのモードを使用することが推奨されます。言い換えれば、このスイッチは、コマンドが init やシェルの実装を参照している場合を除き、ほとんどすべてのコマンドに使用すべきです。[...] このオプションは --boot と組み合わせることはできません。

非特権コンテナ

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

ノート: この機能には user_namespaces(7) が必要です。詳細については、Linux Containers#非特権コンテナのサポートを有効化 (任意) を参照してください。

これを行う最も簡単な方法は、-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) を参照。

X nesting/Xephyr を使用

X アプリケーションを実行し、共有 X デスクトップのリスクを回避するもう1つの簡単な方法は、X nesting を使用することです。 ここでの利点は、コンテナ内アプリケーションと非コンテナアプリケーションの間の相互作用を完全に回避し、異なる デスクトップ環境 または ウィンドウマネージャ を実行できることです。 欠点はパフォーマンスの低下と Xephyr を使用した場合のハードウェアアクセラレーションの欠如です。

Xephyr をコンテナの外で起動するには以下の方法があります。

# Xephyr :1 -resizeable

その後、以下のオプションでコンテナを起動します。

--setenv=DISPLAY=:1 --bind-ro=/tmp/.X11-unix/X1

他のバインドは必要ありません。

状況によっては、コンテナ内で DISPLAY=:1 を手動で設定する必要があるかもしれません(主に -b と併用する場合)

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
ノート: そのため、firefox は root ユーザーとして実行されますが、#非特権コンテナを使用していない場合には独自のリスクが伴います。その場合、まずコンテナ内でユーザーを追加し、その後 systemd-nspawn の呼び出しで --user <username> オプションを追加することができます。

あるいは、コンテナを起動して、例えば、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

3D グラフィックスアクセラレーション

3Dグラフィックスアクセラレーションを有効にするためには、.nspawn ファイルに以下の行を追加して、マウント /dev/dri をコンテナにバインドする必要があるかもしれません。

Bind=/dev/dri

この方法は patrickskiba.com から引用しました。これにより、以下の問題が解決されます。

libGL error: MESA-LOADER: failed to retrieve device information
libGL error: Version 4 or later of flush extension not found
libGL error: failed to load driver: i915

glxinfo または glxgears を実行して、有効になっているか確認してください。

NVIDIA GPUs

コンテナ上にホストと同じバージョンの NVIDIA ドライバをインストールできない場合、ドライバライブラリファイルもバインドする必要がある場合があります。ホスト上で pacman -Ql nvidia-utils を実行すると、含まれている全てのファイルを確認することができます。全てをコピーする必要はありません。以下の systemd override ファイルは、コンテナを machinectl start container-name で実行する際に必要なファイルを全てバインドします。

この記事またはセクションの正確性には問題があります。
理由: No reason to bind from /usr/lib/ into /usr/lib/x86_64-linux-gnu/. (議論: トーク:Systemd-nspawn#)
/etc/systemd/system/systemd-nspawn@.service.d/nvidia-gpu.conf
[Service]
ExecStart=
ExecStart=systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%i \
--bind=/dev/dri \
--bind=/dev/shm \
--bind=/dev/nvidia0 \
--bind=/dev/nvidiactl \
--bind=/dev/nvidia-modeset \
--bind=/usr/bin/nvidia-bug-report.sh:/usr/bin/nvidia-bug-report.sh \
--bind=/usr/bin/nvidia-cuda-mps-control:/usr/bin/nvidia-cuda-mps-control \
--bind=/usr/bin/nvidia-cuda-mps-server:/usr/bin/nvidia-cuda-mps-server \
--bind=/usr/bin/nvidia-debugdump:/usr/bin/nvidia-debugdump \
--bind=/usr/bin/nvidia-modprobe:/usr/bin/nvidia-modprobe \
--bind=/usr/bin/nvidia-ngx-updater:/usr/bin/nvidia-ngx-updater \
--bind=/usr/bin/nvidia-persistenced:/usr/bin/nvidia-persistenced \
--bind=/usr/bin/nvidia-powerd:/usr/bin/nvidia-powerd \
--bind=/usr/bin/nvidia-sleep.sh:/usr/bin/nvidia-sleep.sh \
--bind=/usr/bin/nvidia-smi:/usr/bin/nvidia-smi \
--bind=/usr/bin/nvidia-xconfig:/usr/bin/nvidia-xconfig \
--bind=/usr/lib/gbm/nvidia-drm_gbm.so:/usr/lib/x86_64-linux-gnu/gbm/nvidia-drm_gbm.so \
--bind=/usr/lib/libEGL_nvidia.so:/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so \
--bind=/usr/lib/libGLESv1_CM_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLESv1_CM_nvidia.so \
--bind=/usr/lib/libGLESv2_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLESv2_nvidia.so \
--bind=/usr/lib/libGLX_nvidia.so:/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so \
--bind=/usr/lib/libcuda.so:/usr/lib/x86_64-linux-gnu/libcuda.so \
--bind=/usr/lib/libnvcuvid.so:/usr/lib/x86_64-linux-gnu/libnvcuvid.so \
--bind=/usr/lib/libnvidia-allocator.so:/usr/lib/x86_64-linux-gnu/libnvidia-allocator.so \
--bind=/usr/lib/libnvidia-cfg.so:/usr/lib/x86_64-linux-gnu/libnvidia-cfg.so \
--bind=/usr/lib/libnvidia-egl-gbm.so:/usr/lib/x86_64-linux-gnu/libnvidia-egl-gbm.so \
--bind=/usr/lib/libnvidia-eglcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-eglcore.so \
--bind=/usr/lib/libnvidia-encode.so:/usr/lib/x86_64-linux-gnu/libnvidia-encode.so \
--bind=/usr/lib/libnvidia-fbc.so:/usr/lib/x86_64-linux-gnu/libnvidia-fbc.so \
--bind=/usr/lib/libnvidia-glcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so \
--bind=/usr/lib/libnvidia-glsi.so:/usr/lib/x86_64-linux-gnu/libnvidia-glsi.so \
--bind=/usr/lib/libnvidia-glvkspirv.so:/usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so \
--bind=/usr/lib/libnvidia-ml.so:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so \
--bind=/usr/lib/libnvidia-ngx.so:/usr/lib/x86_64-linux-gnu/libnvidia-ngx.so \
--bind=/usr/lib/libnvidia-opticalflow.so:/usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so \
--bind=/usr/lib/libnvidia-ptxjitcompiler.so:/usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so \
--bind=/usr/lib/libnvidia-rtcore.so:/usr/lib/x86_64-linux-gnu/libnvidia-rtcore.so \
--bind=/usr/lib/libnvidia-tls.so:/usr/lib/x86_64-linux-gnu/libnvidia-tls.so \
--bind=/usr/lib/libnvidia-vulkan-producer.so:/usr/lib/x86_64-linux-gnu/libnvidia-vulkan-producer.so \
--bind=/usr/lib/libnvoptix.so:/usr/lib/x86_64-linux-gnu/libnvoptix.so \
--bind=/usr/lib/modprobe.d/nvidia-utils.conf:/usr/lib/x86_64-linux-gnu/modprobe.d/nvidia-utils.conf \
--bind=/usr/lib/nvidia/wine/_nvngx.dll:/usr/lib/x86_64-linux-gnu/nvidia/wine/_nvngx.dll \
--bind=/usr/lib/nvidia/wine/nvngx.dll:/usr/lib/x86_64-linux-gnu/nvidia/wine/nvngx.dll \
--bind=/usr/lib/nvidia/xorg/libglxserver_nvidia.so:/usr/lib/x86_64-linux-gnu/nvidia/xorg/libglxserver_nvidia.so \
--bind=/usr/lib/vdpau/libvdpau_nvidia.so:/usr/lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so \
--bind=/usr/lib/xorg/modules/drivers/nvidia_drv.so:/usr/lib/x86_64-linux-gnu/xorg/modules/drivers/nvidia_drv.so \
--bind=/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf:/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf \
--bind=/usr/share/dbus-1/system.d/nvidia-dbus.conf:/usr/share/dbus-1/system.d/nvidia-dbus.conf \
--bind=/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json:/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json \
--bind=/usr/share/glvnd/egl_vendor.d/10_nvidia.json:/usr/share/glvnd/egl_vendor.d/10_nvidia.json \
--bind=/usr/share/licenses/nvidia-utils/LICENSE:/usr/share/licenses/nvidia-utils/LICENSE \
--bind=/usr/share/vulkan/icd.d/nvidia_icd.json:/usr/share/vulkan/icd.d/nvidia_icd.json \
--bind=/usr/share/vulkan/implicit_layer.d/nvidia_layers.json:/usr/share/vulkan/implicit_layer.d/nvidia_layers.json \
DeviceAllow=/dev/dri rw
DeviceAllow=/dev/shm rw
DeviceAllow=/dev/nvidia0 rw
DeviceAllow=/dev/nvidiactl rw
DeviceAllow=/dev/nvidia-modeset rw
ノート: ホスト上で NVIDIA ドライバをアップグレードするたびに、コンテナを再起動する必要があり、ライブラリを更新するためにコンテナ内で ldconfig を実行する必要がある場合があります。

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

例えばホストとコンテナの両方が 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 20.10 以降、cgroups v2 を有効にした非特権 systemd-nspawn コンテナ内で Docker コンテナを実行することが可能になりました(Arch Linux ではデフォルト)。これにより、cgroups やユーザー名前空間を無効にすることなくセキュリティ対策を損なうことなく行えます。これを行うには、/etc/systemd/nspawn/myContainer.nspawn を編集し(存在しない場合は作成)、以下の設定を追加します。

/etc/systemd/nspawn/myContainer.nspawn
[Exec]
SystemCallFilter=add_key keyctl bpf

その後、コンテナ内で Docker はそのまま機能するはずです。

ノート: 上記の設定では、コンテナに add_keykeyctl、および bpf といった名前空間化されていないシステムコールを公開しています。これはユーザー名前空間を完全に無効にする以前の方法と比較するとセキュリティリスクは大幅に低いものの、依然としてセキュリティリスクになり得ます。

overlayfs はユーザー名前空間と互換性がなく、デフォルトでは systemd-nspawn 内で使用できません。そのため、Docker は非効率な vfs をストレージドライバーとして使用することになります。これはコンテナを開始するたびにイメージのコピーを作成します。これを回避するためには、ストレージドライバーとして fuse-overlayfs を使用する必要があります。これを行うためには、まずコンテナに fuse を公開する必要があります:

/etc/systemd/nspawn/myContainer.nspawn
[Files]
Bind=/dev/fuse

そして、コンテナがデバイスノードを読み書きできるように設定します:

# systemctl set-property systemd-nspawn@myContainer DeviceAllow='/dev/fuse rwm'

最後に、コンテナ内に fuse-overlayfs パッケージをインストールします。すべての設定を有効にするには、コンテナを再起動する必要があります。

トラブルシューティング

root ログインが失敗する

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

arch-nspawn login: root
Login incorrect

そして、コンテナの journal が以下のように表示する場合:

pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
この記事またはセクションの正確性には問題があります。
理由: Files in /usr/lib should not be edited by users, the change in /usr/lib/tmpfiles.d/arch.conf will be lost when filesystem is upgraded. (議論: トーク:Systemd-nspawn#)

コンテナファイルシステム上の、/etc/securetty[7]/usr/share/factory/etc/securetty を削除するか、コンテナファイイルシステム上の /etc/securetty に必要な pty 端末デバイス(pts/0 のような)を追加します。変更は、次の起動時に上書きされるため、/etc/securetty のエントリを削除する必要があります。FS#63236 を参照。削除を選択した場合は、/etc/pacman.confNoExtract にそれらを追加し、再インストールされないようにします。FS#45903 を参照してください。

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月)では利用できません。

参照

翻訳ステータス: このページは en:Systemd-nspawn の翻訳バージョンです。最後の翻訳日は 2024/4/18 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。