Docker を実稼働環境で数か月間実行しても、目に見える問題は発生しません。コンテナーが起動し、アプリが応答し、何も中断されません。次に、1 つの公開されたポートまたは 1 つの誤って設定された権限によって、攻撃者が獲得する必要のない足場が作成されます。 Docker のセキュリティ上の間違いのほとんどは、何か問題が発生するまでは間違いのように見えません。
この記事では、コンテナ環境を危険にさらす具体的な構成と、それぞれの構成が攻撃者に何を可能にするかについて説明し、最後に、独自のセットアップに対して今すぐ実行できるチェックリストを示します。
Docker セキュリティが見た目よりも難しい理由
コンテナは孤立しているように感じます。コンテナを起動すると、独自のプロセス空間が実行され、その内部からは次のコンテナは存在しません。確かに孤立感は得られますが、それは部分的なものにすぎません。コンテナはホストのカーネルを共有します。これは、コンテナ内のプロセスが特定の条件下でホスト システムに完全に到達できることを意味します。
Docker シップは、本番環境の強化ではなく、開発者の利便性を考慮して構成されています。ルートアクセスがオン。すべてのポートはすべてのインターフェイスにバインド可能です。ランタイム監視はありません。ほとんどの開発者はこれらの設定を受け入れ、コンテナを出荷して次に進みます。これは、始めるための合理的なアプローチです。それは完成したセキュリティ体制ではありません。
によると Red Hat の 2024 年の Kubernetes セキュリティ状況レポート, 組織の 67% は、コンテナーまたは Kubernetes のセキュリティ上の懸念により、アプリケーションのデプロイメントを遅延または遅らせました。その摩擦は通常、攻撃によるものではありません。これは、コンテナ設定に組み込まれていない強化が必要であることに気付いたチームからのものです。
コンテナが、開発者のローカル マシンと同じ構成で実稼働環境で実行されているのをよく見かけます。ここで、Docker のセキュリティ上のミスが静かに悪化する傾向があり、何かが監査されるか失敗するまで目に見える兆候はありません。
こうしたギャップを生み出す間違いは、構成レベルから始めて具体的かつ予測可能であり、ほとんどの場合回避可能です。
よくある Docker 構成の間違い
ほとんどのコンテナ侵害はゼロデイエクスプロイトから始まるわけではありません。彼らは、ネットワークへの露出や特権の範囲についてあまり考えずに、初日から構成セットから開始します。
デフォルトの Docker 設定は機能するように構築されています。機能性と安全性の間のギャップは、特にデプロイされても再検討されないセルフホスト型セットアップにおいて、Docker コンテナーのセキュリティ リスクが蓄積する場所です。
このパターンはよく見られます。パブリック IP サーバー上のコンテナーは、初期展開時とまったく同じポート バインディング、ユーザー設定、およびネットワーク構成を持ちます。
コンテナをルートとして実行する
ユーザーを指定せずに Docker コンテナを起動すると、root として実行されます。つまり、アプリケーションを含むコンテナ内のすべてのプロセスは、コンテナの名前空間内で root レベルの権限を持っています。

コンテナ内のルートはホスト上のルートと同じではありませんが、分離は絶対的なものではありません。十分に文書化されている runc CVE-2019-5736 や同様のランタイムの欠陥など、ランタイムをターゲットとした権限昇格エクスプロイトでは、成功するためにルート コンテナー プロセスが必要になることがよくあります。
非ルート コンテナは、これらのエクスプロイトが依存するルート プロセス要件を削除し、そのクラスの脆弱性に対する攻撃対象領域を大幅に狭めますが、コンテナ エスケープのリスクを完全に排除するわけではありません。
USER ディレクティブを Dockerfile に追加すると、この問題に対処できます。一部の公式イメージには、USER ディレクティブでアクティブ化できる非特権ユーザーが同梱されていますが、多くは依然としてデフォルトで root になり、既製のアプリ ユーザーは存在しません。このような場合は、Dockerfile に切り替える前に、Dockerfile にユーザーを作成します。ほとんどの自己ホスト型セットアップでは、この 1 つの変更により、エスカレーション リスクのカテゴリ全体が削除されます。
多すぎるポートをパブリック インターネットに公開する
Docker でポートを公開すると、Docker は独自の iptables ルールを直接作成します。これらのルールは、ホストレベルのファイアウォール ルールより前に実行されます。これは コミュニティによって報告されたよく知られた行為 そして Docker のパケット フィルタリング ガイドに記載されていますこれは構成ミスではなく、UFW や同様のツールが Docker がすでに開いているものをブロックしないことを意味します。

