サービスがイメージとして提供され、必要とするのが厳密に限定されたファイル、ポート、デバイス、ケイパビリティだけである場合は、最小権限のDockerコンテナを選択します。より完全なLinux環境、直接的なシステム統合、または個別に管理するゲスト内で複数の関連プロセスを必要とする場合は、専用の非特権LXCを選択します。広範なホストディレクトリ、Dockerソケット、制限のないデバイス、またはホストレベルのroot権限を公開した時点で、どちらのモデルも意味のあるセキュリティ境界ではなくなります。
まず同等のデプロイ境界を比較する
DockerとLXCはどちらもホストカーネルを共有するLinuxコンテナ技術ですが、通常は異なる単位をパッケージ化します。Dockerは通常、1つのアプリケーションまたはComposeスタックを隔離します。LXCは、独自のユーザー、パッケージデータベース、サービス、オペレーティングシステムのファイルシステムを備えた軽量なシステムコンテナを作成します。
したがって、比較対象として適切なのは、Linuxホスト上で直接実行するDockerアプリケーションと、同じ特権型ホームサービスを専用LXC内にインストールした場合です。LXC内のDockerとLXCそのものを比較するものではなく、どちらのコンテナモデルも、別カーネルを持つ仮想マシンと比較するものではありません。
既存のZimaSpaceによるLXC内でのDockerとネイティブインストールの比較では、パッケージ化とメンテナンスを扱っています。この記事では、通常のコンテナ境界を弱める権限をサービスが要求する場合のセキュリティ上の判断に焦点を絞ります。
| セキュリティの観点 | Dockerアプリコンテナ | 専用LXCシステムコンテナ |
|---|---|---|
| 主な隔離単位 | アプリケーションプロセスとそのパッケージ済み依存関係 | 複数のサービスとユーザーを備えたLinuxユーザー空間 |
| ホストカーネル | ホストと共有 | ホストと共有 |
| rootのマッピング | ユーザーネームスペースまたはrootlessモードを使用しない限り、デフォルトではroot権限で動作する | 特権モードにすることも、コンテナのrootを非特権ホストUIDにマッピングすることもできる |
| デバイスアクセス | 個別のデバイスをマッピングできる。特権モードでは広範囲に公開される | ホストのデバイスノードと権限をゲストにマッピングできる |
| ホストファイル | バインドマウントは選択したホストパスをアプリに直接公開する | バインドマウントはゲストおよびゲスト内の認証済みプロセスすべてにパスを公開する |
| 管理API | DockerソケットによってDockerホストを制御できる | LXC内に別のランタイムをインストールしない限り、同等のデーモンソケットは存在しない |
| 最適な選択 | 権限が厳密に制限されたパッケージアプリ | 非特権ゲスト境界内でOS統合を必要とするサービス |
サービスに必要な権限から始める
「特権付きホームサービス」という言葉は、互いに関係のない複数の権限を意味する場合があります。USBシリアルデバイスの読み取り、GPUのレンダーノードの使用、ネットワークインターフェースの制御、ファイルシステムのマウント、1024未満のポートへのバインド、Bluetoothへのアクセス、SMART情報の読み取り、他のコンテナの管理などです。これらの権限がもたらすホストへのリスクは同じではありません。
サービスが動作するために必要な最小限のケーパビリティ、デバイス、パス、ネットワークモードだけを付与してください。Snykによる特権コンテナモードの解説では、完全な特権アクセスによって、すべてのホストデバイスと、ホストとほぼ同等の権限が公開されることを強調しています。不足している1つの権限を調査する代わりに、これを使うべきではありません。
サービスに必要なのが /dev/dri/renderD128、シリアル番号による1つのパス、または読み取り専用の設定ディレクトリだけが必要な場合、DockerとLXCのどちらでも、その限定的なリソースを公開できます。セキュリティ上の違いが意味を持つのは、デプロイメントで広範なケーパビリティや複数のホスト側インターフェースが必要になる場合です。
非特権LXCは、より強固なrootマッピング境界を作る
非特権LXCでは、ゲスト内のUID 0がProxmoxホスト上の通常のサブUIDにマッピングされます。プロセスはコンテナ内ではrootとして動作しているように見えても、ユーザー名前空間の外側ではホストのrootとしてのIDを持ちません。これにより、多くのファイル権限の設定ミスや一部のコンテナエスケープによる影響を軽減できます。
Linux Containersプロジェクトは、非特権LXCのrootマッピングを、この設計における主要なセキュリティ境界として説明しています。さらに、AppArmor、seccomp、ケーパビリティがプロセスとホストリソースに対する制限を追加します。
そのメリットは、コンテナを非特権で維持することにかかっています。特権LXCでは同じUIDの再マッピングが行われないため、ゲスト内のrootはホスト上のrootにより直接的に対応します。マウントやデバイスを簡単に扱う目的だけで特権モードへ移行すると、LXCのほうが安全に見えた理由が失われる可能性があります。
Dockerは、アプリをLXCに移行せずにrootのリスクを低減できる
Dockerコンテナは、制限のないroot権限のデーモンやrootユーザーでアプリケーションを実行する必要はありません。コンテナイメージでは非rootユーザーを指定でき、ランタイムではケーパビリティを削減でき、ファイルシステムを読み取り専用にでき、ユーザー名前空間ではコンテナ内のIDを再マッピングできます。
Dockerのrootlessモードでは、デーモンとコンテナの両方がホストのroot権限なしで実行されます。アプリケーションと必要なストレージまたはネットワーク機能がrootlessの制限に対応している場合、これによりデーモンとランタイムのリスクを軽減できます。
アプリがすでに適切にパッケージ化され、狭く定義された1つの権限だけを必要とする場合は、Dockerのほうが優れた境界であり続けます。完全なLXCに移行すると、侵害されたアプリケーションに割り当てられたリソースが自動的に減るわけではないのに、パッチを適用すべきオペレーティングシステムが1つ増えます。
Dockerソケットはアプリケーションの境界を消し去る可能性がある
一部のダッシュボード、自動更新ツール、バックアップツール、監視サービスは、次へのアクセスを要求します /var/run/docker.sockこのソケットを使うと、クライアントはホストのDockerデーモンに対して、コンテナの作成、ホストパスのマウント、デバイスの公開、ネットワークの変更を指示できます。そのため、侵害されたサービスはカーネル脱出を悪用しなくても、間接的にホストを制御できる可能性があります。
Netdataの分析では、Dockerソケットへのアクセスがホスト管理のように機能する理由を説明しています。プロセスは、従来のコンテナ脱出を利用せず、特権を持つデーモンに代わりに強力なホスト操作を実行させるからです。
ここが最初の見極めポイントです。サービスにDockerソケットへの無制限のアクセスが必要な場合、通常のDocker分離と通常のLXC分離を比較するのは適切ではありません。そのサービスをホスト管理者として扱い、可能であれば目的に特化したプロキシでAPIを制限し、信頼できないネットワークから分離し、認証情報を適切に保護してください。
デバイスマッピングでは、権限レイヤーが少ないモデルが有利
GPU、USBコーディネーター、チューナー、Coralアクセラレーター、UPS、シリアルアダプターは、どちらのデプロイにも渡せます。直接Dockerを使う場合、ホストがアプリケーションコンテナにデバイスを公開します。LXCでは、Proxmoxがシステムコンテナにデバイスを公開し、そのコンテナ内でサービスをネイティブに実行するか、ネストしたDockerに再度渡すことができます。
複数の関連プロセスが同じデバイスを必要とし、Linuxのユーザーやグループでアクセスを管理したい場合は、専用のLXCのほうが構成を整理しやすくなります。1つのイメージが1つのデバイスを必要とし、その割り当てをComposeに直接記述できる場合は、Dockerのほうが整理しやすいでしょう。
一方のデバイスの権限設定が難しいという理由だけで、どちらのコンテナにもすべてのデバイスへのアクセスを与えないでください。Proxmoxは、LXCのセキュリティは、名前空間、AppArmor、seccomp、デバイス制限を組み合わせていると説明しています。広範なデバイスアクセスを許可すると、Dockerの特権モードと同様に、この多層的な境界の一部が失われます。
ホストのバインドマウントは、異なる方向にリスクを移す
Dockerのバインドマウントは、選択したホストパスをアプリケーションに直接公開します。写真、バックアップ、設定、または他のアプリケーションの状態を含む書き込み可能なマウントでは、コンテナが侵害された場合、そのパスでマッピングされたホストユーザーと同じ変更権限が与えられます。
LXCのバインドマウントはそのパスをゲストに公開します。ゲスト内の複数のサービスや管理ユーザーが、UIDとGIDのマッピングに従ってアクセスできる可能性があります。追加のシステム境界は権限の整理に役立ちますが、同時にデータへ到達できるゲスト内プロセスの集合も広げます。
可能な限り読み取り専用マウントを使用し、設定と大量データを分離し、ホストのroot、 /proc, /sys, /dev、またはDockerのデータディレクトリを広範にマウントすることです。サービスが保護されたNASデータを書き換える必要がある場合、アプリケーションの分離だけでは、スナップショットや独立したバックアップの代わりにはなりません。
ネットワーク権限は、ファイルシステムアクセスよりも広範な影響範囲を生むことがある
VPNゲートウェイ、DNSフィルター、ネットワーク探索ツール、Home Assistant連携、監視システムなどのホームサービスでは、ホストネットワーク、rawソケット、パケットキャプチャ、ファイアウォールの変更、複数のVLANへのアクセスを要求する場合があります。こうしたケーパビリティによってトラフィックが露出し、サービスが他のデバイスに影響を与えられる可能性があります。
ホストネットワークを使用するDockerコンテナでは、ポート単位のネットワーク分離が失われます。また、 NET_ADMIN または NET_RAW 侵害された場合に可能となる操作の範囲を広げます。独自の仮想インターフェースを持つLXCなら、分離されたアドレスとファイアウォールポリシーを設定できますが、特権ゲストや広範にブリッジ接続されたゲストは、依然として機密性の高いネットワークに到達できます。
最も狭いネットワーク経路を定義できる境界を選びましょう。分離されたVLAN、専用アドレス、明示的なファイアウォールルール、NAS管理画面へのアクセス禁止は、サービスをすべての信頼済みネットワークに接続したままコンテナ技術だけを変更するよりも、リスクを減らせることがよくあります。
特権LXCと特権Dockerは、異なる形で問題を起こす
完全に特権化されたDockerコンテナは、root権限で動作するDockerデーモンを通じて、広範なLinuxケーパビリティとデバイスアクセスを受け取ります。特権LXCでは、ゲストの完全なユーザー空間が、ホストのrootとのより密接な権限関係を持ちます。どちらも、通常の非特権アプリケーションコンテナと同じように扱うべきではありません。
Tigera のセキュリティガイダンスでは、特権 Docker モードは主要な分離制御を回避すると警告しています。同様に、Proxmox コミュニティの議論でも、LXC 内でネスト機能や広範なホストファイルシステムへのアクセスを有効にすると、設定を誤った場合にホストの /proc や /sys の領域が露出する可能性があると警告されています。
サービスが本当にホストの root と同等の権限を必要とする場合は、専用カーネルを備えた VM のほうが、より明確な封じ込め境界を提供できる可能性があります。サービスがインターネットに公開されている、信頼できない入力を処理する、カーネルに近いドライバーを読み込む、または他のワークロードを管理する場合は、追加のメモリとストレージのオーバーヘッドを正当化できます。
更新と復旧によって、分離を実用的な状態に保てるかどうかが決まる
Docker では、アプリケーションパッケージを交換可能にできます。固定したイメージまたはダイジェストからコンテナを再作成し、設定と永続データを復元して、同じ範囲の狭い権限を再適用します。これは、セキュリティポリシーをシェルコマンドの記憶に頼らず、Compose 内で可視化できる場合に有効です。
専用 LXC では、運用環境全体を1つの Proxmox ゲストとして交換可能にできます。パッケージデータベース、サービスファイル、ユーザー、デバイスマッピングをまとめてバックアップできます。バインドマウント、UID マップ、ホストデバイス、ネットワークルールをゲストの外部に記録しておけば、復旧をクリーンに行えます。
Docker VM とアプリごとの LXC における復旧境界に関する ZimaSpace の比較では、これに隣接する運用テストを紹介しています。より小さなセキュリティ境界は、広範な権限を手作業で再作成せずに復元できる場合にのみ有用です。
Docker と LXC のどちらを選ぶか決める前に、権限削減テストを実施する
- サービスが要求するすべてのデバイス、ホストパス、ケイパビリティ、ネットワーク、API、カーネル機能を一覧化します。
- 完全な特権モードを削除し、必要な要件を一度に1つずつ追加します。
- アプリケーションを root 以外のユーザーとして実行するか、対応している場合は非特権 LXC 内で実行します。
- 広範な書き込み可能マウントを、範囲を絞った読み取り専用パスまたはデータセット固有のパスに置き換えます。
- Docker ソケットへのアクセスを削除するか、サービスとデーモンの間に制限付きプロキシを配置します。
- どのホストファイル、デバイス、ネットワークに引き続き到達できるかを確認し、侵害時の想定を検証します。
- バージョン管理された設定のみを使用し、クリーンな Docker または LXC ホスト上でサービスを復元します。
セキュリティをレイヤーの数だけで評価しないでください。必要なデバイス、マウント、ケイパビリティ、ソケット、ネットワークをすべて追加した後に利用可能となる実効権限で評価します。アクセス範囲を限定した単純なコンテナは、複数の例外を伴う複雑なネスト構成より安全な場合があります。
特権ホームサービスに適した境界はどれですか?
Dockerアプリコンテナを選ぶ場合
サービスがイメージとして配布され、1~2個の明示的なデバイスまたはマウントを必要とし、以下なしで実行できる場合は、Dockerを選択します。 --privileged、無制限のDockerソケットアクセス、または広範なホストネットワーク。バージョンを固定し、ケイパビリティを削減し、可能な限り読み取り専用ファイルシステムを使用し、永続データを明示的に管理してください。
専用の非特権LXCを選ぶ場合
サービスにより完全なLinux環境、複数の関連デーモン、systemdとの直接統合、または複雑なデバイスグループ権限が必要な場合は、LXCを選択します。ユーザーネームスペースマッピングを維持し、AppArmorとseccompの制限を有効にしたまま、すべてのホストマウントとデバイスマッピングを文書化してください。
代わりにVMを選ぶ場合
ワークロードにホストroot相当の制御が必要な場合、特殊なドライバーを読み込む場合、他のワークロードを管理する場合、信頼できない公開入力を受け付ける場合、または広範なファイルシステム権限とネットワーク権限なしでは実行できない場合は、VMを使用します。別のカーネルによって、共有カーネルのコンテナに例外を追加するよりも強固な境界が作られます。
よくある質問
特権LXCは特権Dockerコンテナより安全ですか?
一般的なルールとしては、追加されません。どちらも重要な分離制御が弱まっていますが、権限の露出の仕方は異なります。コンテナのラベルだけに頼らず、UIDマッピング、デバイス、マウント、ケイパビリティ、ネットワークアクセス、AppArmor、seccomp、デーモンAPIを評価してください。
非特権LXC内でDockerを実行すると、別のセキュリティ層が追加されますか?
LXCとProxmoxホストの間にUIDマッピングを追加できますが、LXC内のDockerをネストして実行するには、ネスティング機能、追加のケイパビリティ、ファイルシステムの例外、またはデバイスマッピングが必要になる場合があります。これらの変更によってメリットが相殺されることがあります。ホストからの強力な分離が必要な場合は、VMのほうが明確です。
LAN内限定のホームサービスに非特権コンテナは必要ですか?
別のLANデバイス、脆弱なWebインターフェース、悪意のあるメディアやドキュメント入力、サプライチェーン由来のイメージ、または漏洩した認証情報を介して侵害が発生する可能性がある場合は、必要です。LAN内だけに配置すれば一部の露出は減りますが、ホストrootアクセスが無害になるわけではありません。
最終結論
パッケージ化されたアプリケーションが、明示的に限定した権限と管理者用ホストインターフェースなしで実行できる場合は、Dockerを使用します。サービスにより完全なLinuxシステムが必要で、rootマッピングと制御されたデバイスアクセスを維持できる場合は、非特権LXCを使用します。どちらの設計でも広範なホストroot権限、無制限のソケット、または重要なデータへの書き込みアクセスが必要になる場合は、コンテナの比較をやめ、より強固なVMまたは別マシンの境界の内側にサービスを移してください。
製品比較
もっと読む

CGNAT配下のデバイス向けWireGuardサーバーとメッシュVPNの比較
手間なくデバイスをローミングさせるにはメッシュVPNを使用し、ルーティング、鍵、パブリックエンドポイントを自分で管理したい場合はWireGuardリレーを使用してください。

ギガビットクライアントで10GbE NASを使う場合、まずサーバーとエンドポイントのどちらをアップグレードすべきか?
1台の遅いワークステーションではエンドポイントの経路をアップグレードし、複数のギガビットクライアントが同時に帯域を使い切る場合は、まずNASのアップリンクをアップグレードしてください。

ホームサーバー向け1GbEと2.5GbEの比較:どのワークロードで違いが出る?
軽量なサービスや単一ストリームには1GbEを使用し、定期的な転送や複数のクライアントによる合計速度が約100 MB/sを超えて継続する場合は、2.5GbEに移行します。

