はじめに
Dockerコンテナは軽量で起動が速い反面、コンテナを削除するとその中のデータも消えてしまいます。また、複数のコンテナを連携させるには、コンテナ間でネットワーク通信を行う必要があります。
本記事では、Dockerのデータ永続化(ボリューム・バインドマウント)とネットワーク設定(bridge/hostネットワーク、ポートマッピング)について、基礎から実践的な使い方まで解説します。この記事を読み終えると、以下のことができるようになります。
- ボリュームとバインドマウントの違いを理解し、適切に使い分けられる
docker volumeコマンドでボリュームを作成・管理できる- bridgeネットワークを使ってコンテナ間通信を設定できる
- ポートマッピングでコンテナのサービスを外部に公開できる
前提として、Dockerの基本コマンド(docker run、docker psなど)を理解していることを想定しています。まだ基本コマンドに不安がある場合は、Docker基本コマンド完全ガイドを参照してください。
Dockerにおけるデータ永続化の重要性
コンテナのデータは消える
Dockerコンテナには書き込み可能なレイヤー(Writable Layer)があり、コンテナ内でファイルを作成・編集できます。しかし、この書き込み可能レイヤーはコンテナと運命を共にします。
flowchart TD
subgraph Container["コンテナ実行中"]
subgraph WritableLayer["書き込み可能レイヤー"]
AppData["アプリケーションが生成したデータ"]
LogFiles["ログファイル"]
DBData["データベースのデータ ← 消える"]
end
subgraph ReadOnlyLayer["読み取り専用レイヤー (イメージ)"]
OS["OS, ライブラリ, アプリコード"]
end
end
Container -->|"docker rm (コンテナ削除)"| Lost["書き込み可能レイヤーのデータは完全に消失"]例えば、データベースコンテナを起動してデータを蓄積しても、docker rmでコンテナを削除すると、すべてのデータが失われます。
データ永続化が必要なユースケース
以下のような場面では、コンテナの外部にデータを保存する必要があります。
| ユースケース | 具体例 |
|---|---|
| データベース | MySQL、PostgreSQL、MongoDBのデータファイル |
| アップロードファイル | ユーザーがアップロードした画像や文書 |
| ログファイル | アプリケーションログ、アクセスログ |
| 設定ファイル | アプリケーションの設定を外部から注入 |
| 開発時のソースコード | ホストで編集したコードをコンテナに反映 |
Dockerでは、この問題を解決するためにボリュームとバインドマウントという2つの仕組みを提供しています。
ボリュームとバインドマウントの違い
Dockerには主に3種類のデータ永続化方法があります。
| 方式 | 管理者 | 用途 |
|---|---|---|
| ボリューム(Volume) | Docker | 本番環境でのデータ永続化 |
| バインドマウント(Bind Mount) | ユーザー | 開発環境でのソースコード共有 |
| tmpfsマウント | メモリ | 一時的な機密データの保存 |
本記事では、最もよく使われるボリュームとバインドマウントに焦点を当てます。
flowchart TB
subgraph Volume["ボリューム - Dockerが管理する領域に保存"]
direction LR
HostVolume["ホスト\n/var/lib/docker/\nvolumes/myvolume/_data/\n(※Dockerが自動管理)"]
ContainerVolume["コンテナ\n/data"]
HostVolume <--> ContainerVolume
end
subgraph BindMount["バインドマウント - ホストの任意のディレクトリをマウント"]
direction LR
HostBind["ホスト\n/home/user/myproject/src/\n(※ユーザーが直接管理)"]
ContainerBind["コンテナ\n/app"]
HostBind <--> ContainerBind
endボリュームの特徴
ボリュームはDockerによって完全に管理されるデータ保存領域です。
メリット
- Docker CLIやAPIで簡単に管理できる
- Linux/Windowsの両方で動作する
- 複数のコンテナ間で安全に共有できる
- ボリュームドライバーを使ってリモートストレージやクラウドに保存できる
- バックアップや移行が容易
デメリット
- ホストから直接ファイルにアクセスしにくい
バインドマウントの特徴
バインドマウントは、ホストマシンの任意のディレクトリをコンテナにマウントします。
メリット
- ホストとコンテナでファイルをリアルタイムに共有できる
- 開発時にソースコードの変更を即座にコンテナに反映できる
- 設定ファイルをホストから注入しやすい
デメリット
- ホストのディレクトリ構造に依存する(ポータビリティが低い)
- ホストのファイルシステムへの書き込みアクセスを許可するため、セキュリティリスクがある
ボリュームの作成と利用方法
ボリュームの基本操作
ボリュームはdocker volumeコマンドで管理します。
ボリュームの作成
|
|
実行結果の例:
DRIVER VOLUME NAME
local my-data
ボリュームの詳細確認
|
|
実行結果の例:
|
|
Mountpointが実際にデータが保存されるホスト上のパスです。ただし、Docker Desktopを使用している場合、このパスはLinux VM内のパスであり、ホストから直接アクセスすることは想定されていません。
コンテナにボリュームをマウントする
ボリュームをコンテナにマウントするには、--mountフラグまたは-vフラグを使用します。--mountフラグの方が明示的で推奨されています。
–mountフラグを使用する場合(推奨)
|
|
-vフラグを使用する場合
|
|
どちらのコマンドも、my-dataボリュームをコンテナ内の/usr/share/nginx/htmlにマウントします。
実践例: MySQLのデータを永続化する
データベースはデータ永続化の典型的なユースケースです。以下の例では、MySQLコンテナのデータをボリュームに保存します。
|
|
この設定により、コンテナを削除してもデータはmysql-dataボリュームに保持されます。
|
|
ボリュームの削除
使用しなくなったボリュームは、明示的に削除する必要があります。
|
|
注意: ボリュームを削除すると、中のデータは完全に失われます。本番環境では、削除前に必ずバックアップを取得してください。
バインドマウントの使い方
バインドマウントの基本
バインドマウントは、ホストの任意のディレクトリをコンテナにマウントします。開発環境でソースコードを共有する際によく使用されます。
–mountフラグを使用する場合(推奨)
|
|
-vフラグを使用する場合
|
|
Windowsの場合は、パスの指定方法が異なります。
|
|
–mountと-vの違い
--mountと-vには重要な違いがあります。
| 項目 | –mount | -v |
|---|---|---|
| 存在しないパスの扱い | エラーになる | 自動的にディレクトリを作成する |
| 構文 | 明示的(key=value形式) | 簡潔だが暗黙的 |
| 推奨度 | 推奨 | 互換性のために残されている |
|
|
明示的にエラーを検出したい場合は--mountを使用することをお勧めします。
実践例: 開発環境でのソースコード共有
Node.jsアプリケーションの開発で、ホストのソースコードをコンテナに共有する例です。
|
|
この設定により、ホストでソースコードを編集すると、即座にコンテナ内に反映されます。ホットリロードを備えたフレームワーク(Vite、Next.jsなど)と組み合わせると、効率的な開発環境を構築できます。
読み取り専用でマウントする
セキュリティを高めるため、コンテナからの書き込みが不要な場合は読み取り専用でマウントできます。
|
|
Dockerネットワークの基礎
なぜネットワークが必要か
現代のアプリケーションは、複数のサービスで構成されることが一般的です。例えば、Webアプリケーション、データベース、キャッシュサーバーなどを連携させる必要があります。Dockerネットワークは、これらのコンテナ間で安全に通信するための仕組みを提供します。
flowchart TB
subgraph DockerNetwork["Docker Network"]
WebApp["Web App\n(nginx)\nPort 80"]
Database["Database\n(postgres)\nPort 5432"]
Redis["Redis\n(cache)\nPort 6379"]
WebApp --> Database
Redis --> Database
end
External["外部アクセス\nhttp://localhost:8080"] -->|"ポートマッピング (8080:80)"| WebAppネットワークドライバーの種類
Dockerは複数のネットワークドライバーを提供しています。
| ドライバー | 説明 | 用途 |
|---|---|---|
| bridge | デフォルトのネットワーク。コンテナ間で通信可能 | 単一ホストでの一般的な使用 |
| host | ホストのネットワークを直接使用 | 高パフォーマンスが必要な場合 |
| none | ネットワーク接続なし | 完全に隔離されたコンテナ |
| overlay | 複数のDockerホスト間で通信 | Docker Swarm環境 |
本記事では、最もよく使われるbridgeとhostについて解説します。
デフォルトbridgeネットワークの特徴
Dockerをインストールすると、bridgeという名前のデフォルトネットワークが自動的に作成されます。--networkオプションを指定せずにコンテナを起動すると、このデフォルトbridgeネットワークに接続されます。
|
|
実行結果の例:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
g7h8i9j0k1l2 host host local
m3n4o5p6q7r8 none null local
デフォルトbridgeネットワークの制限
デフォルトbridgeネットワークには重要な制限があります。
- コンテナ間でIPアドレスでの通信は可能
- コンテナ名での名前解決ができない
|
|
この制限を解消するには、ユーザー定義bridgeネットワークを使用します。
ユーザー定義bridgeネットワークの作成と活用
ユーザー定義bridgeネットワークは、デフォルトbridgeネットワークより優れた機能を提供します。
ユーザー定義bridgeネットワークの利点
- コンテナ名で自動的に名前解決ができる
- より良い分離性(異なるネットワークのコンテナは通信できない)
- コンテナを停止せずにネットワークに接続・切断できる
- ネットワークごとに個別の設定が可能
ネットワークの作成と使用
|
|
ユーザー定義ネットワークでは、コンテナ名(この例ではdb)で自動的に名前解決が行われます。
実践例: WebアプリケーションとデータベースのNetwork構成
実際のアプリケーション構成を模した例を見てみましょう。
|
|
この構成では、webappコンテナはpostgresというホスト名でデータベースに接続できます。
hostネットワークドライバー
hostネットワークドライバーを使用すると、コンテナはホストのネットワークスタックを直接使用します。ネットワーク分離がなくなり、コンテナのポートがそのままホストのポートになります。
|
|
hostネットワークの特徴
- ネットワークのオーバーヘッドが最小限
- ポートマッピングが不要(コンテナのポート80がそのままホストのポート80になる)
- コンテナのネットワーク分離がなくなる
注意: hostネットワークはLinuxでのみ完全に動作します。Docker Desktop(Windows/macOS)では、LinuxVM内のネットワークがhostになるため、期待通りに動作しない場合があります。
ポートマッピングの仕組み
ポートマッピングとは
デフォルトでは、bridgeネットワーク上のコンテナのポートはDockerホストの外部からアクセスできません。外部からアクセスを許可するには、**ポートマッピング(ポート公開)**を設定する必要があります。
flowchart LR
subgraph DockerHost["Docker Host"]
subgraph Network["Docker Network (bridge)"]
Container["コンテナ\nnginx (Port 80)"]
end
end
Client["外部クライアント"] -->|"Port 8080"| DockerHost
DockerHost -->|"8080:80\nホスト側:コンテナ側"| Containerポートマッピングの指定方法
-pまたは--publishフラグを使用してポートをマッピングします。
基本的なポートマッピング
|
|
この設定により、http://localhost:8080でnginxにアクセスできます。
複数ポートのマッピング
|
|
特定のIPアドレスにバインド
|
|
UDPポートのマッピング
|
|
ポートマッピングの書式一覧
| 書式 | 説明 |
|---|---|
-p 8080:80 |
ホストの8080番ポートをコンテナの80番ポートにマッピング(TCP) |
-p 192.168.1.100:8080:80 |
特定のホストIPアドレスにバインド |
-p 8080:80/udp |
UDPポートをマッピング |
-p 8080:80/tcp -p 8080:80/udp |
同じポートでTCPとUDPの両方をマッピング |
実践例: Webサーバーの公開
nginxコンテナを起動し、外部からアクセス可能にする例です。
|
|
ブラウザでhttp://localhost:8080にアクセスすると、「Hello Docker!」と表示されます。
Docker Composeでの設定
ボリュームとネットワークは、Docker Composeでも簡潔に定義できます。
|
|
この設定では、以下が自動的に行われます。
db-dataという名前のボリュームが作成され、PostgreSQLのデータが永続化されるapp-networkというbridgeネットワークが作成されるwebコンテナからdbというホスト名でPostgreSQLに接続できる- ホストのポート8080がWebサーバーに公開される
まとめ
本記事では、Dockerのデータ永続化とネットワーク設定について解説しました。
データ永続化のポイント
| 方式 | 推奨用途 |
|---|---|
| ボリューム | 本番環境でのデータベース、ファイルストレージ |
| バインドマウント | 開発環境でのソースコード共有 |
ネットワーク設定のポイント
| 要素 | 推奨設定 |
|---|---|
| コンテナ間通信 | ユーザー定義bridgeネットワーク(名前解決が自動) |
| 外部公開 | ポートマッピング(-p ホスト:コンテナ) |
| 本番環境 | ユーザー定義ネットワークで分離 |
これらの知識を活用することで、データを安全に永続化し、複数のコンテナを連携させたアプリケーション環境を構築できるようになります。
次のステップとして、Docker Compose入門で複数コンテナの管理を学ぶことをお勧めします。