Docker は、多くの Linux ホスト上の UFW および firewalld のデフォルトをバイパスして、iptables に直接書き込みます。つまり、ファイアウォールが構成されているように見えても、0.0.0.0 にバインドされたポートはパブリックにアクセスできる可能性があります。クラウド セキュリティ グループと DOCKER-USER チェーン ルールは依然としてそのトラフィックをブロックする可能性があるため、実際の危険は特定のネットワーク設定によって異なります。
可能な場合はサービスを 127.0.0.1 にバインドし、一般向けのトラフィックをリバース プロキシ経由でルーティングし、本当に外部アクセスが必要なもののみを公開します。リバース プロキシは、ホストの外部から公開されるものを制御する最も信頼できる方法です。
コンテナ間のネットワーク分離の無視
そのネットワーク上のすべてのコンテナは、制限なくそのネットワーク上の他のコンテナにアクセスできます。デフォルトのブリッジは、それを共有するコンテナ間でトラフィック フィルタリングを適用せず、ほとんどのセットアップでその構成が変更されることはありません。

1 つのコンテナが侵害された場合、そのオープンなコミュニケーションが横方向の移動経路になります。フロントエンド コンテナは、アクセスが意図されていない場合でも、データベース、内部 API、または同じデフォルト ブリッジ ネットワーク上のその他のあらゆるものにアクセスできます。
ユーザー定義のネットワークを使用すると、どのコンテナが通信できるかを明示的に制御できますが、すべてのサービスで共有される単一のカスタム ネットワークでは、依然としてコンテナ間の無料トラフィックが許可されます。実際に分離するには、相互に通信すべきではないサービスを別のネットワークに配置する必要があります。デフォルトのブリッジをオフにすることは、終了点ではなく開始点です。
Docker ソケットを見下ろす
/var/run/docker.sock にある Docker ソケットは、Docker エンジン全体の制御インターフェイスです。これをコンテナーにマウントすると、そのコンテナーはホスト上で実行されているデーモンに直接 API アクセスできるようになります。

このアクセスにより、コンテナーは新しいコンテナーの起動、ホスト ディレクトリのマウント、実行中のコンテナーの検査と変更、ホスト マシンの効率的な制御を行うことができます。攻撃対象領域はホスト上の root に相当するため、ソケット アクセスを必要とするツールは慎重に評価する必要があります。
ほとんどのユースケースでは、より安全な代替手段があります: スコープ付き API または Docker管理ツール ソケットアクセスを必要としないもの。 Docker-in-Docker には独自のセキュリティと運用上のトレードオフがあり、単純な代替品ではありません。
設定ミスにより初期の危険が生じます。画像と依存関係の選択によって、時間の経過とともにその危険性がどのように増大するかが決まります。
コンテナを超えて存続するイメージと秘密の間違い
コンテナを停止すると、コンテナ内の構成ミスも停止します。脆弱性またはハードコードされた認証情報を含むイメージから再構築すると、コンテナーで問題が再び発生します。イメージレベルの間違いは、デプロイ間でリセットされません。
彼らは、イメージを取得するすべての環境、イメージを保存するすべてのレジストリ、およびイメージを実行するすべてのチーム メンバーにイメージとともに移動します。この永続性により、イメージとシークレットの管理はリスクの別個のカテゴリとなり、構成とは別に監査する価値があります。
このパターンはよく見られます。プロジェクトの開始時に慎重に選択されたイメージが、それ以降再構築されず、最初に表現されていたセキュリティ ベースラインから徐々に離れていくというパターンです。
信頼できないイメージまたは古いイメージの使用
公開レジストリは誰でも公開されています。悪意のあるイメージは、コンテナーの再起動後も持続するレイヤー履歴に埋め込まれた暗号通貨マイナーやバックドアを含む Docker Hub を通じて配布されています。特に非公式または不明な発行元からの画像の場合は、プルする前の検証が重要です。

