「Linux コンテナ」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎NAT ブリッジの使用: 不自然な読点の削除)
 
(5人の利用者による、間の30版が非表示)
1行目: 1行目:
[[Category:セキュリティ]]
 
 
[[Category:仮想化]]
 
[[Category:仮想化]]
  +
[[Category:サンドボックス]]
 
[[en:Linux Containers]]
 
[[en:Linux Containers]]
 
[[pt:Linux Containers]]
 
[[pt:Linux Containers]]
 
{{Related articles start}}
 
{{Related articles start}}
{{Related4|AirVPN}}
 
 
{{Related|Cgroups}}
 
{{Related|Cgroups}}
 
{{Related|Docker}}
 
{{Related|Docker}}
{{Related4|OpenVPN}}
+
{{Related|Incus}}
  +
{{Related|Linux コンテナ/VPN の使用}}
{{Related4|OpenVPN in Linux containers}}
 
  +
{{Related|LXD}}
  +
{{Related|podman}}
 
{{Related|systemd-nspawn}}
 
{{Related|systemd-nspawn}}
 
{{Related articles end}}
 
{{Related articles end}}
   
 
'''LinuX Containers''' ('''LXC''') はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる [[cgroups]] 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。
 
'''LinuX Containers''' ('''LXC''') はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる [[cgroups]] 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。
  +
  +
[[Incus]] や [[LXD]] は LXC のマネージャーとして使用できます。このページでは、LXC を直接使用する方法について説明します
  +
  +
コンテナを使用する代替手段としては [[systemd-nspawn]]、[[docker]]、[[podman]] があります。
  +
  +
== 特権コンテナと非特権コンテナ ==
  +
  +
LXC は特権または非特権で動作するように設定することができます。
  +
  +
