序論:コンテナ間通信とデータ管理の核心

Dockerを活用したアプリケーションデプロイにおいて最も重要な2つのテーマがネットワークボリュームです。複数のコンテナで構成されるマイクロサービスアーキテクチャでは、コンテナ間の通信が必須であり、コンテナが削除されてもデータが維持される必要がある状況は非常によくあります。

今回の第5編では、Dockerのネットワークモデルとボリュームシステムを深く掘り下げ、実際の運用環境で活用できる実践的な例を一緒に見ていきます。

1. Dockerネットワーク概要

1.1 Dockerネットワークの必要性

コンテナは基本的に隔離された環境で実行されます。しかし、実際のアプリケーションではWebサーバーがデータベースと通信し、APIゲートウェイが複数のマイクロサービスと接続される必要があります。Dockerネットワークは、このようなコンテナ間通信を安全かつ効率的に管理できるようにしてくれます。

1.2 ネットワーク関連の基本コマンド

# ネットワーク一覧表示
docker network ls

# ネットワーク詳細情報確認
docker network inspect [ネットワーク名]

# ネットワーク作成
docker network create [ネットワーク名]

# ネットワーク削除
docker network rm [ネットワーク名]

# 使用していないネットワークの一括削除
docker network prune

2. Dockerネットワークの種類

2.1 Bridgeネットワーク(デフォルト)

Bridgeネットワークは Dockerのデフォルトネットワークドライバーで、同じホスト内でコンテナ同士が通信できるようにします。Dockerをインストールすると自動的にdocker0というブリッジネットワークが作成されます。

# デフォルトのbridgeネットワークでコンテナを実行
docker run -d --name web1 nginx

# デフォルトのbridgeネットワーク情報を確認
docker network inspect bridge

特徴:

  • 同一ホストのコンテナ間通信をサポート
  • ホストとコンテナ間でNAT(Network Address Translation)を使用
  • ポートマッピング(-pオプション)で外部アクセスを許可
  • デフォルトのbridgeではコンテナ名での通信は不可(IPのみ可能)

2.2 Hostネットワーク

Hostネットワークはコンテナがホストのネットワークスタックを直接使用します。ネットワーク分離がないためパフォーマンスは良いですが、セキュリティ上の注意が必要です。

# hostネットワークでコンテナを実行
docker run -d --network host --name web-host nginx

# 別途ポートマッピングなしでホストの80番ポートから直接アクセス可能

特徴:

  • ホストと同一のネットワーク環境を使用
  • NATオーバーヘッドがなくネットワークパフォーマンスが優れている
  • ポートマッピング不要(ホストポートを直接使用)
  • Linuxでのみ完全サポート(macOS、Windowsは制限あり)

2.3 Noneネットワーク

Noneネットワークはコンテナのネットワークを完全に無効化します。ネットワークが全く必要ないバッチ処理やセキュリティが重要な環境で使用します。

# noneネットワークでコンテナを実行
docker run -d --network none --name isolated alpine sleep 3600

# ネットワークインターフェース確認(loのみ存在)
docker exec isolated ip addr

特徴:

  • ネットワークインターフェースなし(loopbackのみ存在)
  • 外部通信を完全に遮断
  • 最高レベルのネットワーク分離

2.4 Overlayネットワーク

Overlayネットワークは複数のDockerホストにまたがってコンテナ間通信を可能にします。Docker SwarmやKubernetesなどのクラスター環境で必須です。

# Swarmモードを有効化する必要あり
docker swarm init

# overlayネットワーク作成
docker network create -d overlay my-overlay-network

# overlayネットワークでサービス作成
docker service create --name web --network my-overlay-network nginx

特徴:

  • 複数ホスト間のコンテナ通信をサポート
  • VXLAN技術を使用した仮想ネットワーク
  • Swarmモードで自動サービスディスカバリ
  • 内蔵のロードバランシング機能

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

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

デフォルトのbridgeネットワークの代わりにユーザー定義bridgeネットワークを使用すると、いくつかの利点があります。

# ユーザー定義ネットワーク作成
docker network create my-app-network

# 特定のサブネットとゲートウェイを指定
docker network create \
    --driver bridge \
    --subnet 172.20.0.0/16 \
    --gateway 172.20.0.1 \
    my-custom-network

# ネットワークにコンテナを接続
docker run -d --name db --network my-app-network mysql:8.0
docker run -d --name web --network my-app-network nginx