別の問題は、古さです。 6 か月前に取得し、それ以来再構築されていない公式イメージには、そのパッケージに対して公開された CVE ごとに、パッチが適用されていない Docker の脆弱性が蓄積されています。イメージが崩れていない。それはもはや最新ではありません。
Sonatype の 2024 年のソフトウェア サプライ チェーンの現状レポート は、95% の確率で脆弱なコンポーネントが使用され、修正バージョンがすでに利用可能であり、アプリケーションの依存関係の 80% が 1 年以上アップグレードされないままであることを発見しました。 Docker ベース イメージは同じオープンソース パッケージに依存しているため、このパターンは Docker ベース イメージにも当てはまります。
「最新」に依存するのではなく、検証済みの発行元からの公式イメージを使用し、特定のバージョンのタグを固定します。イメージを最新の状態に保つために、定期的な再構築の頻度を構築します。
Dockerfile および Compose ファイルでのシークレットのハードコーディング
Dockerfile ENV または ARG 命令に書き込まれた認証情報、Compose 環境ブロックにハードコーディングされた認証情報、ビルド引数として渡された認証情報、またはバージョン管理にコミットされた .env ファイルに保存された認証情報は、コンテナーを停止しても消えません。これらはイメージ レイヤーの履歴またはソース管理に保存され、どちらかにアクセスできる人は誰でもアクセスできます。

これは、開発中に目に見える問題を引き起こさないため、最も見落とされがちな Docker セキュリティ上の間違いの 1 つです。 ENV 命令の API キーは正しく機能します。これはリポジトリ内にもあり、イメージに組み込まれ、イメージが移動する場所であればどこにでも配布されます。
最新の Docker Compose は、資格情報をイメージにベイクせずに実行時にマウントするネイティブ シークレット メカニズムをサポートしています。 Docker のシークレット API と外部シークレット マネージャーは同じ原則に従います。これらは、認証情報がビルド アーティファクトやコミットされたファイルに完全に含まれないようにするオプションです。
ランタイム環境変数はハードコードされた認証情報よりも改善されていますが、依然として Docker 検査の出力、ログ、クラッシュ ダンプを通じて公開されます。これらは、組み込まれた秘密からのステップアップであり、完成したソリューションではありません。
コンテナイメージを定期的に更新しない
同じイメージを何か月も実行するのはよくある習慣です。新しい脆弱性が公開されてから毎日が経過しますが、再構築するまでは、コンテナには目に見える変化が見られずに拡大するエクスポージャ ウィンドウが存在します。
一貫した再構築スケジュールを作成します。可能な場合はそのプロセスを自動化し、現在のイメージに対して脆弱性スキャナーを定期的に実行します。目標は完璧ではありません。パッチがリリースされてから展開されるまでの時間が短縮されています。
アクセス制御と監視は、迅速な導入では優先順位が低くなる可能性があります。これらは、インシデントが最も長期間検出されないカテゴリでもあります。
アクセス制御と可視性のギャップ
コンテナーが安定した構成と現在のイメージで実行された後、2 つのカテゴリーの障害が残ります。どちらも本質的に目に見えないものです。脆弱なアクセス制御の問題は誰かが使用するまで気づかず、監視のギャップはログに記録されていないアクティビティを調査する必要があるまで気づきません。
同じ Red Hat 2024 の調査 チームの 42% には、コンテナのセキュリティと関連する脅威に対処するための十分な能力が欠けていることがわかりました。
監視のギャップは通常、インシデントの調査中に表面化し、それ以前には表面化しないことがわかりました。可視性が優先されるまでに、多くの場合、何かを防ぐのではなく、何かに対応するようになっています。
弱い認証と公開された管理ダッシュボード
認証を行わないパブリック IP 上のコンテナ管理ダッシュボードには、高度な攻撃者は必要ありません。住所を知っている必要があります。これは、ほとんどのチームが認識しているよりも低いハードルです。

