Blog Article
Dockerのネットワークモデルやセキュリティについて

はじめに
Docker では、コンテナ同士を通信させたり、コンテナから外部へ接続したりするためにネットワーク機能を利用します。また、安全に Docker を利用するには、ネットワークだけでなく、コンテナに与える権限やイメージの安全性についても考える必要があります。今回は、 Docker の代表的なネットワークと基本的なセキュリティについて説明します。
参考リンク
- Docker 公式ドキュメント - Networking overview
- Docker 公式ドキュメント - Bridge network driver
- Docker 公式ドキュメント - Host network driver
- Docker 公式ドキュメント - Overlay network driver
- Docker 公式ドキュメント - Docker Engine security
- Docker 公式ドキュメント - Rootless mode
- Docker 公式ドキュメント - Seccomp security profiles
Docker のネットワークとは?
Docker のネットワークは、コンテナがほかのコンテナやホスト、外部のネットワークと通信するための仕組みです。
ここでいう「ホスト」とは、 Docker を動かしているコンピューターのことです。例えば、自分の PC に Docker をインストールしてコンテナを動かしている場合、その PC がホストになります。
また、「ネットワーク」と聞くとインターネットだけを想像するかもしれませんが、 Docker ではコンテナ同士をつなぐこともネットワークに含まれます。
例えば、 Web アプリケーションとデータベースをそれぞれ別のコンテナで動かす場合、次のような通信が必要になります。
ユーザー
│
│ HTTP 通信
↓
Web コンテナ
│
│ データベースへの通信
↓
DB コンテナこのような通信を Docker のネットワーク機能によって管理します。
Docker には複数のネットワーク方式があり、代表的なものとして bridge、host、overlay などがあります。それぞれ、コンテナをどのようにネットワークへ接続するかが異なります。
bridge ネットワーク
bridge は、同じ Docker ホスト上で動作しているコンテナ同士を通信させるために、よく利用されるネットワーク方式です。
「bridge」は日本語にすると「橋」という意味です。その名前のとおり、コンテナ同士をネットワークでつなぐ橋のような役割をします。
Docker をインストールすると、デフォルトで bridge ネットワークが用意されています。
Docker ホスト
┌──────────────────────────┐
│ │
│ bridge ネットワーク │
│ │
│ ┌────────┐ ┌────────┐ │
│ │ web │──│ db │ │
│ │コンテナ │ │コンテナ │ │
│ └────────┘ └────────┘ │
│ │
└──────────────────────────┘このように、同じ bridge ネットワークに接続されたコンテナ同士で通信できます。
ユーザー定義 bridge ネットワーク
Docker では、最初から用意されている bridge だけでなく、自分で bridge ネットワークを作成することもできます。
例えば、次のコマンドを実行します。
docker network create my-networkすると、 my-network という名前のネットワークが作成されます。
続いて、コンテナをこのネットワークに接続して起動できます。
docker run -d --name web --network my-network nginx
docker run -d --name db --network my-network mysqlここで --network my-network は、「このコンテナを my-network というネットワークに接続する」という意味です。
ユーザー定義の bridge ネットワークでは、同じネットワークに接続されたコンテナをコンテナ名で指定して通信できます。
例えば、 web コンテナから db コンテナへ接続する場合、 IP アドレスを直接指定するのではなく、 db という名前を使って接続できます。
web コンテナ
│
│ 「db」という名前で接続
↓
db コンテナこれは、 Docker がコンテナ名を IP アドレスへ変換してくれるためです。
IP アドレスとは、ネットワーク上にあるコンピューターやコンテナを識別するための番号です。例えば 192.168.1.10 のような値です。
このように、コンテナ名を使って通信できるため、アプリケーション側で IP アドレスを直接管理する必要がなくなります。
また、ユーザー定義 bridge ネットワークを利用すると、ネットワーク単位でコンテナを分離しやすくなります。例えば、 Web コンテナと DB コンテナだけを同じネットワークに接続し、それ以外のコンテナとは別のネットワークにすることができます。
Docker 公式ドキュメントでも、デフォルトの bridge よりユーザー定義 bridge ネットワークを利用することが推奨されています。
つまり、 bridge ネットワークは単純に「コンテナ同士をつなぐ」だけではなく、どのコンテナ同士を通信させるのかを整理するためにも利用できます。
host ネットワーク
host ネットワークは、コンテナと Docker ホストのネットワークをほぼ分離せず、そのまま利用する方式です。
ここで出てくる「ネットワーク名前空間」という言葉についても簡単に説明します。
ネットワーク名前空間とは、どのネットワーク機器や IP アドレス、ポートなどが見えるのかを分ける仕組みです。
通常のコンテナでは、コンテナ専用のネットワーク環境が用意されます。
一方、 host ネットワークでは、コンテナがホストと同じネットワーク名前空間を利用します。
そのため、 host ネットワークのコンテナには、通常のコンテナのような独自の IP アドレスが割り当てられません。
イメージすると、次のような違いです。
通常の bridge
ホスト
│
└── コンテナ専用のネットワーク
│
└── コンテナ
host
ホスト
│
└── ホストと同じネットワークをコンテナが利用例えば、コンテナ内のアプリケーションがポート 80 で通信を待ち受けている場合、 host ネットワークではホスト側のポート 80 を直接利用します。
そのため、通常の bridge ネットワークで使用するようなポート転送は必要ありません。
ポートとは、1 台のコンピューターの中で、どのアプリケーションへ通信を届けるのかを区別する番号です。
例えば Web サーバーでは 80 番ポートや 443 番ポートがよく利用されます。
通常の Docker では、次のようにホストの 8080 番ポートからコンテナの 80 番ポートへ通信を転送できます。
docker run -p 8080:80 nginxこれは、
ホストの 8080 番ポート
↓
コンテナの 80 番ポートという関係です。
しかし、 host ネットワークではコンテナがホストのネットワークを直接利用するため、 -p や --publish によるポートマッピングは無視されます。
host ネットワークには、ネットワークアドレス変換などの処理を減らせるという特徴があります。
NAT(Network Address Translation)とは、ネットワーク上の IP アドレスを別の IP アドレスへ変換する仕組みです。
通常の Docker では、ホストとコンテナの間で通信を転送するために、このような処理が関係します。
一方、 host ネットワークではホストのネットワークを直接利用するため、この処理を必要としません。
ただし、ホストとコンテナのネットワークが分離されなくなるため、ネットワークの分離を重視する場合には注意が必要です。
overlay ネットワーク
overlay ネットワークは、複数の Docker ホストにまたがってコンテナ同士を通信させるためのネットワーク方式です。
ここでいう「overlay」は、既存のネットワークの上に、 Docker 用の仮想的なネットワークを作るイメージです。
bridge ネットワークは、基本的に 1 台の Docker ホスト上で利用します。
そのため、例えば次のように Docker ホストが 2 台ある場合、
Docker ホスト A Docker ホスト B
┌──────────────┐ ┌──────────────┐
│ Web コンテナ │ │ DB コンテナ │
└──────────────┘ └──────────────┘bridge ネットワークだけでは、これらを同じ Docker ネットワークとして扱うことはできません。
そこで overlay ネットワークを利用します。
Docker ホスト A Docker ホスト B
┌──────────────┐ ┌──────────────┐
│ Web コンテナ │ │ DB コンテナ │
└──────┬───────┘ └──────┬───────┘
│ │
└──── overlay ネットワーク ────┘このように、Docker ホストをまたいでコンテナ同士を通信させられるのが overlay ネットワークの特徴です。
overlay ネットワークは、特に Docker Swarm のサービス間通信などで利用されます。
Docker Swarm とは、複数の Docker ホストをまとめて管理し、コンテナを複数のホストへ配置・運用するための Docker の機能です。
複数の Docker ホストで overlay ネットワークを利用する場合、 Docker ホストを Swarm に参加させる必要があります。
また、元の記事では「overlay ネットワークは通信を暗号化する」と説明していましたが、これは正確ではありません。
overlay ネットワークの暗号化は自動的に有効になるわけではありません。暗号化された overlay ネットワークを作成する場合は、暗号化オプションを指定する必要があります。
bridge・host・overlay の違い
ここまで説明した 3 つのネットワーク方式を整理すると、次のようになります。
ネットワーク | 主な用途 | 特徴 |
|---|---|---|
| 同じ Docker ホスト上のコンテナ間通信 | コンテナをネットワークに接続して通信させる |
| ホストのネットワークを直接利用 | コンテナとホストのネットワークを分離しない |
| 複数の Docker ホスト間の通信 | ホストをまたいでコンテナを通信させる |
初心者のうちは、まず次の関係を覚えておくと理解しやすいです。
同じ Docker ホスト内
↓
bridge
ホストのネットワークを直接利用
↓
host
複数の Docker ホストをまたぐ
↓
overlayただし、これはあくまで代表的な使い分けです。Docker にはほかにも none、macvlan、ipvlan などのネットワーク方式があります。Docker のセキュリティ
Docker のセキュリティでは、ネットワーク、権限、ファイルへのアクセス、システムコールなどを適切に制限することが重要です。
ここでいう「システムコール」とは、プログラムが OS に処理を依頼するときに使う仕組みです。
例えば、プログラムがファイルを読み込んだり、新しいプロセスを作ったりするときには、 OS の機能を利用します。そのときに使われるのがシステムコールです。
Docker では、このような OS の機能へのアクセスも一定範囲に制限できます。
重要なのは、「コンテナだから完全に安全」というわけではないということです。
Docker コンテナは仮想マシンとは異なります。
仮想マシンでは、それぞれが独立した OS を動かします。一方、 Docker コンテナはホストの Linux カーネルを利用して動作します。
Linux カーネルとは、アプリケーションとコンピューターのハードウェアの間で、 CPU やメモリ、ファイルなどを管理する OS の中心部分です。
つまり、 Docker コンテナはホストから完全に独立したコンピューターではありません。
Docker は Linux の機能を利用して、コンテナから見えるプロセスやネットワークなどを分離したり、利用できる権限を制限したりしています。
コンテナの分離
コンテナでは、ほかのコンテナやホストから見える範囲を一定程度分離できます。
例えば、コンテナごとにプロセスを分けたり、独立したネットワーク環境を用意したりできます。
このような「分離」を実現するために、 Linux の namespace(名前空間) という仕組みが利用されています。
namespace とは、同じ Linux カーネルを利用していても、プロセスから見える世界を分けるための仕組みです。
例えば、コンテナ A からはコンテナ A のプロセスだけが見えていても、ホスト側から見るとコンテナ A のプロセスも含めて確認できます。
ホストから見える世界
┌─────────────────────┐
│ ホストのプロセス │
│ コンテナ A のプロセス │
│ コンテナ B のプロセス │
└─────────────────────┘
コンテナ A から見える世界
┌─────────────────────┐
│ コンテナ A のプロセス │
└─────────────────────┘
このような仕組みによって、コンテナから見える範囲を制限しています。
ただし、 Docker daemon は通常 root 権限で動作するため、 Docker daemon を操作できるユーザーやアプリケーションには注意が必要です。
Docker daemon とは、Docker のコンテナ作成や起動、ネットワークなどを実際に管理しているバックグラウンドのプログラムです。
つまり、 Docker コマンドを実行すると、その要求を Docker daemon が受け取り、実際の処理を行います。
最小権限の原則
Docker のセキュリティでは、必要以上の権限を与えないという考え方が重要です。
これを「最小権限の原則」といいます。
例えば、 Web サーバーとして動作するだけのコンテナに、ホストを自由に操作できるような強い権限を与える必要はありません。
もしアプリケーションに脆弱性があり、攻撃者にコンテナを操作されてしまった場合、コンテナに強い権限を与えているほど、被害が大きくなる可能性があります。
Docker では capabilities(ケーパビリティ) という仕組みを利用して、 Linux の強力な権限を細かく分けて管理できます。
capabilities とは、root が持っている権限をいくつかの種類に分割し、「この権限だけ許可する」という制御を行う仕組みです。
例えば、コンテナに必要のない権限まで与えるのではなく、必要な権限だけを与えることができます。
そのため、コンテナを実行するときは、必要以上の権限を与えないことが重要です。
Rootless mode
Docker には Rootless mode という仕組みもあります。
Rootless は「root 権限なし」という意味です。
通常の Docker では Docker daemon が root 権限で動作しますが、 Rootless mode では Docker daemon とコンテナを一般ユーザーの権限で動作させることができます。
通常
root ユーザー
↓
Docker daemon
↓
コンテナ
Rootless mode
一般ユーザー
↓
Docker daemon
↓
コンテナroot とは、 Linux における非常に強い権限を持つ管理者ユーザーです。
そのため、 root 権限を使わずに Docker を動かすことで、 Docker daemon やコンテナに関連する問題が発生した場合の影響を抑えることが期待できます。
ただし、 Rootless mode を利用すればすべてのセキュリティ問題がなくなるわけではありません。
ネットワーク設定、イメージの安全性、アプリケーションの脆弱性など、ほかの対策も必要です。
seccomp による制限
Docker では seccomp(secure computing mode) という Linux の仕組みも利用できます。
seccomp は、プロセスが利用できるシステムコールを制限する仕組みです。
先ほど説明したように、システムコールはプログラムが OS に処理を依頼するときに使うものです。
つまり seccomp は、
コンテナ内のプログラム
↓
「この OS の機能を使いたい」
↓
システムコール
↓
seccomp で確認
↓
許可されていれば実行というように、コンテナ内のプログラムが OS に対して利用できる機能を制限する役割を持ちます。
Docker にはデフォルトの seccomp プロファイルが用意されており、特定のシステムコールを制限しています。(docs.docker.com)
難しく考えず、「コンテナ内のプログラムが OS にお願いできる処理を制限する仕組み」と考えると分かりやすいです。
安全なベースイメージを選ぶ
Docker イメージには、アプリケーションだけではなく、そのアプリケーションを動かすために必要な OS のパッケージやライブラリなども含まれます。
ここでいう ベースイメージ とは、Docker イメージを作るときの土台になるイメージのことです。
例えば、
FROM ruby:3.4と書いた場合、 ruby:3.4 がその Docker イメージを作るための土台になります。
このベースイメージに古いパッケージや脆弱性のあるソフトウェアが含まれていれば、作成した Docker イメージにもその影響が及ぶ可能性があります。
そのため、イメージを選ぶときは、信頼できる提供元のものを使用し、使用しているパッケージやベースイメージを適切に更新することが重要です。
ただし、公式イメージだから絶対に安全というわけではありません。
公式であることと、そこに含まれるソフトウェアに脆弱性が存在しないことは別の問題だからです。
イメージをスキャンする
Docker のセキュリティでは、イメージに含まれるソフトウェアの脆弱性を確認することも重要です。
脆弱性とは、ソフトウェアに存在するセキュリティ上の弱点のことです。
例えば、アプリケーションそのものに問題がなくても、使用しているライブラリに脆弱性が存在する場合があります。
そのため、 Docker イメージを作成・利用するときには、脆弱性スキャンなどを利用して問題がないか確認します。
そして、脆弱性が見つかった場合には、使用しているパッケージやベースイメージを更新するなどの対応を行います。
重要なのは、一度スキャンすれば終わりではなく、継続的に確認することです。
ネットワークを必要な範囲に制限する
ネットワークの設定もセキュリティに関係します。
例えば、 DB コンテナを Docker で動かしているとします。
Web アプリケーションから DB に接続できればよく、インターネット上のユーザーから DB に直接接続する必要がないのであれば、 DB のポートを外部へ公開する必要はありません。
外部ユーザー
│
↓
Web コンテナ
│
↓
DB コンテナ
DB は外部へ公開しないこのように、外部からアクセスする必要がないサービスは、外部へ公開しないことが重要です。
また、ユーザー定義 bridge ネットワークを利用して、 Web コンテナと DB コンテナだけを同じネットワークに接続することもできます。
必要な通信だけを許可することで、不要なアクセス経路を減らせます。
Docker Content Trust について
以前の Docker では、Docker Content Trust(DCT) という仕組みがイメージの信頼性を確認するために利用されていました。
DCT は、Docker イメージに電子署名を付ける仕組みです。
電子署名とは、簡単にいうと「このイメージが誰によって公開されたものなのか」「途中で変更されていないか」を確認するための仕組みです。
ただし、現在の Docker では DCT の扱いに注意が必要です。
Docker 公式ドキュメントでは Docker Content Trust と Notary v1 が退役対象となっており、 Docker Engine v29 では Docker CLI から DCT が削除されています。
そのため、現在の Docker セキュリティについて学ぶ場合、DCT を現在の主要なセキュリティ対策として覚えるのではなく、過去に利用されていた仕組みとして理解しておくのが適切です。
現在の Docker を安全に利用するうえでは、イメージの信頼性だけでなく、脆弱性の確認、最小権限、 Rootless mode、ネットワークの制御などを組み合わせて考えることが重要です。
まとめ
Docker のネットワークは、コンテナ同士やホスト、外部ネットワークとの通信を管理するための仕組みです。
bridgeは、主に同じ Docker ホスト上のコンテナ同士を通信させるために利用します。- ユーザー定義 bridge ネットワークでは、コンテナ名を使った通信やネットワークの分離ができます。
hostは、コンテナとホストのネットワークを分離せずに利用する方式です。overlayは、複数の Docker ホストにまたがってコンテナを通信させるために利用します。- コンテナは完全に独立した仮想マシンではなく、ホストの Linux カーネルを利用して動作します。
- namespace によって、コンテナから見えるプロセスやネットワークなどを分離します。
- capabilities によって、コンテナに与える権限を細かく制限できます。
- Rootless mode では、 Docker daemon とコンテナを一般ユーザーの権限で動かせます。
- seccomp によって、コンテナ内のプログラムが利用できるシステムコールを制限できます。
- ベースイメージやパッケージの脆弱性を確認し、必要に応じて更新することが重要です。
- 外部から必要のないサービスやポートは、むやみに公開しないことが重要です。
- Docker Content Trust は現在退役が進められているため、現行の主要な対策として扱わないよう注意が必要です。
Docker のネットワークやセキュリティを理解するときは、用語を暗記するだけではなく、「誰と通信できるのか」「どこまで見えるのか」「どのような権限を持っているのか」という視点で考えると理解しやすくなります。