ユーザー定義ネットワークの利点:

  • 自動DNS解決: コンテナ名で通信可能
  • より良い分離: 他のネットワークのコンテナと自動的に分離
  • 動的接続: 実行中のコンテナをネットワークに接続/切断可能
  • 設定可能: サブネット、ゲートウェイ、IP範囲などをカスタマイズ

3.2 コンテナ名で通信する

# ユーザー定義ネットワーク作成
docker network create app-net

# MySQLコンテナ実行
docker run -d \
    --name mysql-db \
    --network app-net \
    -e MYSQL_ROOT_PASSWORD=secret \
    mysql:8.0

# Webアプリケーションからmysql-dbという名前でアクセス可能
docker run -d \
    --name webapp \
    --network app-net \
    -e DB_HOST=mysql-db \
    my-webapp:latest

4. コンテナ間通信

4.1 同一ネットワーク内の通信

# ネットワーク作成
docker network create backend

# 2つのコンテナを同じネットワークに接続
docker run -d --name server1 --network backend alpine sleep 3600
docker run -d --name server2 --network backend alpine sleep 3600

# server1からserver2へpingテスト
docker exec server1 ping -c 3 server2

4.2 複数のネットワークに接続

1つのコンテナを複数のネットワークに接続できます。これはプロキシやゲートウェイの役割を果たすコンテナに便利です。

# 2つのネットワークを作成
docker network create frontend
docker network create backend

# データベースはbackendのみに接続
docker run -d --name db --network backend mysql:8.0

# Webサーバーはfrontendに接続
docker run -d --name web --network frontend nginx

# APIサーバーは両方のネットワークに接続
docker run -d --name api --network frontend node:18
docker network connect backend api

4.3 ネットワーク接続と切断

# 実行中のコンテナをネットワークに接続
docker network connect my-network container-name

# ネットワークからコンテナを切断
docker network disconnect my-network container-name

# 特定のIPアドレスで接続
docker network connect --ip 172.20.0.100 my-network container-name

5. DNSとサービスディスカバリ

5.1 内蔵DNSサーバー

Dockerはユーザー定義ネットワークで内蔵DNSサーバー(127.0.0.11)を提供します。これにより、コンテナ名やネットワークエイリアスで他のコンテナを見つけることができます。

# DNS設定確認
docker exec webapp cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:0

5.2 ネットワークエイリアス(Alias)

# ネットワークエイリアス設定
docker run -d \
    --name mysql-primary \
    --network app-net \
    --network-alias db \
    --network-alias database \
    mysql:8.0

# dbまたはdatabaseという名前でもアクセス可能
docker run --rm --network app-net alpine ping -c 2 db

5.3 ラウンドロビンDNS

同じネットワークエイリアスを持つ複数のコンテナがある場合、Docker DNSはラウンドロビン方式でIPを返します。

# 同じエイリアスで複数のWebサーバーを実行
docker run -d --name web1 --network app-net --network-alias webserver nginx
docker run -d --name web2 --network app-net --network-alias webserver nginx
docker run -d --name web3 --network app-net --network-alias webserver nginx

# webserverにリクエストすると3つのコンテナのいずれかに接続
docker run --rm --network app-net alpine nslookup webserver

6. データ永続性の重要性

6.1 コンテナの揮発性

コンテナは本質的に揮発的(ephemeral)です。コンテナが削除されると、コンテナ内部に保存されたすべてのデータも一緒に消えます。これはデータベース、ユーザーアップロードファイル、設定ファイルなどの重要なデータを扱う場合、深刻な問題になります。

# コンテナ内部にファイルを作成
docker run -d --name temp-container alpine sh -c "echo 'important data' > /data.txt && sleep 3600"
docker exec temp-container cat /data.txt  # important data

# コンテナ削除
docker rm -f temp-container

# 新しいコンテナにはデータがない
docker run --rm alpine cat /data.txt  # エラー:ファイルなし

6.2 データ永続性が必要な場合

  • データベース: MySQL、PostgreSQL、MongoDBなどのデータファイル
  • ユーザーアップロード: 画像、ドキュメントなどユーザーがアップロードしたファイル
  • ログファイル: アプリケーションログ、アクセスログ
  • 設定ファイル: アプリケーション設定、証明書
  • セッションデータ: キャッシュ、セッションストレージ

7. Dockerボリュームの種類

7.1 Volumes(管理型ボリューム)

Dockerが管理するボリュームで、最も推奨される方式です。ボリュームはDockerの保存領域(/var/lib/docker/volumes/)に作成されます。

# ボリューム作成
docker volume create my-data

# ボリューム一覧表示
docker volume ls

# ボリューム詳細情報
docker volume inspect my-data

