Linux & IT ノート

Docker のボリュームとネットワーク:データ永続化とコンテナ間通信

管理人 約8分で読めます

前回は Dockerfile を書いてコンテナイメージを作る方法を解説しました。 コンテナは便利ですが、一つ大きな落とし穴があります。コンテナを削除するとその中のデータも消えるという点です。

Docker のコンテナは、イメージに書き込みレイヤーを重ねて動作します。コンテナが削除されると、その書き込みレイヤーも一緒に消えます。開発中に起動したデータベースにデータを入れていても、docker rm した瞬間にすべてなくなります。

この記事では、データを永続化するボリュームと、複数コンテナを連携させるネットワークの使い方を解説します。

ボリューム:データをコンテナの外に置く

ボリュームはコンテナのライフサイクルから独立してデータを保存する仕組みです。コンテナが削除されてもボリュームは残り、新しいコンテナからマウントして使い続けられます。

ボリュームには大きく2種類あります。

名前付きボリューム

Docker が管理する専用の領域にデータを保存します。ホストのどこに実体があるか意識しなくてよいのが利点で、本番や CI 環境での利用に向いています。

# ボリュームを作成する
docker volume create mydata

# ボリューム一覧を確認する
docker volume ls

# コンテナ起動時にマウントする(-v ボリューム名:コンテナ内パス)
docker run -d \
  --name mydb \
  -e POSTGRES_PASSWORD=secret \
  -v mydata:/var/lib/postgresql/data \
  postgres:16

-v mydata:/var/lib/postgresql/data で、PostgreSQL のデータディレクトリをボリュームにマウントしています。 これで mydb コンテナを削除しても mydata ボリュームにデータが残ります。

# コンテナを削除してみる
docker rm -f mydb

# 同じボリュームをマウントして新しいコンテナを立ち上げ直す
docker run -d \
  --name mydb \
  -e POSTGRES_PASSWORD=secret \
  -v mydata:/var/lib/postgresql/data \
  postgres:16
# → データはそのまま残っている

バインドマウント

ホストマシンの特定のディレクトリをコンテナにマウントします。ホストとコンテナが同じファイルを共有するため、ホスト側で編集したファイルがリアルタイムでコンテナ内に反映されます。開発中のライブリロードに便利です。

# $(pwd) でカレントディレクトリをコンテナの /app にマウントする
docker run -d \
  -p 3000:3000 \
  -v $(pwd):/app \
  --name devapp \
  myapp:latest

バインドマウントはホストのパスに依存するため、チームで共有するような設定には名前付きボリュームを使うほうが安全です。

使い分けの基準

用途推奨
DB のデータ・ログなどを永続化する名前付きボリューム
開発中にホストのコードをコンテナで動かすバインドマウント
CI/CD やサーバー環境での永続データ名前付きボリューム

ネットワーク:コンテナ同士を会話させる

複数のコンテナ(アプリと DB、など)を連携させるには、ネットワークの設定が必要です。

デフォルトの bridge ネットワーク

コンテナを起動するとデフォルトで bridge ネットワークに接続されます。同じ bridge 上のコンテナ同士は IP アドレスで通信できますが、コンテナ名では名前解決できません。IP は起動のたびに変わる可能性があるため、デフォルト bridge への依存は避けたほうが無難です。

ユーザー定義ネットワーク

自分でネットワークを作ると、同じネットワーク内でコンテナ名による名前解決が使えます。これが Docker でのコンテナ間通信の基本パターンです。

# ネットワークを作成する
docker network create mynet

# ネットワーク一覧を確認する
docker network ls

ネットワークを作ったら、コンテナ起動時に --network で指定します。

# DB コンテナを mynet に接続して起動する
docker run -d \
  --name db \
  --network mynet \
  -e POSTGRES_PASSWORD=secret \
  -v mydata:/var/lib/postgresql/data \
  postgres:16

# アプリコンテナを同じ mynet に接続して起動する
docker run -d \
  --name app \
  --network mynet \
  -p 3000:3000 \
  -e DATABASE_URL="postgres://postgres:secret@db:5432/mydb" \
  myapp:latest

アプリコンテナの DATABASE_URL@db:5432 とコンテナ名(db)を指定しています。 同じユーザー定義ネットワーク内では、コンテナ名がそのまま DNS ホスト名として解決されるためこれが使えます。

ポート公開(-p)との違い

-p 3000:3000 は、ホストマシンのポートをコンテナに転送します。外部からコンテナにアクセスするために使います。

一方、同じネットワーク内のコンテナ間通信は -p が不要です。app コンテナから db コンテナの 5432 番に直接アクセスできます。DB コンテナに -p 5432:5432 を書く必要はなく、むしろ書かないほうがホスト外からの意図しないアクセスを防げます。

実践的なコツ

ボリュームの中身を確認する

名前付きボリュームの実体はホストの /var/lib/docker/volumes/ 以下にありますが、直接触るより一時コンテナでマウントして中身を見るほうが安全です。

# 一時コンテナでボリュームをマウントして中身を確認する
docker run --rm -v mydata:/data busybox ls /data

不要なボリュームを掃除する

ボリュームはコンテナを削除しても残り続けます。docker volume ls で使われていないボリュームが増えたら prune で掃除します。

# どのコンテナにも使われていないボリュームを削除する
docker volume prune

# ネットワークも同様に掃除できる
docker network prune

prune は「使われていないもの」だけ削除するので、稼働中のコンテナのボリュームは消えません。

コンテナのネットワーク設定を確認する

docker inspect でコンテナの詳細な設定(ネットワーク・マウント情報など)を確認できます。

# ネットワーク情報を確認する
docker inspect app --format '{{json .NetworkSettings.Networks}}' | jq .

この例は JSON を整形するために jq を使っています。未インストールの場合は jq を導入するか、| jq . を外して --format だけで確認してください。

まとめ

  • コンテナを削除するとデータも消える。永続化にはボリュームを使う
  • 名前付きボリューム(docker volume create)は Docker が管理する永続ストレージ。DB のデータ保存に向く
  • バインドマウント(-v $(pwd):/app)はホストのディレクトリを共有。開発中のライブ編集に便利
  • ユーザー定義ネットワークを作ると、コンテナ名で名前解決できるためコンテナ間通信が簡単になる
  • ポート公開(-p)は外部向け。ネットワーク内の通信は -p 不要
  • docker volume prune / docker network prune で不要なリソースを定期的に掃除する

ここまでで、コンテナの作成・データ永続化・コンテナ間通信の基礎が揃いました。 次回は Docker Compose を取り上げます。ここまで個別のコマンドで行ってきた複数コンテナの起動・ネットワーク設定・ボリューム定義を、1つの YAML ファイルにまとめて管理する方法を学びます。