Docker ネットワーク構成とセキュリティの実践ガイド

Docker ネットワークの基本概念

コンテナ間の効率的かつ安全な通信を実現するには、Dockerネットワークの仕組みを理解することが重要です。ネットワーク構成は、情報が適切に流れるための基盤となります。

主要な基礎知識

Dockerネットワークは、コンテナの接続と相互作用の方法を定義する重要な要素です。

  1. ネットワーク名前空間: 各コンテナは独立したネットワーク環境(IPアドレス、ルーティングテーブル、ポート番号)を持ちます。
  2. 内部・外部通信: コンテナ間の内部通信と、ポートマッピングによる外部通信が可能です。Dockerはサービス名による自動発見のためのDNSサービスを提供します。
  3. ネットワークドライバ:
    • ブリッジ: 同一ホスト上のコンテナ通信に適したデフォルトドライバ
    • ホスト: コンテナがホストのネットワークを直接利用するモード
    • オーバーレイ: Docker Swarm環境での複数ホスト間通信を可能にするドライバ
  4. ネットワーク設定: コマンドラインまたはComposeファイルによる設定、IPアドレス管理(IPAM)の構成が可能です。
  5. セキュリティと分離: ネットワーク分離によるセキュリティ向上と、ファイアウォールルールによる追加保護が実現できます。

実践ケース:Flaskマイクロサービスの構築

FlaskアプリケーションとRedisサービス間の通信を実現するネットワーク構成の例を示します。

アプリケーションの作成

# web_app.py
from flask import Flask
import redis
import os

application = Flask(__name__)
cache_host = os.getenv('CACHE_HOST', 'localhost')
cache_client = redis.Redis(host=cache_host, port=6379)

@application.route('/')
def index():
    visits = cache_client.incr('visitor_count')
    return f'ようこそ!訪問回数: {visits}回'

if __name__ == '__main__':
    application.run(debug=True, host='0.0.0.0', port=8000)
# 依存パッケージ定義ファイル
flask
redis

Dockerイメージのビルド

FROM python:3.9-alpine
WORKDIR /service
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY web_app.py .
EXPOSE 8000
CMD ["python", "web_app.py"]

ネットワークの構築と実行

# カスタムネットワークの作成
docker network create app-network

# Redisサービスの起動
docker run -d --name cache-service --network app-network redis:alpine

# Flaskアプリケーションのビルドと実行
docker build -t web-service .
docker run -d --name web-service --network app-network -p 8000:8000 web-service

ネットワーク構成の詳細設定

高度なネットワーク設定

プロダクション環境でのネットワーク構成には、より詳細な設定が必要です。

データベース連携の例

# database_app.py
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://db_user:db_pass@database/app_db'
db = SQLAlchemy(app)

class Customer(db.Model):
    customer_id = db.Column(db.Integer, primary_key=True)
    customer_name = db.Column(db.String(100), unique=True, nullable=False)

@app.route('/customers')
def get_customers():
    return jsonify({'status': 'Database connected'})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
# MySQLコンテナの設定
docker run -d --name database \
  --network app-backend \
  -e MYSQL_ROOT_PASSWORD=admin_pass \
  -e MYSQL_DATABASE=app_db \
  -e MYSQL_USER=db_user \
  -e MYSQL_PASSWORD=db_pass \
  mysql:8.0

セキュリティ対策の実装

安全なコンテナ実行

プロダクション環境では、以下のセキュリティ対策が推奨されます。

非特権ユーザーでの実行

FROM python:3.9-slim

# 専用ユーザーの作成
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# 作業ディレクトリの設定と権限変更
WORKDIR /application
RUN chown -R appuser:appgroup /application
USER appuser

COPY --chown=appuser:appgroup requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

COPY --chown=appuser:appgroup . .

CMD ["python", "secure_app.py"]

機密情報の管理

# Swarm環境でのSecret利用
echo "production-api-key-12345" | docker secret create api_secret_key -

# Composeファイルでの定義
version: '3.8'
services:
  api_service:
    image: secure-api:v1
    secrets:
      - api_secret_key
    environment:
      - API_KEY_FILE=/run/secrets/api_secret_key

secrets:
  api_secret_key:
    external: true

ネットワーク分離の実践

サービス間通信の制御

# 公開APIサービス
# public_api.py
from flask import Flask, jsonify
import requests

api = Flask(__name__)

@api.route('/status')
def service_status():
    return jsonify({"service": "operational"})

@api.route('/fetch-data')
def retrieve_data():
    try:
        response = requests.get('http://internal-data-service:9001/data')
        return response.json()
    except Exception as e:
        return jsonify({"error": str(e)}), 503

if __name__ == '__main__':
    api.run(host='0.0.0.0', port=8080)
# ネットワークの分離設定
docker network create public-access
docker network create private-internal

# サービスの分離実行
docker run -d --name public-api \
  --network public-access \
  -p 8080:8080 \
  public-api-service

docker run -d --name internal-service \
  --network private-internal \
  internal-data-service

マルチホスト環境の構成

オーバーレイネットワークの利用

# Swarmクラスタでのネットワーク作成
docker network create \
  --driver overlay \
  --subnet 10.10.0.0/16 \
  --attachable \
  cluster-network

# 分散サービスのデプロイ
docker service create \
  --name distributed-api \
  --network cluster-network \
  --replicas 3 \
  --publish published=80,target=8080 \
  web-application:latest

セキュリティスキャンと監視

コンテナの脆弱性検査

# セキュリティスキャンツールの使用例
# イメージの脆弱性検査
docker scan web-application:latest

# 実行時セキュリティチェック
docker run --security-opt no-new-privileges \
  --read-only \
  --tmpfs /tmp \
  secured-container:latest

監視システムの構築

# 監視用Compose設定例
version: '3.7'
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secure_pass
    ports:
      - "3000:3000"
    depends_on:
      - prometheus

ログ管理の設定

# ログドライバーの指定
docker run -d \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name monitored-app \
  application-service:latest

# ログの確認と分析
docker logs --tail 50 --follow monitored-app

これらの実践を通じて、Docker環境におけるネットワーク構成とセキュリティ対策の重要性を理解できます。適切なネットワーク設計とセキュリティ対策は、本番環境でのアプリケーション運用に不可欠です。

タグ: Docker flask container-networking redis MySQL

7月4日 16:45 投稿