# ボリュームを使用してコンテナを実行
docker run -d \
    --name db \
    -v my-data:/var/lib/mysql \
    mysql:8.0

# または--mountフラグを使用(より明示的)
docker run -d \
    --name db \
    --mount source=my-data,target=/var/lib/mysql \
    mysql:8.0

Volumesの利点:

  • Docker CLIで簡単に管理(バックアップ、マイグレーション)
  • LinuxとWindowsコンテナの両方で動作
  • 複数のコンテナ間で安全に共有可能
  • ボリュームドライバーを通じてリモートストレージ、暗号化をサポート
  • ホストのファイルシステム構造から独立

7.2 Bind Mounts

ホストの特定のパスをコンテナにマウントします。開発環境でソースコードをコンテナにリアルタイムで反映する時に便利です。

# ホストディレクトリをコンテナにマウント
docker run -d \
    --name web \
    -v /home/user/website:/usr/share/nginx/html \
    nginx

# --mountフラグを使用(より明示的)
docker run -d \
    --name web \
    --mount type=bind,source=/home/user/website,target=/usr/share/nginx/html \
    nginx

# 読み取り専用でマウント
docker run -d \
    --name web \
    -v /home/user/website:/usr/share/nginx/html:ro \
    nginx

Bind Mountsの特徴:

  • ホストの正確なパス指定が必要
  • ホストファイルシステムに直接アクセス
  • 開発環境でのソースコードリアルタイム反映に適している
  • ホストディレクトリが存在しない場合は自動作成(注意が必要)

7.3 tmpfs Mounts

tmpfsはホストのメモリにデータを保存します。機密情報を一時的に保存したり、高パフォーマンスが必要な時に使用します。

# tmpfsマウントを使用
docker run -d \
    --name cache \
    --tmpfs /app/cache \
    my-app:latest

# --mountフラグを使用
docker run -d \
    --name secure-app \
    --mount type=tmpfs,destination=/run/secrets,tmpfs-size=64m \
    my-app:latest

tmpfsの特徴:

  • メモリにのみ保存されるため非常に高速
  • コンテナ終了時にデータが自動削除
  • 機密データ(パスワード、APIキー)の一時保存に適している
  • Linuxでのみサポート

8. ボリュームの作成と管理

8.1 ボリュームの作成と確認

# 基本ボリューム作成
docker volume create app-data

# ラベルを含むボリューム作成
docker volume create \
    --label project=myapp \
    --label env=production \
    myapp-data

# すべてのボリュームを確認
docker volume ls

# ラベルでフィルタリング
docker volume ls --filter label=project=myapp

# 特定のボリュームの詳細情報
docker volume inspect app-data

8.2 ボリュームの削除

# 特定のボリュームを削除(使用中でない場合のみ)
docker volume rm app-data

# 使用していないすべてのボリュームを削除
docker volume prune

# フィルターと一緒に削除
docker volume prune --filter label=env=development

8.3 ボリュームの共有

# ボリューム作成
docker volume create shared-data

# 複数のコンテナで同じボリュームを使用
docker run -d --name writer -v shared-data:/data alpine sh -c "while true; do date >> /data/log.txt; sleep 5; done"
docker run -d --name reader -v shared-data:/data:ro alpine tail -f /data/log.txt

9. ボリュームドライバー

9.1 ローカルドライバーオプション

# NFSボリューム作成
docker volume create \
    --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.100,rw \
    --opt device=:/path/to/share \
    nfs-volume

# 特定のファイルシステムタイプでボリューム作成
docker volume create \
    --driver local \
    --opt type=ext4 \
    --opt device=/dev/sdb1 \
    ext4-volume

9.2 サードパーティボリュームドライバー

様々なサードパーティボリュームドライバーを使用して、クラウドストレージや分散ファイルシステムを活用できます。

  • Amazon EBS: AWSのElastic Block Store
  • Azure File Storage: Microsoft Azureのファイルストレージ
  • GlusterFS: 分散ファイルシステム
  • Portworx: エンタープライズコンテナストレージ
  • REX-Ray: 様々なストレージプラットフォームをサポート

10. データのバックアップと復元

10.1 ボリュームのバックアップ

# 一時的なコンテナを使用したボリュームバックアップ
docker run --rm \
    -v my-data:/source:ro \
    -v $(pwd):/backup \
    alpine tar cvf /backup/my-data-backup.tar -C /source .

# 圧縮バックアップ
docker run --rm \
    -v my-data:/source:ro \
    -v $(pwd):/backup \
    alpine tar czvf /backup/my-data-backup.tar.gz -C /source .