セルフホスト型の監視および管理ツールには、通常、すべてのネットワーク インターフェイスでアクセスできる Web インターフェイスが付属しています。認証なしでパブリック IP 上にあるコンテナをそのままにしておくのは、管理パネルのロックを解除したままにするのと同じです。
認証、リバース プロキシ、およびプライベート ネットワークの配置がベースラインです。アクセス制御は、出荷時に有効になっているものではなく、管理インターフェイスに追加する構成手順です。
同じ原則が次の場合にも当てはまります Docker CLI および GUI 管理;デーモンへの管理者レベルのアクセスには、インターフェイスに関係なく同じリスクが伴います。
コンテナの動作を監視していない
コンテナが侵害されると、攻撃者のアクティビティによってプロセスの動作の変化、異常なネットワーク接続、予期しないファイルの変更などの痕跡が作成されます。ログ収集が適切に行われていないと、その証跡は対処できる形式で存在しません。
一元化されたログ収集、コンテナ監査ログ、ランタイム監視ツールにより、異常なアクティビティが悪化する前に検出するためのデータが得られます。目標はすべての行を分析することではありません。調査が必要なときにデータを利用できるようになります。
ログ パイプラインやアラートを使用せずに本番環境でサイレントに実行されるコンテナーのセットアップは、メンテナンスの手間がかかるものではありません。それらは検査されていません。これらは 2 つの異なる動作状態です。
インフラストラクチャ環境も重要な理由
コンテナのセキュリティは構成から始まりますが、構成はインフラストラクチャ上で実行されます。ネットワークの構成が間違っているホスト、共有リソースがあるホスト、またはネットワーク レベルのフィルタリングがないホストは、その上のすべてのコンテナに影響を与える状態を作成します。コンテナーのセットアップとサーバー構成を正しく行うことは、2 つの別個のタスクです。
Docker のセキュリティ ギャップの多くは、コンテナ自体が継承する条件によってさらに増幅されます。
- テナント間でハードウェアを分離しない共有テナント サーバー
- パッチを適用せずに実行されているホスト カーネル
- ネットワークレベルのフィルタリングが組み込まれていないホスト
インフラストラクチャ層に関係なくコンテナの適切な強化が重要であるため、これによって上記の構成手順が不要になるわけではありません。分離されたインフラストラクチャから開始すると、方程式から懸念要素が 1 つ取り除かれます。
Cloudzy では、セットアップの要件に応じて 2 つのパスを提供しています。
- Linux VPS: Docker を自分でデプロイし、この記事の強化手順を適用するためのクリーンな環境
- ポーテナー VPS: Porttainer がプリインストールされたワンクリック オプション。サーバーが起動すると、すでにダッシュボードが表示されます
どちらのオプションも同じインフラストラクチャ上で実行されます。KVM 仮想化、最大 5.7 GHz のブースト クロックの AMD Ryzen 9 CPU、DDR5 メモリ、NVMe SSD ストレージ、最大 40 Gbps のネットワーク、BuyVM フィルタリングによる無料の DDoS 保護が、世界 12 拠点にわたって 99.95% の稼働率 SLA で実行されます。
VPS での Porttainer の実行について詳しくは、専用の記事で説明しています。
Docker デプロイメントのための実践的なセキュリティ チェックリスト
上記の Docker セキュリティ上の間違いは、ほとんどが、一度だけ行われ、再検討されなかった 1 つの構成決定に起因します。このチェックリストを既存の設定に対して実行すると、それらのギャップが見つかります。これは導入ガイドではなく、監査として機能します。
これらの Docker セキュリティのベスト プラクティスでは、上記の最も一般的な構成エラーから Docker コンテナーを保護する方法について説明します。
クイックリファレンス: 9 つの間違いすべて
| 間違い | カテゴリ | 一行修正 |
| rootとして実行 | 構成 | 追加 ユーザー Dockerfile へのディレクティブ |
| 0.0.0.0にバインドされたポート | 構成 | 127.0.0.1 にバインドし、リバース プロキシ経由でルーティングする |
| ネットワーク分離なし | 構成 | アクセスのニーズに基づいて、個別のユーザー定義ネットワーク間でサービスを分割します。 |
| Dockerソケットがマウントされました | 構成 | マウントを取り外します。スコープ指定された API または代替手段を使用する |
| 信頼できないイメージまたは古いイメージ | 画像 | ピン留めされたバージョンタグが付いた公式画像を使用する |
| ハードコードされたシークレット | 画像 | 認証情報をランタイム環境変数またはシークレット マネージャーに移動する |
| イメージ再構築スケジュールなし | 画像 | 毎月の再構築頻度を設定します。可能な限り自動化する |
| 認証されていないダッシュボード | アクセス | 認証を追加し、管理 UI をプライベート ネットワークに移動する |
| コンテナログ収集なし | アクセス | 集中ログとランタイム監視を設定する |
すでにギャップが存在する可能性が最も高い場所にあるため、最初に既存のセットアップに対して実行することをお勧めします。
非 root として実行されているコンテナ: Dockerfile に USER ディレクティブがないか確認してください。存在しない場合、コンテナは root として実行されます。
ポート バインディングはローカルホストまたはプロキシに限定されます。 docker ps を実行し、ポート バインディングを確認します。 0.0.0.0:PORT エントリは、上流のセキュリティ グループ、外部ファイアウォール、または DOCKER-USER チェーン ルールによってブロックされていないホスト上でパブリックにアクセスできます。
使用中のカスタム ブリッジ ネットワーク: Docker のデフォルト ブリッジ上のコンテナは相互に自由にアクセスできます。同じユーザー定義ブリッジ上のコンテナーは引き続き相互に通信できるため、実際に分離するには、信頼境界によってサービスを別々のネットワークに分割します。
Docker ソケットがコンテナーにマウントされていません: ファイルを構成して引数を実行することを確認します。 /var/run/docker.sock がボリュームとして表示される場合は、それが必須であり、意図的なものであることを確認してください。
固定バージョンを持つ検証済みの発行元からの基本イメージ: FROM ubuntu:latest は、不特定の、古い可能性のあるバージョンをプルします。特定のリリースに固定します。
Dockerfile、Compose ファイル、ビルド引数にシークレットはありません。 イメージ レイヤーの履歴には、コンテナーの削除後も資格情報が保持されます。 Compose シークレット、Swarm シークレット、ビルド シークレット マウント、または外部シークレット マネージャーを使用します。ランタイム環境変数はハードコードされた値よりも優れていますが、それでも検査出力とログに表示されます。
イメージ再構築スケジュールが定義されています: 古いイメージには脆弱性が蓄積されます。毎月の再構築頻度により、ほとんどのセットアップで管理可能な露出ウィンドウが維持されます。
認証の背後にある管理インターフェイス: 認証のないパブリック IP 上のダッシュボードはオープン エントリ ポイントです。可能であれば、プライベート ネットワークの配置が望ましいです。
収集されているコンテナログ: ログ パイプラインがない場合、インシデントの検出は目に見えるシステムへの影響に依存します。それは行動するのが遅い信号です。
結論
Docker のデフォルト構成は、セキュリティではなく利便性を目的として構築されています。この記事で取り上げた間違いのほとんどは、高度な攻撃によるものではなく、最初の展開後に変更されなかった設定に遡ります。
修正のほとんどは、USER ディレクティブ、ポート バインディングの変更、カスタム ネットワーク、再構築スケジュールなど、1 回限りの構成決定です。ほとんどのセットアップに新しいツールは必要ありません。
コンテナーの構成を正しく行うことが最初のタスクです。それが動作するインフラストラクチャは 2 番目です。どちらも重要であり、どちらも他方の代わりにはなりません。