一般的に、非特権コンテナは特権コンテナよりも安全だとされています [https://www.stgraber.org/2014/01/17/lxc-1-0-unprivileged-containers]。非特権コンテナでは分離の程度が原理上増すからです。非特権コンテナではコンテナの root の UID をホストの root 以外の UID にマッピングすることで、コンテナの中からホスト環境に影響を及ぼすことを難しくします。たとえ攻撃者がコンテナから脱獄しても、ホスト側では攻撃者に権限がありません。
  +
  +
現在 Arch のパッケージでは特権コンテナは最初からサポートしています。非特権コンテナはカーネル設定を行わないと利用できません。Arch の {{pkg|linux}} カーネルでは通常ユーザーでユーザー名前空間が無効になっているためです。この記事では特権・非特権両方のコンテナの情報を載せていますが、非特権を使うには設定が必要です。
  +
  +
=== 非特権コンテナの例 ===
  +
  +
UID マッピングの能力を説明するために、非特権コンテナで以下のコマンドを実行したときの出力を考えてみましょう。{{ic|ps}} の出力でコンテナ化されたプロセスの所有者が同じくコンテナ化された root ユーザーとなっていることが確認できます:
  +
  +
[root@unprivileged_container /]# ps -ef | head -n 5
  +
UID PID PPID C STIME TTY TIME CMD
  +
root 1 0 0 17:49 ? 00:00:00 /sbin/init
  +
root 14 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-journald
  +
dbus 25 1 0 17:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
  +
systemd+ 26 1 0 17:49 ? 00:00:00 /usr/lib/systemd/systemd-networkd
  +
  +
ホスト側では、コンテナ化された root プロセスはマッピングされたユーザー (ID>100000) で動作します。ホストの root ユーザーではありません:
  +
[root@host /]# lxc-info -Ssip --name sandbox
  +
State: RUNNING
  +
PID: 26204
  +
CPU use: 10.51 seconds
  +
BlkIO use: 244.00 KiB
  +
Memory use: 13.09 MiB
  +
KMem use: 7.21 MiB
  +
  +
[root@host /]# ps -ef | grep 26204 | head -n 5
  +
UID PID PPID C STIME TTY TIME CMD
  +
100000 26204 26200 0 12:49 ? 00:00:00 /sbin/init
  +
100000 26256 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-journald
  +
100081 26282 26204 0 12:49 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
  +
100000 26284 26204 0 12:49 ? 00:00:00 /usr/lib/systemd/systemd-logind
   
 
== セットアップ ==
 
== セットアップ ==
 
=== 必要なソフトウェア ===
 
=== 必要なソフトウェア ===
[[公式リポジトリ]]から {{Pkg|lxc}} と {{Pkg|arch-install-scripts}} をインストールしてください。
+
{{Pkg|lxc}} と {{Pkg|arch-install-scripts}} パッケージをインストールしてください。
   
  +
==== 非特権コンテナのサポートを有効化 (任意) ====
使用中のカーネルがコンテナを実行できるように正しく設定されているか確認:
 
$ lxc-checkconfig
 
   
  +
{{ic|/etc/lxc/default.conf}} を変更して次の行を含めます:
セキュリティに配慮して、デフォルトの Arch カーネルでは、非特権ユーザーではコンテナを実行できないようになっています。そのため、上記のコマンドを実行すると "User namespaces" の状態が '''missing''' になっているのが確認できます。詳しくは {{Bug|36969}} を見て下さい。
 
   
  +
lxc.idmap = u 0 100000 65536
=== ホストネットワークの設定 ===
 
  +
lxc.idmap = g 0 100000 65536
LXC は様々なタイプの仮想化ネットワークをサポートしています。仮想ネットワークではほとんどの場合、ホスト側にブリッジデバイスが必要になります。以下で示しているブリッジの作成例に限られることはありません。例証として見て下さい。他のプログラムを使って同じようにネットワークを構築することも可能です。
 
   
  +
言い換えると、65536 個の連続した uid の範囲をマップします。コンテナ側の uid 0 (ホストの観点からは uid 100000 になります) から、ホストが uid 165535 として認識するコンテナ側の uid 65535 までです。同じマッピングを gid に適用します。
{{Note|Select only '''one''' of the methods below to implement the bridge on the host!}}
 
   
  +
{{ic|/etc/subuid}} と {{ic|/etc/subgid}} の両方を作成して、コンテナを実行できる各ユーザーのコンテナ化された uid/gid ペアへのマッピングを含めます。以下の例は、単純に root ユーザー (および [[systemd]] システムユニット) を対象としています:
==== netctl だけを使用する例 ====
 
{{Pkg|netctl}} は[[公式リポジトリ]]からインストールすることができます。ブリッジのテンプレートは {{ic|/etc/netctl/examples}} に存在します。ホストネットワークのハードウェアの仕様やホストネットワークの IP の範囲にあわせて編集するようにしてください。以下2つのブリッジの設定例を記載していますが、片方は dhcp を使っており、もう片方は固定 IP で設定しています。
 
   
{{hc|1=/etc/netctl/lxcbridge|2=
+
{{hc|/etc/subuid|
  +
root:100000:65536
Description="LXC bridge"
 
  +
}}
Interface=br0
 
Connection=bridge
 
BindsToInterfaces=('eno1')
 
IP=dhcp
 
SkipForwardingDelay=yes}}
 
   
{{hc|1=/etc/netctl/lxcbridge|2=
+
{{hc|/etc/subgid|
  +
root:100000:65536
Description="LXC bridge"
 
  +
}}
Interface=br0
 
Connection=bridge
 
BindsToInterfaces=('eno1')
 
IP=static
 
Address=192.168.0.2/24
 
Gateway='192.168.0.1'
 
DNS=('192.168.0.1')}}
 
   
  +
さらに、非特権ユーザーとして非特権コンテナを実行することは、事前に [[cgroup]] を委任した場合にのみ機能します (この制限は、liblxc ではなく cgroup2 委任モデルによって強制されます) 次の ''systemd'' コマンドを使用して cgroup を委任します ([https://linuxcontainers.org/lxc/getting-started/#creating-unprivileged-containers-as-a-user LXC - Getting started: Creating unprivileged containers as a user]):
ブリッジを開始する前に、ホスト側の既存のネットワークインターフェイスを[[systemd#ユニットを使う|無効化]]してブリッジで置き換えるようにしてください。無効化するサービスはどうやってネットワークを設定していたかによって変わってきます。基本的なネットワーク設定については[[ビギナーズガイド#ネットワークの設定]]に例があります。
 
   
  +
$ systemd-run --unit=''myshell'' --user --scope -p "Delegate=yes" lxc-start ''container_name''
netctl を使ってアダプタを管理していた場合は、switch-to で切り替えて下さい:
 
# netctl switch-to lxcbridge
 
# netctl enable lxcbridge
 
   
  +
これは他の lxc コマンドでも同様に機能します。
次に進む前にホストからネットワークにちゃんと接続されているか確認してください。ping を実行することで確認できます:
 
$ ping -c 1 www.google.com
 
   
  +
{{hc|/etc/systemd/system/user@.service.d/delegate.conf|2=
==== bridge-utils だけを使用する例 ====
 
  +
[Service]
Placeholder for someone using this setup.
 
  +
Delegate=cpu cpuset io memory pids
  +
}}
   
  +
===== linux-hardened などカスタムカーネル上の特権のないコンテナ =====
==== 無線ネットワークの例 ====
 
   
  +
{{Pkg|linux-hardened}} またはカスタム カーネル上で ''非特権'' コンテナを実行したいユーザーは、いくつかの追加のセットアップ手順を完了する必要があります。
無線ネットワークを直接ブリッジすることはできません。他の方法を使う必要があります。最初に、先の例と同じようにブリッジを作成しますが、インターフェイスは何も定義しないようにしておきます (コンテナ自身の仮想インターフェイスは自動的に定義されます)。ブリッジに固定 IP アドレスを割り当てますがゲートウェイは割り当てないようにしてください。
 
   
  +
まず、ユーザー名前空間をサポートするカーネル ({{ic|CONFIG_USER_NS}} を備えたカーネル) が必要です。すべての Arch Linux カーネルは {{ic|CONFIG_USER_NS}} をサポートしています。ただし、より一般的なセキュリティ上の懸念により、{{Pkg|linux-hardened}} カーネルは、''root'' ユーザーに対してのみ有効になったユーザー名前空間とともに出荷されます。そこに ''非特権'' コンテナを作成するには 2 つのオプションがあります:
iptables を使って NAT を行うようにホストを設定:
 
   
  +
*特権のないコンテナは ''root'' としてのみ起動してください。また、現在の値が {{ic|0}} の場合、[[sysctl]] 設定 {{ic|user.max_user_namespaces}} に環境に合わせて正の値を指定します (これにより、{{ic|lxc info --show-log ''container_name''}} で見られる {{ic|Failed to clone process in new user namespace}} というエラーが修正されます)
# iptables -A POSTROUTING -o <var>wlp3s0</var> -j MASQUERADE
 
  +
*{{Pkg|linux-hardened}} および {{ic|lxd 5.0.0}} では、{{ic|root:1000000:65536}} の範囲を使用するように {{ic|/etc/subuid}} および {{ic|/etc/subgid}} を設定する必要がある場合があります。'''最初''' のコンテナを特権付きで起動する必要がある場合もあります。これにより、{{ic|newuidmap failed to write mapping "newuidmap: uid range [0-1000000000) -> [1000000-1001000000) not allowed" エラーが修正されます。}}
  +
* ''sysctl'' 設定 {{ic|kernel.unprivileged_userns_clone}} を有効にして、通常のユーザーが特権のないコンテナを実行できるようにします。これは、root として {{ic|1=sysctl kernel.unprivileged_userns_clone=1}} を実行することで現在のセッションに対して行うことができ、また、{{man|5|sysctl.d}} を使用して永続化することもできます。
   
  +
=== ホストネットワーク設定 ===
{{ic|<var>wlp3s0</var>}} は無線インターフェイスの名前に置き換えて下さい。パケット転送はデフォルトでは無効化されているので、[[インターネット共有#パケット転送の有効化|カーネルパラメータを変更]]して有効にします:
 
   
  +
LXC は、さまざまな仮想ネットワークタイプとデバイスをサポートします ({{man|5|lxc.container.conf}} を参照) ホスト上のブリッジデバイスは、このセクションで説明するほとんどのタイプの仮想ネットワークに必要です。
# echo 1 > /proc/sys/net/ipv4/ip_forward
 
   
  +
考慮すべき主な設定がいくつかあります。
再起動するとパラメータがリセットされてしまうので {{ic|/etc/sysctl.d}} に conf ファイルを追加するようにしてください ([[インターネット共有#パケット転送の有効化]]の警告を見て下さい)。
 
  +
# ホストブリッジ
  +
# NAT ブリッジ
   
  +
ホストブリッジでは、ホストのネットワークマネージャーが共有ブリッジインターフェイスを管理する必要があります。ホストとすべての lxc には、同じネットワーク内の IP アドレスが割り当てられます (たとえば、192.168.1.x) Web サーバーや VPN サーバーなど、ネットワークに公開されたサービスをコンテナ化することが目的の場合、これはより単純になる可能性があります。ユーザーは、lxc を物理 LAN 上の単なる別の PC と考えることができ、それに応じてルーター内の必要なポートを転送できます。追加されたシンプルさは、追加の脅威ベクトルと考えることもできます。WAN トラフィックが lxc に転送される場合、別の範囲で lxc を実行すると、脅威の表面が小さくなります。
残りの作業はほとんど同じですが、コンテナ側では、ゲートウェイはホストの IP アドレスを設定するようにしてください (上記の例では、192.168.0.2 になります)。{{ic|/var/lib/lxc/''container_name''/config}} で指定することができます (下のセクションを見て下さい)。
 
  +
  +
NAT ブリッジでは、ホストのネットワークマネージャーがブリッジを管理する必要はありません。{{pkg|lxc}} には、{{ic|lxcbr0}} という NAT ブリッジを作成する {{ic|lxc-net}} が同梱されています。NAT ブリッジは、ホストのイーサネット デバイスや物理ネットワークにブリッジされていないプライベート ネットワークを備えたスタンドアロンブリッジです。ホスト内にプライベートサブネットとして存在します。
  +
  +
==== ホストブリッジの使用 ====
  +
  +
[[ネットワークブリッジ]] を参照してください。
  +
  +
==== NAT ブリッジの使用 ====
  +
  +
{{pkg|dnsmasq}} を [[インストール]] して下さい、これは {{ic|lxc-net}} の依存関係です。ブリッジを開始する前に、まずブリッジの設定ファイルを作成します:
  +
  +
{{hc|/etc/default/lxc-net|
  +
2=# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
  +
# containers. Set to "false" if you'll use virbr0 or another existing
  +
# bridge, or mavlan to your host's NIC.
  +
USE_LXC_BRIDGE="true"
  +
  +
# If you change the LXC_BRIDGE to something other than lxcbr0, then
  +
# you will also need to update your /etc/lxc/default.conf as well as the
  +
# configuration (/var/lib/lxc/<container>/config) for any containers
  +
# already created using the default config to reflect the new bridge
  +
# name.
  +
# If you have the dnsmasq daemon installed, you'll also have to update
  +
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
  +
LXC_BRIDGE="lxcbr0"
  +
LXC_ADDR="10.0.3.1"
  +
LXC_NETMASK="255.255.255.0"
  +
LXC_NETWORK="10.0.3.0/24"
  +
LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
  +
LXC_DHCP_MAX="253"
  +
# Uncomment the next line if you'd like to use a conf-file for the lxcbr0
  +
# dnsmasq. For instance, you can use 'dhcp-host=mail1,10.0.3.100' to have
  +
# container 'mail1' always get ip address 10.0.3.100.
  +
#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf
  +
  +
# Uncomment the next line if you want lxcbr0's dnsmasq to resolve the .lxc
  +
# domain. You can then add "server=/lxc/10.0.3.1' (or your actual $LXC_ADDR)
  +
# to your system dnsmasq configuration file (normally /etc/dnsmasq.conf,
  +
# or /etc/NetworkManager/dnsmasq.d/lxc.conf on systems that use NetworkManager).
  +
# Once these changes are made, restart the lxc-net and network-manager services.
  +
# 'container1.lxc' will then resolve on your host.
  +
#LXC_DOMAIN="lxc"
  +
}}
  +
  +
{{Tip|ブリッジの IP 範囲がローカルネットワークに干渉しないことを確認してください。}}
  +
  +
次に、コンテナがブリッジを使用するように LXC コンテナテンプレートを変更する必要があります。
  +
  +
{{hc|/etc/lxc/default.conf|
  +
2=lxc.net.0.type = veth
  +
lxc.net.0.link = lxcbr0
  +
lxc.net.0.flags = up
  +
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
  +
}}
  +
  +
Optionally create a configuration file to manually define the IP address of any containers:
  +
{{hc|/etc/lxc/dnsmasq.conf|
  +
2=dhcp-host=playtime,10.0.3.100
  +
}}
  +
  +
{{ic|lxc-net.service}} を [[起動]]/[[有効化]] してブリッジ インターフェイスを作成します。
  +
  +
===== ファイアウォールの考慮事項 =====
  +
  +
ホストマシンが実行しているファイアウォールによっては、{{ic|lxcbr0}} からホストへの受信パケットと、{{ic|lxcbr0}} からの送信パケットがホストを経由して他のネットワークに到達することを許可する必要がある場合があります。これをテストするには、IP 割り当てに DHCP を使用するように設定されたコンテナを起動して、{{ic|lxc-net}} がコンテナに IP アドレスを割り当てることができるかどうかを確認してください ({{ic|lxc-ls -f}} IP が割り当てられていない場合は、ホストのポリシーを調整する必要があります。
  +
  +
{{pkg|ufw}} のユーザーは、次の [https://discuss.linuxcontainers.org/t/lxd-bridge-doesnt-work-with-ipv4-and-ufw-with-nftables/10034/17 2 行] を実行するだけです。これを有効にするには:
  +
# ufw allow in on lxcbr0
  +
# ufw route allow in on lxcbr0
  +
  +
あるいは、{{pkg|nftables}} のユーザーは、{{ic|/etc/nftables.conf}} を変更できます (そして、{{ic|nft -f /etc/nftables.conf}} で再ロードします。設定が正しいかどうかを確認してください) {{ic|nft -cf /etc/nftables.conf}} これでコンテナがインターネットにアクセスできるようになります ({{ic|"eth0"}} を、インターネットにアクセスできるシステム上のデバイスに置き換えます。 {{ic|ip link}} を使用して既存のデバイスをリストします):
  +
  +
{{hc|/etc/nftables.conf|
  +
table inet filter {
  +
chain input {
  +
...
  +
iifname "lxcbr0" accept comment "Allow lxc containers"
  +
  +
pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited
  +
counter
  +
}
  +
chain forward {
  +
...
  +
iifname "lxcbr0" oifname "eth0" accept comment "Allow forwarding from lxcbr0 to eth0"
  +
iifname "eth0" oifname "lxcbr0" accept comment "Allow forwarding from eth0 to lxcbr0"
  +
}
  +
}
  +
}}
  +
  +
さらに、コンテナーは 10.0.3.x サブネット上で実行されているため、ssh、httpd などのサービスへの外部アクセスは lxc にアクティブに転送される必要があります。原則として、ホスト上のファイアウォールは、コンテナ上の予期されるポートで受信トラフィックを転送する必要があります。
  +
  +
====== iptables ルールの例 ======
  +
  +
このルールの目的は、lxc への ssh トラフィックを許可することです:
  +
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2221 -j DNAT --to-destination 10.0.3.100:22
  +
  +
このルールは、ポート 2221 から発信される tcp トラフィックをポート 22 の lxc の IP アドレスに転送します。
  +
{{Note|ホスト上で 2221/tcp のトラフィックを許可し、lxc 上で 22/tcp のトラフィックを許可するようにしてください。}}
  +
  +
LAN 上の別の PC からコンテナーに ssh 接続するには、ポート 2221 でホストに ssh 接続する必要があります。その後、ホストはそのトラフィックをコンテナに転送します。
  +
  +
$ ssh -p 2221 host.lan
  +
  +
====== ufw ルールの例 ======
  +
  +
{{pkg|ufw}} を使用する場合は、これを永続化するために、{{ic|/etc/ufw/before.rules}} の最後に次の行を追加します:
  +
  +
{{hc|/etc/ufw/before.rules|
  +
  +
*nat
  +
:PREROUTING ACCEPT [0:0]
  +
-A PREROUTING -i eth0 -p tcp --dport 2221 -j DNAT --to-destination 10.0.3.100:22
  +
COMMIT
  +
}}
  +
  +
===== 非 root ユーザーとしてコンテナを実行する =====
  +
  +
非 root ユーザーとしてコンテナーを作成して起動するには、追加の構成を適用する必要があります。
  +
  +
{{ic|/etc/lxc/lxc-usernet}} にユーザーネットファイルを作成します。{{man|5|lxc-usernet}} によると、1 行あたりのエントリは次のとおりです。
  +
  +
user type bridge number
  +
  +
コンテナを作成する必要があるユーザーを使用してファイルを設定します。ブリッジは、{{ic|/etc/default/lxc-net}} で定義されているものと同じになります。
  +
  +
{{ic|/etc/lxc/default.conf}} のコピーが、非 root ユーザーのホームディレクトリに必要です。例: {{ic|~/.config/lxc/default.conf}} (ディレクトリを作成します) 必要に応じて)
  +
  +
非 root ユーザーとしてコンテナを実行するには、{{ic|~/.local/share/}} に対する {{ic|+x}} 権限が必要です。コンテナを起動する前に、[[chmod]] を使用して変更を加えます。
   
 
=== コンテナの作成 ===
 
=== コンテナの作成 ===
{{ic|/usr/share/lxc/templates}} からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります:
+
特権コンテナの場合、{{ic|/usr/share/lxc/templates}} からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります:
* Debian ベース: [[AUR]] の {{AUR|debootstrap}}。
+
* Debian ベース: {{Pkg|debootstrap}}。
* Fedora ベース: [[AUR]] の {{AUR|yum}}。
+
* Fedora ベース: {{AUR|yum}}。
   
 
{{ic|lxc-create}} を実行してコンテナを作成します。デフォルトでは LXC の root ファイルシステムは {{ic|/var/lib/lxc/CONTAINER_NAME/rootfs}} にインストールされます。例えば "playtime" という名前の Arch Linux LXC を作成:
 
{{ic|lxc-create}} を実行してコンテナを作成します。デフォルトでは LXC の root ファイルシステムは {{ic|/var/lib/lxc/CONTAINER_NAME/rootfs}} にインストールされます。例えば "playtime" という名前の Arch Linux LXC を作成:
 
# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux
 
# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux
   
  +
非特権コンテナを使いたい場合は {{ic|-t download}} を使用してイメージを選択してください。例:
{{Tip|{{Pkg|haveged}} をインストールして {{ic|haveged.service}} を[[起動]]することで、セットアップ中にシステムエントロピーが作成されるまでシステムが停止するのを回避することができます。haveged を使用しない場合、GPG 鍵を作成するのにしばらく時間がかかるかもしれません。}}
 
  +
# lxc-create -n playtime -t download
   
  +
{{Tip|
{{Tip|[[Btrfs]] を使っている場合 {{ic|-B btrfs}} を追加することでコンテナ化した rootfs を保存するための Btrfs サブボリュームを作成することができます。{{ic|lxc-clone}} コマンドを使ってコンテナを複製するときに便利です。}}
 
  +
* [[haveged]] をインストールして {{ic|haveged.service}} を[[起動]]することで、セットアップ中にシステムエントロピーが作成されるまでシステムが停止するのを回避することができます。haveged を使用しない場合、GPG 鍵を作成するのにしばらく時間がかかるかもしれません。
  +
* [[Btrfs]] を使っている場合 {{ic|-B btrfs}} を追加することでコンテナ化した rootfs を保存するための Btrfs サブボリュームを作成することができます。{{ic|lxc-clone}} コマンドを使ってコンテナを複製するときに便利です。[[ZFS]] ユーザーは {{ic|-B zfs}} が使えます。}}
   
 
=== コンテナの設定 ===
 
=== コンテナの設定 ===
  +
  +
以下の例は特権コンテナと非特権コンテナどちらでも同じように使えます非特権コンテナの場合、{{ic|1=lxc.idmap = u 0 100000 65536}} and the {{ic|1=lxc.idmap = g 0 100000 65536}} values optionally defined in the [[#非特権コンテナのサポートを有効化 (任意)]]セクションで定義した {{ic|1=lxc.idmap = u 0 100000 65536}} や {{ic|1=lxc.idmap = g 0 100000 65536}} などの値がデフォルトで存在するはずです。
  +
 
==== ネットワークの基本設定 ====
 
==== ネットワークの基本設定 ====
  +
System resources to be virtualized / isolated when a process is using the container are defined in {{ic|/var/lib/lxc/CONTAINER_NAME/config}}. By default, the creation process will make a minimum setup without networking support. Below is an example config with networking:
 
  +
{{Note|lxc-1:2.1.0-1 から、設定オプションの多くが変わりました。既存のコンテナはアップデートする必要があります。変更については [https://discuss.linuxcontainers.org/t/lxc-2-1-has-been-released/487 v2.1 リリースノート] を参照してください。}}
  +
  +
プロセスが {{ic|/var/lib/lxc/CONTAINER_NAME/config}} に定義されたコンテナを使う場合、システムリソースは仮想化され分離されます。デフォルトでは、作成プロセスはネットワークサポートを省いた最小限のセットアップを作成します。以下はネットワークを設定する例です:
   
 
{{hc|/var/lib/lxc/playtime/config|<nowiki>
 
{{hc|/var/lib/lxc/playtime/config|<nowiki>
99行目: 267行目:
   
 
## default values
 
## default values
lxc.rootfs = /var/lib/lxc/playtime/rootfs
+
lxc.rootfs.path = /var/lib/lxc/playtime/rootfs
lxc.utsname = playtime
+
lxc.uts.name = playtime
 
lxc.arch = x86_64
 
lxc.arch = x86_64
 
lxc.include = /usr/share/lxc/config/archlinux.common.conf
 
lxc.include = /usr/share/lxc/config/archlinux.common.conf
   
 
## network
 
## network
lxc.network.type = veth
+
lxc.net.0.type = veth
lxc.network.link = br0
+
lxc.net.0.link = br0
lxc.network.flags = up
+
lxc.net.0.flags = up
lxc.network.ipv4 = 192.168.0.3/24
+
lxc.net.0.name = eth0
lxc.network.ipv4.gateway = 192.168.0.1
+
lxc.net.0.hwaddr = ee:ec:fa:e9:56:7d
  +
# uncomment the next two lines if static IP addresses are needed
lxc.network.name = eth0
 
  +
# leaving these commented will imply DHCP networking
 
## mounts
 
## specify shared filesystem paths in the format below
 
## make sure that the mount point exists on the lxc
 
#lxc.mount.entry = /mnt/data/share mnt/data none bind 0 0
 
 
#
 
#
  +
#lxc.net.0.ipv4.address = 192.168.0.3/24
# if running the same Arch linux on the same architecture it may be
 
  +
#lxc.net.0.ipv4.gateway = 192.168.0.1
# adventitious to share the package cache directory
 
#lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0
 
</nowiki>}}
 
 
==== Systemd considerations (required) ====
 
The following sections explain some quirks that should be addressed. A small bash script is required for this to work which users should create:
 
{{hc|/var/lib/lxc/playtime/autodev|<nowiki>
 
#!/bin/bash
 
cd ${LXC_ROOTFS_MOUNT}/dev
 
mkdir net
 
mknod net/tun c 10 200
 
chmod 0666 net/tun
 
 
</nowiki>}}
 
</nowiki>}}
   
  +
{{Note|lxc.network.hwaddr エントリは任意です。省略した場合、自動的にランダムな MAC アドレスが作成されます。コンテナの MAC アドレスを定義することで DHCP サーバーからコンテナの NIC に常に同じ IP を割り当てることが可能になります。}}
Make it executable:
 
# chmod +x /var/lib/lxc/playtime/autodev
 
   
  +
==== コンテナの中でマウント ====
Next, modify {{ic|/var/lib/lxc/playtime/config}} to contain this new section:
 
  +
特権コンテナの場合、ホストでディレクトリを選択してコンテナにバインドマウントすることができます。同一アーキテクチャをコンテナ化している場合にホストとコンテナで pacman のパッケージを共有するなどの使用方法が考えられます。また、共有ディレクトリとして使用することもできます。構文は以下の通りです:
## systemd within the lxc
 
lxc.autodev = 1
 
lxc.pts = 1024
 
lxc.kmsg = 0
 
lxc.hook.autodev=/var/lib/lxc/playtime/autodev
 
   
  +
lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0
===== Systemd conflicts in the /dev tree =====
 
To avoid conflicts of systemd and lxc in the /dev tree. It is '''highly recommended''' to enable the 'autodev' mode. This will cause LXC to create its own device tree but this also means that the traditional way of manually creating device nodes in the container rootfs /dev tree will not work because /dev is overmounted by LXC.
 
   
  +
{{Note|非特権コンテナを使っている場合、ホスト側でファイルシステムのパーミッションを修正しないと上記の設定は機能しません。}}
{{Warning|Any device nodes required that are not created by LXC by default must be created by the ''autodev hook'' script!}}
 
   
  +
==== Xorg プログラムの設定 (任意) ====
It is also important to disable services that are not supported inside a container. Either attach to the running LXC or [[chroot]] into the container rootfs and mask those services:
 
  +
ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。{{ic|/var/lib/lxc/playtime/config}} に以下のセクションを追加してください:
 
ln -s /dev/null /etc/systemd/system/systemd-udevd.service
 
ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket
 
ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket
 
ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount
 
 
This disables udev and mounting of {{ic|/proc/sys/fs/binfmt_misc}}.
 
 
===== Maintain devpts consistency =====
 
Additionally ensure a pty declaration in the LXC container because the presence of this causes LXC to mount devpts as a new instance. Without this the container gets the host's devpts and that is not a good thing - more strange things will happen!
 
lxc.pts = 1024
 
 
{{Note|There is no need to explicitly mount system devices (either via the container config or via its own /etc/fstab) and this should not be done because systemd (or LXC in the case of /dev...) takes care of it.}}
 
 
===== Prevent excess journald activity =====
 
 
By default lxc symlinks /dev/kmsg to /dev/console, this leads to journald running 100% cpu usage all the time. To prevent the symlink, use:
 
lxc.kmsg = 0
 
 
==== Xorg program considerations (optional) ====
 
In order to run programs on the host's display, some bind mounts need to be defined so the containerized programs can access the host's resources. Add the following section to {{ic|/var/lib/lxc/playtime/config}}:
 
 
## for xorg
 
## for xorg
## fix overmounting see: https://github.com/lxc/lxc/issues/434
 
lxc.mount.entry = tmpfs tmp tmpfs defaults
 
 
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
 
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
 
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir
 
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir
+
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir,ro
 
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file
 
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file
   
  +
LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で {{ic|xhost +}} を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。
==== OpenVPN considerations ====
 
   
  +
{{Note|上記の設定は非特権コンテナでは機能しません。}}
コンテナで [[OpenVPN]] を実行したい場合は [[en2:OpenVPN in Linux containers|OpenVPN in Linux containers]] の記事を読んで下さい。
 
   
== コンテナ管理 ==
+
==== OpenVPN 設定 ====
   
  +
コンテナで [[OpenVPN]] を実行したい場合は [[Linux コンテナ/VPN の使用]]の記事を読んで下さい。
  +
  +
== コンテナの管理 ==
  +
=== 基本的な使用方法 ===
 
インストール済みの LXC コンテナを確認するには:
 
インストール済みの LXC コンテナを確認するには:
 
# lxc-ls -f
 
# lxc-ls -f
193行目: 322行目:
 
コンテナを停止:
 
コンテナを停止:
 
# lxc-stop -n CONTAINER_NAME
 
# lxc-stop -n CONTAINER_NAME
  +
  +
コンテナにログインするには:
  +
# lxc-console -n CONTAINER_NAME
  +
  +
ログイン時に pts/0 と lxc/tty1 が表示される場合:
  +
# lxc-console -n CONTAINER_NAME -t 0
  +
  +
ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。
   
 
コンテナにアタッチ:
 
コンテナにアタッチ:
# lxc-attach -n CONTAINER_NAME
+
# lxc-attach -n CONTAINER_NAME --clear-env
   
  +
lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。{{ic| --clear-env}} フラグを指定しなかった場合、ホストは環境変数をコンテナに渡します ({{ic|$PATH}} など、コンテナが他のディストリビューションの場合、一部のコマンドが機能しなくなる可能性があります)。
アタッチしたら、他の linux システム用にコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。
 
  +
  +
=== 高度な使用方法 ===
  +
  +
==== LXC の複製 ====
  +
同じコンテナを複数実行する必要があるときはスナップショットを使うことで管理を簡単にできます。最新状態にしておくベースコンテナをひとつだけセットアップして、それを必要に応じて複製 (スナップショットを作成) するという方法です。スナップショットは overlayfs を使用してデータの差異部分だけをディスクに書き込むためディスク容量を節約してオーバーヘッドをなくすことができます。ベースシステムは読み取り専用にしてスナップショットにのみ overlayfs で変更を加えられるようにします。
  +
  +
欠点としてスナップショットを作成しているときにベースの lxc を実行することはできません。
  +
  +
上に書いているようにコンテナをセットアップしたら "base" と名前を付けます。以下のコマンドで "base" コンテナのスナップショット ("snap1" と "snap2") を作成します:
  +
# lxc-copy -n base -N snap1 -B overlayfs -s
  +
# lxc-copy -n base -N snap2 -B overlayfs -s
  +
  +
{{Note|ベースの lxc で固定 IP を使っている場合、"snap1" や "snap2" を起動する前にネットワーク設定を手動で変更する必要があります。}}
  +
  +
スナップショットは他のコンテナと同じように起動・停止できます。以下のコマンドでスナップショットを削除できます (ベースの lxc に変更は加えられません):
  +
# lxc-destroy -n snap1 -f
  +
  +
[[pi-hole]] と [[OpenVPN]] のスナップショットを管理する systemd ユニットとラッパースクリプトが {{AUR|lxc-snapshots}}{{Broken package link|パッケージが存在しません}} パッケージでインストールできます。
  +
  +
=== 特権コンテナを非特権コンテナに変換 ===
  +
非特権コンテナを使うようにシステムを設定したら ([[#非特権コンテナのサポートを有効化 (任意)]] を参照), {{AUR|nsexec-bzr}} に含まれている {{ic|uidmapshift}} という名前のユーティリティで既存の特権コンテナを非特権コンテナに変換できます。イメージの再ビルドは不要です。
  +
  +
{{Warning|
  +
* ユーティリティを使用する前に既存のイメージをバックアップすることを推奨します。
  +
* ユーティリティは [[ACL]] の UID と GID をシフトしません。手動でシフトする必要があります。
  +
}}
  +
  +
以下のようにコマンドを実行することで変換できます:
  +
# uidmapshift -b /var/lib/lxc/foo 0 100000 65536
  +
  +
利用可能なオプションは引数を付けずに {{ic|uidmapshift}} を実行することで確認可能です。
   
 
== Xorg プログラムの実行 ==
 
== Xorg プログラムの実行 ==
  +
対象のコンテナにアタッチまたは [[SSH]] でログインしてホストの X セッションの DISPLAY ID をプログラムを呼び出すときに指定します。ほとんどの場合、ディスプレイは常時 0 です。
Either attach to or ssh into the target container and prefix the call to the program with the DISPLAY id of the host's X session. For most simple setups, the display is always 0. Example running firefox from the container in the host's display:
 
  +
  +
ホストのディスプレイでコンテナから Firefox を起動する例:
 
$ DISPLAY=:0 firefox
 
$ DISPLAY=:0 firefox
   
  +
もしくは、直接コンテナにアタッチしたり接続する代わりに、以下のコマンドを使って自動的にホストにディスプレイを設定することもできます:
Alternatively, to avoid directly attaching to or connecting to the container, the following can be used on the host to automate the process:
 
# lxc-attach -n playtime --clear-env -- sudo -u YOURUSER env DISPLAY=0.0 firefox
+
# lxc-attach -n playtime --clear-env -- sudo -u YOURUSER env DISPLAY=:0 firefox
  +
  +
== トラブルシューティング ==
  +
  +
=== root ログインが失敗する ===
  +
  +
lxc-console を使ってログインしようとすると以下のエラーが表示される場合:
  +
  +
login: root
  +
Login incorrect
  +
  +
そしてコンテナの {{ic|journalctl}} で以下のように表示される場合:
  +
  +
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
  +
  +
コンテナのファイルシステムにある {{ic|/etc/securetty}} のターミナル名のリストに {{ic|pts/0}} を追加してください。[https://unix.stackexchange.com/questions/41840/effect-of-entries-in-etc-securetty/41939#41939] を参照。コンテナの {{ic|/etc/securetty}} を削除することで常時 root ログインを許可することもできます。[https://github.com/systemd/systemd/issues/852] を参照。
  +
  +
もしくは、lxc-attach に新しいユーザーを作成してシステムにログインするときに使うようにして、それから root に切り替えて下さい。
  +
  +
# lxc-attach -n playtime
  +
[root@playtime]# useradd -m -Gwheel newuser
  +
[root@playtime]# passwd newuser
  +
[root@playtime]# passwd root
  +
[root@playtime]# exit
  +
# lxc-console -n playtime
  +
[newuser@playtime]$ su
  +
  +
===コンテナ設定の veth でネットワークに接続できない===
  +
  +
{{ic|/etc/lxc/''containername''/config}} で設定した '''veth''' ネットワークインターフェイスで LAN や WAN に接続できないことがあります。仮想インターフェイスには IP が割り当てられてネットワークに接続できるようになっている場合:
  +
ip addr show veth0
  +
inet 192.168.1.111/24
  +
固定 IP の設定を全て無効化して、起動したコンテナ OS の中から普通の方法で IP を設定してみてください。
  +
  +
{{ic|''container''/config}} の例:
  +
  +
...
  +
lxc.net.0.type = veth
  +
lxc.net.0.name = veth0
  +
lxc.net.0.flags = up
  +
lxc.net.0.link = {{ic|bridge}}
  +
...
  +
  +
コンテナの中から IP を割り当てる方法は[[ネットワーク設定#IP アドレスの設定]]を参照。
  +
  +
=== Error: unknown command ===
  +
  +
ホスト環境とは異なる Linux ディストリビューションのコンテナ (例えば Arch Linux ホスト環境の Debian コンテナ) に接続して基本的なコマンド (''ls'', ''cat'' など) を入力する発生することがあるエラーです。接続時に {{ic|--clear-env}} 引数を使ってください:
  +
  +
# lxc-attach -n ''container_name'' --clear-env
  +
  +
=== Error: Failed at step KEYRING spawning... ===
  +
  +
特権のないコンテナ内のサービスが失敗し、次のメッセージが表示される場合がある
  +
  +
some.service: Failed to change ownership of session keyring: Permission denied
  +
some.service: Failed to set up kernel keyring: Permission denied
  +
some.service: Failed at step KEYRING spawning ....: Permission denied
  +
  +
次の内容を含むファイル {{ic|/etc/lxc/unpriv.seccomp}} を作成します。
  +
  +
{{hc|/etc/lxc/unpriv.seccomp|
  +
2
  +
blacklist
  +
[all]
  +
keyctl errno 38}}
  +
  +
次に、次の行をコンテナ設定 lxc.idmap '''の後''' に追加します。
  +
  +
lxc.seccomp.profile = /etc/lxc/unpriv.seccomp
  +
  +
== 既知の問題 ==
  +
  +
=== lxc.init.static が欠落しているため lxc-execute が失敗する ===
  +
  +
{{ic|lxc-execute}} はエラーメッセージ {{ic|lxc.init.static}} を表示して失敗する場合。{{Bug|63814}} を参照してください。
  +
  +
{{ic|lxc-start}} を使用してコンテナを起動すると、正常に動作します。
   
 
== 参照 ==
 
== 参照 ==
   
 
* [https://www.stgraber.org/2013/12/20/lxc-1-0-blog-post-series/ LXC 1.0 Blog Post Series]
 
* [https://www.stgraber.org/2013/12/20/lxc-1-0-blog-post-series/ LXC 1.0 Blog Post Series]
* [http://www.ibm.com/developerworks/linux/library/l-lxc-containers/ LXC@developerWorks]
+
* [https://www.ibm.com/developerworks/linux/library/l-lxc-containers/ LXC@developerWorks]
 
* [http://docs.docker.io/en/latest/installation/archlinux/ Docker Installation on ArchLinux]
 
* [http://docs.docker.io/en/latest/installation/archlinux/ Docker Installation on ArchLinux]
  +
* [http://l3net.wordpress.com/tag/lxc/ LXC articles on l3net]

2024年9月1日 (日) 21:55時点における最新版

関連記事

LinuX Containers (LXC) はオペレーティングシステムレベルの仮想化手法であり、一つのコントロールホスト (LXC ホスト) で独立した Linux システム (コンテナ) を複数動作させることができます。仮想マシンではありませんが、CPU やメモリ、ブロック I/O、ネットワークなどが個別に用意された仮想環境として使えます。LXC は LXC ホストの Linux カーネルによる cgroups 機能によって賄われています。chroot に似ていますが、より強力な分離を実現します。

IncusLXD は LXC のマネージャーとして使用できます。このページでは、LXC を直接使用する方法について説明します

コンテナを使用する代替手段としては systemd-nspawndockerpodman があります。

特権コンテナと非特権コンテナ

LXC は特権または非特権で動作するように設定することができます。

一般的に、非特権コンテナは特権コンテナよりも安全だとされています [1]。非特権コンテナでは分離の程度が原理上増すからです。非特権コンテナではコンテナの root の UID をホストの root 以外の UID にマッピングすることで、コンテナの中からホスト環境に影響を及ぼすことを難しくします。たとえ攻撃者がコンテナから脱獄しても、ホスト側では攻撃者に権限がありません。

現在 Arch のパッケージでは特権コンテナは最初からサポートしています。非特権コンテナはカーネル設定を行わないと利用できません。Arch の linux カーネルでは通常ユーザーでユーザー名前空間が無効になっているためです。この記事では特権・非特権両方のコンテナの情報を載せていますが、非特権を使うには設定が必要です。

非特権コンテナの例

UID マッピングの能力を説明するために、非特権コンテナで以下のコマンドを実行したときの出力を考えてみましょう。ps の出力でコンテナ化されたプロセスの所有者が同じくコンテナ化された root ユーザーとなっていることが確認できます:

[root@unprivileged_container /]# ps -ef | head -n 5
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 17:49 ?        00:00:00 /sbin/init
root        14     1  0 17:49 ?        00:00:00 /usr/lib/systemd/systemd-journald
dbus        25     1  0 17:49 ?        00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
systemd+    26     1  0 17:49 ?        00:00:00 /usr/lib/systemd/systemd-networkd

ホスト側では、コンテナ化された root プロセスはマッピングされたユーザー (ID>100000) で動作します。ホストの root ユーザーではありません:

[root@host /]# lxc-info -Ssip --name sandbox
State:          RUNNING
PID:            26204
CPU use:        10.51 seconds
BlkIO use:      244.00 KiB
Memory use:     13.09 MiB
KMem use:       7.21 MiB
[root@host /]# ps -ef | grep 26204 | head -n 5
UID        PID  PPID  C STIME TTY          TIME CMD
100000   26204 26200  0 12:49 ?        00:00:00 /sbin/init
100000   26256 26204  0 12:49 ?        00:00:00 /usr/lib/systemd/systemd-journald
100081   26282 26204  0 12:49 ?        00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
100000   26284 26204  0 12:49 ?        00:00:00 /usr/lib/systemd/systemd-logind

セットアップ

必要なソフトウェア

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

非特権コンテナのサポートを有効化 (任意)

/etc/lxc/default.conf を変更して次の行を含めます:

lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536

言い換えると、65536 個の連続した uid の範囲をマップします。コンテナ側の uid 0 (ホストの観点からは uid 100000 になります) から、ホストが uid 165535 として認識するコンテナ側の uid 65535 までです。同じマッピングを gid に適用します。

/etc/subuid/etc/subgid の両方を作成して、コンテナを実行できる各ユーザーのコンテナ化された uid/gid ペアへのマッピングを含めます。以下の例は、単純に root ユーザー (および systemd システムユニット) を対象としています:

/etc/subuid
root:100000:65536
/etc/subgid
root:100000:65536

さらに、非特権ユーザーとして非特権コンテナを実行することは、事前に cgroup を委任した場合にのみ機能します (この制限は、liblxc ではなく cgroup2 委任モデルによって強制されます) 次の systemd コマンドを使用して cgroup を委任します (LXC - Getting started: Creating unprivileged containers as a user):

$ systemd-run --unit=myshell --user --scope -p "Delegate=yes" lxc-start container_name

これは他の lxc コマンドでも同様に機能します。

/etc/systemd/system/user@.service.d/delegate.conf
[Service]
Delegate=cpu cpuset io memory pids
linux-hardened などカスタムカーネル上の特権のないコンテナ

linux-hardened またはカスタム カーネル上で 非特権 コンテナを実行したいユーザーは、いくつかの追加のセットアップ手順を完了する必要があります。

まず、ユーザー名前空間をサポートするカーネル (CONFIG_USER_NS を備えたカーネル) が必要です。すべての Arch Linux カーネルは CONFIG_USER_NS をサポートしています。ただし、より一般的なセキュリティ上の懸念により、linux-hardened カーネルは、root ユーザーに対してのみ有効になったユーザー名前空間とともに出荷されます。そこに 非特権 コンテナを作成するには 2 つのオプションがあります:

  • 特権のないコンテナは root としてのみ起動してください。また、現在の値が 0 の場合、sysctl 設定 user.max_user_namespaces に環境に合わせて正の値を指定します (これにより、lxc info --show-log container_name で見られる Failed to clone process in new user namespace というエラーが修正されます)
  • linux-hardened および lxd 5.0.0 では、root:1000000:65536 の範囲を使用するように /etc/subuid および /etc/subgid を設定する必要がある場合があります。最初 のコンテナを特権付きで起動する必要がある場合もあります。これにより、newuidmap failed to write mapping "newuidmap: uid range [0-1000000000) -> [1000000-1001000000) not allowed" エラーが修正されます。
  • sysctl 設定 kernel.unprivileged_userns_clone を有効にして、通常のユーザーが特権のないコンテナを実行できるようにします。これは、root として sysctl kernel.unprivileged_userns_clone=1 を実行することで現在のセッションに対して行うことができ、また、sysctl.d(5) を使用して永続化することもできます。

ホストネットワーク設定

LXC は、さまざまな仮想ネットワークタイプとデバイスをサポートします (lxc.container.conf(5) を参照) ホスト上のブリッジデバイスは、このセクションで説明するほとんどのタイプの仮想ネットワークに必要です。

考慮すべき主な設定がいくつかあります。

  1. ホストブリッジ
  2. NAT ブリッジ

ホストブリッジでは、ホストのネットワークマネージャーが共有ブリッジインターフェイスを管理する必要があります。ホストとすべての lxc には、同じネットワーク内の IP アドレスが割り当てられます (たとえば、192.168.1.x) Web サーバーや VPN サーバーなど、ネットワークに公開されたサービスをコンテナ化することが目的の場合、これはより単純になる可能性があります。ユーザーは、lxc を物理 LAN 上の単なる別の PC と考えることができ、それに応じてルーター内の必要なポートを転送できます。追加されたシンプルさは、追加の脅威ベクトルと考えることもできます。WAN トラフィックが lxc に転送される場合、別の範囲で lxc を実行すると、脅威の表面が小さくなります。

NAT ブリッジでは、ホストのネットワークマネージャーがブリッジを管理する必要はありません。lxc には、lxcbr0 という NAT ブリッジを作成する lxc-net が同梱されています。NAT ブリッジは、ホストのイーサネット デバイスや物理ネットワークにブリッジされていないプライベート ネットワークを備えたスタンドアロンブリッジです。ホスト内にプライベートサブネットとして存在します。

ホストブリッジの使用

ネットワークブリッジ を参照してください。

NAT ブリッジの使用

dnsmasqインストール して下さい、これは lxc-net の依存関係です。ブリッジを開始する前に、まずブリッジの設定ファイルを作成します:

/etc/default/lxc-net
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers.  Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"

# If you change the LXC_BRIDGE to something other than lxcbr0, then
# you will also need to update your /etc/lxc/default.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.3.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.3.0/24"
LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
LXC_DHCP_MAX="253"
# Uncomment the next line if you'd like to use a conf-file for the lxcbr0
# dnsmasq.  For instance, you can use 'dhcp-host=mail1,10.0.3.100' to have
# container 'mail1' always get ip address 10.0.3.100.
#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

# Uncomment the next line if you want lxcbr0's dnsmasq to resolve the .lxc
# domain.  You can then add "server=/lxc/10.0.3.1' (or your actual $LXC_ADDR)
# to your system dnsmasq configuration file (normally /etc/dnsmasq.conf,
# or /etc/NetworkManager/dnsmasq.d/lxc.conf on systems that use NetworkManager).
# Once these changes are made, restart the lxc-net and network-manager services.
# 'container1.lxc' will then resolve on your host.
#LXC_DOMAIN="lxc"
ヒント: ブリッジの IP 範囲がローカルネットワークに干渉しないことを確認してください。

次に、コンテナがブリッジを使用するように LXC コンテナテンプレートを変更する必要があります。

/etc/lxc/default.conf
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx

Optionally create a configuration file to manually define the IP address of any containers:

/etc/lxc/dnsmasq.conf
dhcp-host=playtime,10.0.3.100

lxc-net.service起動/有効化 してブリッジ インターフェイスを作成します。

ファイアウォールの考慮事項

ホストマシンが実行しているファイアウォールによっては、lxcbr0 からホストへの受信パケットと、lxcbr0 からの送信パケットがホストを経由して他のネットワークに到達することを許可する必要がある場合があります。これをテストするには、IP 割り当てに DHCP を使用するように設定されたコンテナを起動して、lxc-net がコンテナに IP アドレスを割り当てることができるかどうかを確認してください (lxc-ls -f IP が割り当てられていない場合は、ホストのポリシーを調整する必要があります。

ufw のユーザーは、次の 2 行 を実行するだけです。これを有効にするには:

# ufw allow in on lxcbr0
# ufw route allow in on lxcbr0

あるいは、nftables のユーザーは、/etc/nftables.conf を変更できます (そして、nft -f /etc/nftables.conf で再ロードします。設定が正しいかどうかを確認してください) nft -cf /etc/nftables.conf これでコンテナがインターネットにアクセスできるようになります ("eth0" を、インターネットにアクセスできるシステム上のデバイスに置き換えます。 ip link を使用して既存のデバイスをリストします):

/etc/nftables.conf
table inet filter {
  chain input {
    ...
    iifname "lxcbr0" accept comment "Allow lxc containers"
    
    pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited
    counter
  }
  chain forward {
    ...
    iifname "lxcbr0" oifname "eth0" accept comment "Allow forwarding from lxcbr0 to eth0"
    iifname "eth0" oifname "lxcbr0" accept comment "Allow forwarding from eth0 to lxcbr0"
  }
}

さらに、コンテナーは 10.0.3.x サブネット上で実行されているため、ssh、httpd などのサービスへの外部アクセスは lxc にアクティブに転送される必要があります。原則として、ホスト上のファイアウォールは、コンテナ上の予期されるポートで受信トラフィックを転送する必要があります。

iptables ルールの例

このルールの目的は、lxc への ssh トラフィックを許可することです:

# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2221 -j DNAT --to-destination 10.0.3.100:22

このルールは、ポート 2221 から発信される tcp トラフィックをポート 22 の lxc の IP アドレスに転送します。

ノート: ホスト上で 2221/tcp のトラフィックを許可し、lxc 上で 22/tcp のトラフィックを許可するようにしてください。

LAN 上の別の PC からコンテナーに ssh 接続するには、ポート 2221 でホストに ssh 接続する必要があります。その後、ホストはそのトラフィックをコンテナに転送します。

$ ssh -p 2221 host.lan
ufw ルールの例

ufw を使用する場合は、これを永続化するために、/etc/ufw/before.rules の最後に次の行を追加します:

/etc/ufw/before.rules

*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -i eth0 -p tcp --dport 2221 -j DNAT --to-destination 10.0.3.100:22
COMMIT
非 root ユーザーとしてコンテナを実行する

非 root ユーザーとしてコンテナーを作成して起動するには、追加の構成を適用する必要があります。

/etc/lxc/lxc-usernet にユーザーネットファイルを作成します。lxc-usernet(5) によると、1 行あたりのエントリは次のとおりです。

user type bridge number

コンテナを作成する必要があるユーザーを使用してファイルを設定します。ブリッジは、/etc/default/lxc-net で定義されているものと同じになります。

/etc/lxc/default.conf のコピーが、非 root ユーザーのホームディレクトリに必要です。例: ~/.config/lxc/default.conf (ディレクトリを作成します) 必要に応じて)

非 root ユーザーとしてコンテナを実行するには、~/.local/share/ に対する +x 権限が必要です。コンテナを起動する前に、chmod を使用して変更を加えます。

コンテナの作成

特権コンテナの場合、/usr/share/lxc/templates からコンテナ化するディストロに合わせてテンプレートを選択してください。Arch 以外のディストロをコンテナに入れたい場合、ディストロによってホストにパッケージを追加でインストールする必要があります:

lxc-create を実行してコンテナを作成します。デフォルトでは LXC の root ファイルシステムは /var/lib/lxc/CONTAINER_NAME/rootfs にインストールされます。例えば "playtime" という名前の Arch Linux LXC を作成:

# lxc-create -n playtime -t /usr/share/lxc/templates/lxc-archlinux

非特権コンテナを使いたい場合は -t download を使用してイメージを選択してください。例:

# lxc-create -n playtime -t download
ヒント:
  • haveged をインストールして haveged.service起動することで、セットアップ中にシステムエントロピーが作成されるまでシステムが停止するのを回避することができます。haveged を使用しない場合、GPG 鍵を作成するのにしばらく時間がかかるかもしれません。
  • Btrfs を使っている場合 -B btrfs を追加することでコンテナ化した rootfs を保存するための Btrfs サブボリュームを作成することができます。lxc-clone コマンドを使ってコンテナを複製するときに便利です。ZFS ユーザーは -B zfs が使えます。

コンテナの設定

以下の例は特権コンテナと非特権コンテナどちらでも同じように使えます非特権コンテナの場合、lxc.idmap = u 0 100000 65536 and the lxc.idmap = g 0 100000 65536 values optionally defined in the #非特権コンテナのサポートを有効化 (任意)セクションで定義した lxc.idmap = u 0 100000 65536lxc.idmap = g 0 100000 65536 などの値がデフォルトで存在するはずです。

ネットワークの基本設定

ノート: lxc-1:2.1.0-1 から、設定オプションの多くが変わりました。既存のコンテナはアップデートする必要があります。変更については v2.1 リリースノート を参照してください。

プロセスが /var/lib/lxc/CONTAINER_NAME/config に定義されたコンテナを使う場合、システムリソースは仮想化され分離されます。デフォルトでは、作成プロセスはネットワークサポートを省いた最小限のセットアップを作成します。以下はネットワークを設定する例です:

/var/lib/lxc/playtime/config
# Template used to create this container: /usr/share/lxc/templates/lxc-archlinux
# Parameters passed to the template:
# For additional config options, please look at lxc.container.conf(5)

## default values
lxc.rootfs.path = /var/lib/lxc/playtime/rootfs
lxc.uts.name = playtime
lxc.arch = x86_64
lxc.include = /usr/share/lxc/config/archlinux.common.conf

## network
lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.name = eth0
lxc.net.0.hwaddr = ee:ec:fa:e9:56:7d
# uncomment the next two lines if static IP addresses are needed
# leaving these commented will imply DHCP networking
#
#lxc.net.0.ipv4.address = 192.168.0.3/24
#lxc.net.0.ipv4.gateway = 192.168.0.1
ノート: lxc.network.hwaddr エントリは任意です。省略した場合、自動的にランダムな MAC アドレスが作成されます。コンテナの MAC アドレスを定義することで DHCP サーバーからコンテナの NIC に常に同じ IP を割り当てることが可能になります。

コンテナの中でマウント

特権コンテナの場合、ホストでディレクトリを選択してコンテナにバインドマウントすることができます。同一アーキテクチャをコンテナ化している場合にホストとコンテナで pacman のパッケージを共有するなどの使用方法が考えられます。また、共有ディレクトリとして使用することもできます。構文は以下の通りです:

lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0
ノート: 非特権コンテナを使っている場合、ホスト側でファイルシステムのパーミッションを修正しないと上記の設定は機能しません。

Xorg プログラムの設定 (任意)

ホストのディスプレイでプログラムを動かしたい場合、コンテナ化されたプログラムがホストのリソースにアクセスできるようにバインドマウントを定義する必要があります。/var/lib/lxc/playtime/config に以下のセクションを追加してください:

## for xorg
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir,ro
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file

LXC のゲスト側に permission denied エラーが表示される場合、ホスト側で xhost + を実行してゲストからホストのディスプレイサーバーに接続できるようにする必要があります。このようにディスプレイサーバーを開くことはセキュリティ上問題があるので注意してください。

ノート: 上記の設定は非特権コンテナでは機能しません。

OpenVPN の設定

コンテナで OpenVPN を実行したい場合は Linux コンテナ/VPN の使用の記事を読んで下さい。

コンテナの管理

基本的な使用方法

インストール済みの LXC コンテナを確認するには:

# lxc-ls -f

Systemd で lxc@CONTAINER_NAME.service を使うことで LXC を起動したり停止することができます。lxc@CONTAINER_NAME.service有効化するとホストシステムの起動時に LXC が立ち上がるようになります。

systemd を使わずに LXC を起動・停止することも可能です。コンテナを起動:

# lxc-start -n CONTAINER_NAME

コンテナを停止:

# lxc-stop -n CONTAINER_NAME

コンテナにログインするには:

# lxc-console -n CONTAINER_NAME

ログイン時に pts/0 と lxc/tty1 が表示される場合:

# lxc-console -n CONTAINER_NAME -t 0

ログインしたら、他の linux システムと同じようにコンテナを扱って、root パスワードを設定し、ユーザーを作成、パッケージのインストールなどを行って下さい。

コンテナにアタッチ:

# lxc-attach -n CONTAINER_NAME --clear-env

lxc-console とほぼ同じですが、自動的にログインを通り越してコンテナの中の root プロンプトにアクセスします。 --clear-env フラグを指定しなかった場合、ホストは環境変数をコンテナに渡します ($PATH など、コンテナが他のディストリビューションの場合、一部のコマンドが機能しなくなる可能性があります)。

高度な使用方法

LXC の複製

同じコンテナを複数実行する必要があるときはスナップショットを使うことで管理を簡単にできます。最新状態にしておくベースコンテナをひとつだけセットアップして、それを必要に応じて複製 (スナップショットを作成) するという方法です。スナップショットは overlayfs を使用してデータの差異部分だけをディスクに書き込むためディスク容量を節約してオーバーヘッドをなくすことができます。ベースシステムは読み取り専用にしてスナップショットにのみ overlayfs で変更を加えられるようにします。

欠点としてスナップショットを作成しているときにベースの lxc を実行することはできません。

上に書いているようにコンテナをセットアップしたら "base" と名前を付けます。以下のコマンドで "base" コンテナのスナップショット ("snap1" と "snap2") を作成します:

# lxc-copy -n base -N snap1 -B overlayfs -s
# lxc-copy -n base -N snap2 -B overlayfs -s
ノート: ベースの lxc で固定 IP を使っている場合、"snap1" や "snap2" を起動する前にネットワーク設定を手動で変更する必要があります。

スナップショットは他のコンテナと同じように起動・停止できます。以下のコマンドでスナップショットを削除できます (ベースの lxc に変更は加えられません):

# lxc-destroy -n snap1 -f

pi-holeOpenVPN のスナップショットを管理する systemd ユニットとラッパースクリプトが lxc-snapshotsAUR[リンク切れ: パッケージが存在しません] パッケージでインストールできます。

特権コンテナを非特権コンテナに変換

非特権コンテナを使うようにシステムを設定したら (#非特権コンテナのサポートを有効化 (任意) を参照), nsexec-bzrAUR に含まれている uidmapshift という名前のユーティリティで既存の特権コンテナを非特権コンテナに変換できます。イメージの再ビルドは不要です。

警告:
  • ユーティリティを使用する前に既存のイメージをバックアップすることを推奨します。
  • ユーティリティは ACL の UID と GID をシフトしません。手動でシフトする必要があります。

以下のようにコマンドを実行することで変換できます:

# uidmapshift -b /var/lib/lxc/foo 0 100000 65536

利用可能なオプションは引数を付けずに uidmapshift を実行することで確認可能です。

Xorg プログラムの実行

対象のコンテナにアタッチまたは SSH でログインしてホストの X セッションの DISPLAY ID をプログラムを呼び出すときに指定します。ほとんどの場合、ディスプレイは常時 0 です。

ホストのディスプレイでコンテナから Firefox を起動する例:

$ DISPLAY=:0 firefox

もしくは、直接コンテナにアタッチしたり接続する代わりに、以下のコマンドを使って自動的にホストにディスプレイを設定することもできます:

# lxc-attach -n playtime --clear-env -- sudo -u YOURUSER env DISPLAY=:0 firefox

トラブルシューティング

root ログインが失敗する

lxc-console を使ってログインしようとすると以下のエラーが表示される場合:

login: root
Login incorrect

そしてコンテナの journalctl で以下のように表示される場合:

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

コンテナのファイルシステムにある /etc/securetty のターミナル名のリストに pts/0 を追加してください。[2] を参照。コンテナの /etc/securetty を削除することで常時 root ログインを許可することもできます。[3] を参照。

もしくは、lxc-attach に新しいユーザーを作成してシステムにログインするときに使うようにして、それから root に切り替えて下さい。

# lxc-attach -n playtime
[root@playtime]# useradd -m -Gwheel newuser
[root@playtime]# passwd newuser
[root@playtime]# passwd root
[root@playtime]# exit
# lxc-console -n playtime
[newuser@playtime]$ su

コンテナ設定の veth でネットワークに接続できない

/etc/lxc/containername/config で設定した veth ネットワークインターフェイスで LAN や WAN に接続できないことがあります。仮想インターフェイスには IP が割り当てられてネットワークに接続できるようになっている場合:

ip addr show veth0 
inet 192.168.1.111/24

固定 IP の設定を全て無効化して、起動したコンテナ OS の中から普通の方法で IP を設定してみてください。

container/config の例:

...
lxc.net.0.type = veth
lxc.net.0.name = veth0
lxc.net.0.flags = up
lxc.net.0.link = bridge
...

コンテナの中から IP を割り当てる方法はネットワーク設定#IP アドレスの設定を参照。

Error: unknown command

ホスト環境とは異なる Linux ディストリビューションのコンテナ (例えば Arch Linux ホスト環境の Debian コンテナ) に接続して基本的なコマンド (ls, cat など) を入力する発生することがあるエラーです。接続時に --clear-env 引数を使ってください:

# lxc-attach -n container_name --clear-env

Error: Failed at step KEYRING spawning...

特権のないコンテナ内のサービスが失敗し、次のメッセージが表示される場合がある

some.service: Failed to change ownership of session keyring: Permission denied
some.service: Failed to set up kernel keyring: Permission denied
some.service: Failed at step KEYRING spawning ....: Permission denied

次の内容を含むファイル /etc/lxc/unpriv.seccomp を作成します。

/etc/lxc/unpriv.seccomp
2
blacklist
[all]
keyctl errno 38

次に、次の行をコンテナ設定 lxc.idmap の後 に追加します。

lxc.seccomp.profile = /etc/lxc/unpriv.seccomp

既知の問題

lxc.init.static が欠落しているため lxc-execute が失敗する

lxc-execute はエラーメッセージ lxc.init.static を表示して失敗する場合。FS#63814 を参照してください。

lxc-start を使用してコンテナを起動すると、正常に動作します。

参照