10.2 ボリュームの復元

# 新しいボリューム作成
docker volume create my-data-restored

# バックアップから復元
docker run --rm \
    -v my-data-restored:/target \
    -v $(pwd):/backup \
    alpine tar xvf /backup/my-data-backup.tar -C /target

10.3 コンテナ間のボリューム複製

# ソースボリュームからターゲットボリュームに複製
docker run --rm \
    -v source-volume:/source:ro \
    -v target-volume:/target \
    alpine cp -av /source/. /target/

10.4 データベースバックアップの例

# MySQLデータベースバックアップ
docker exec mysql-container mysqldump -u root -p'password' --all-databases > backup.sql

# PostgreSQLデータベースバックアップ
docker exec postgres-container pg_dumpall -U postgres > backup.sql

# MongoDBデータベースバックアップ
docker exec mongo-container mongodump --archive --gzip > backup.gz

11. 実践例:Webアプリケーションスタック

11.1 ネットワークとボリュームを活用した完全なスタック

# ネットワーク作成
docker network create webapp-network

# ボリューム作成
docker volume create mysql-data
docker volume create webapp-uploads

# MySQLデータベース
docker run -d \
    --name mysql \
    --network webapp-network \
    -v mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=rootpass \
    -e MYSQL_DATABASE=webapp \
    -e MYSQL_USER=appuser \
    -e MYSQL_PASSWORD=apppass \
    mysql:8.0

# Webアプリケーション
docker run -d \
    --name webapp \
    --network webapp-network \
    -v webapp-uploads:/app/uploads \
    -e DB_HOST=mysql \
    -e DB_USER=appuser \
    -e DB_PASSWORD=apppass \
    -e DB_NAME=webapp \
    -p 3000:3000 \
    my-webapp:latest

# Nginxリバースプロキシ
docker run -d \
    --name nginx \
    --network webapp-network \
    -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
    -p 80:80 \
    nginx:alpine

11.2 Docker Composeで管理

# docker-compose.yml
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    networks:
      - webapp-network
    volumes:
      - mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: webapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass

  webapp:
    image: my-webapp:latest
    networks:
      - webapp-network
    volumes:
      - webapp-uploads:/app/uploads
    environment:
      DB_HOST: mysql
      DB_USER: appuser
      DB_PASSWORD: apppass
      DB_NAME: webapp
    depends_on:
      - mysql

  nginx:
    image: nginx:alpine
    networks:
      - webapp-network
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "80:80"
    depends_on:
      - webapp

networks:
  webapp-network:
    driver: bridge

volumes:
  mysql-data:
  webapp-uploads:

12. ネットワークおよびボリュームのベストプラクティス

12.1 ネットワークのベストプラクティス

  • ユーザー定義ネットワークを使用: デフォルトのbridgeの代わりにユーザー定義ネットワークを使用して、DNS解決と分離の利点を活用
  • 必要なポートのみ公開: -pオプションで外部に公開するポートを最小限に
  • サービスごとにネットワークを分離: フロントエンド、バックエンド、データベースなどを別々のネットワークに分離
  • ネットワークエイリアスを活用: 柔軟なサービスディスカバリのためにエイリアスを使用

12.2 ボリュームのベストプラクティス

  • namedボリュームを使用: 匿名ボリュームの代わりに名前付きボリュームを使用して管理しやすさを確保
  • 開発時はbind mount、本番環境ではvolumeを使用: 環境に合ったマウント方式を選択
  • 定期的なバックアップ: 重要なデータは必ず定期的にバックアップ
  • 読み取り専用マウント: 設定ファイルなど変更が不要なデータは:roオプションを使用
  • 使用していないボリュームの整理: docker volume pruneで定期的に整理

まとめ

Dockerネットワークとボリュームはコンテナベースのアプリケーションのコアコンポーネントです。適切なネットワーク構成でコンテナ間の安全で効率的な通信を保証し、正しいボリューム戦略でデータの永続性と安全性を確保できます。

今回学んだ内容をまとめると:

  • Dockerネットワークの種類(bridge、host、none、overlay)とそれぞれの用途
  • ユーザー定義ネットワークの利点とDNSベースのサービスディスカバリ
  • ボリューム、bind mount、tmpfsの違いと適切な使用シナリオ
  • データのバックアップと復元戦略

次回の第6編では、いよいよKubernetesの基礎を扱います。Kubernetesがなぜ必要なのか、そのアーキテクチャはどのように構成されているのか、コアオブジェクトは何かを見ていきます。