Docker ComposeでPythonとデータベースを連携

プログラミング

Docker ComposeによるPythonとデータベース連携:実践ガイド

Docker Composeは、複数のDockerコンテナを定義し、実行するためのツールです。これにより、Pythonアプリケーションとその依存関係にあるデータベース(例: PostgreSQL, MySQL, Redis)を、単一のコマンドでまとめて管理できるようになります。本稿では、Docker Composeを用いてPythonアプリケーションとデータベースを連携させるための具体的な方法、構成要素、そして運用上の注意点について、詳しく解説します。

Docker Composeの基本構成

Docker Composeの核となるのは、docker-compose.ymlという名前のYAMLファイルです。このファイルに、サービス(コンテナ)、ネットワーク、ボリュームなどの設定を記述します。Pythonアプリケーションとデータベースを連携させる場合、最低限以下の2つのサービスを定義する必要があります。

Pythonアプリケーションサービス

Pythonアプリケーションを実行するためのサービスを定義します。ここでは、python_appというサービス名を例に説明します。

services:
  python_app:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DATABASE_URL: postgresql://user:password@db:5432/mydatabase
    volumes:
      - .:/app
  • build: .: Dockerfileを使用してイメージをビルドすることを指定します。カレントディレクトリにあるDockerfileを使用します。
  • ports: - "8000:8000": ホストマシンの8000番ポートをコンテナの8000番ポートにマッピングします。これにより、ホストマシンからPythonアプリケーションにアクセスできるようになります。
  • depends_on: - db: このサービスがdbサービスに依存していることを示します。Docker Composeは、dbサービスが起動してからpython_appサービスを起動します。
  • environment: DATABASE_URL: ...: 環境変数を設定します。Pythonアプリケーションは、このDATABASE_URL環境変数からデータベース接続情報を取得します。db:5432のように、サービス名をホスト名として使用できるのがDocker Composeの利点です。
  • volumes: - .:/app: ホストマシンのカレントディレクトリ(.)をコンテナ内の/appディレクトリにマウントします。これにより、コードの変更がコンテナに即座に反映され、開発効率が向上します。

データベースサービス

データベースコンテナを定義します。ここでは、PostgreSQLを例にdbというサービス名を定義します。

services:
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydatabase
    volumes:
      - db_data:/var/lib/postgresql/data
  • image: postgres:latest: Docker Hubからpostgresイメージの最新版をプルして使用します。
  • environment: ...: データベースのユーザー名、パスワード、データベース名を指定します。これらの値は、Pythonアプリケーションで設定するDATABASE_URLと一致させる必要があります。
  • volumes: - db_data:/var/lib/postgresql/data: データベースの永続化のためにボリュームを定義します。db_dataという名前のボリュームを作成し、PostgreSQLのデータディレクトリをマウントします。これにより、コンテナが再作成されてもデータは失われません。

docker-compose.ymlの全体像

上記のPythonアプリケーションサービスとデータベースサービスを組み合わせたdocker-compose.ymlの例は以下のようになります。

version: '3.8'

services:
  python_app:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DATABASE_URL: postgresql://user:password@db:5432/mydatabase
    volumes:
      - .:/app

  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydatabase
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Pythonアプリケーション側の実装

Pythonアプリケーションでは、DATABASE_URL環境変数からデータベース接続情報を取得し、ORM(Object-Relational Mapper)ライブラリ(例: SQLAlchemy, Django ORM)を使用してデータベースに接続します。

SQLAlchemyの例

SQLAlchemyを使用する場合、以下のようなコードでデータベースに接続できます。

import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DATABASE_URL = os.environ.get('DATABASE_URL')

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# アプリケーション内でget_db()を使用してデータベースセッションを取得

Docker Composeの実行と管理

docker-compose.ymlファイルを作成したら、以下のコマンドでコンテナを起動、停止、管理できます。

  • docker-compose up: 定義されたサービスを起動します。-dオプションをつけるとバックグラウンドで起動します。
  • docker-compose down: 起動しているコンテナを停止し、削除します。--volumesオプションをつけると、定義されたボリュームも削除します。
  • docker-compose ps: 実行中のサービスを表示します。
  • docker-compose logs: サービスのログを表示します。

開発ワークフローの改善

Docker Composeを活用することで、開発ワークフローが劇的に改善されます。

  • 環境構築の簡略化: 新しい開発者がプロジェクトに参加する際、docker-compose upを実行するだけで、Pythonアプリケーションとデータベースの環境が即座に構築されます。
  • 環境の一貫性: 開発、ステージング、本番環境で同じDockerイメージを使用することで、環境間の差異に起因する問題を最小限に抑えられます。
  • 依存関係の管理: データベースのバージョンや特定のライブラリなど、プロジェクトの依存関係をDockerイメージとdocker-compose.ymlで管理できます。
  • テストの容易性: CI/CDパイプラインでDocker Composeを使用することで、テスト環境の構築と破棄を自動化し、テストの実行を容易にできます。

応用的な設定と考慮事項

Docker Composeは、より複雑なアプリケーション構成にも対応できます。

カスタムDockerfile

PythonアプリケーションのビルドにカスタムDockerfileを使用すると、より細かく環境を制御できます。例えば、特定のPythonバージョンを指定したり、必要なシステムライブラリをインストールしたりできます。

# Dockerfile の例
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

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

ネットワーク設定

デフォルトでは、Docker Composeは各プロジェクト(docker-compose.ymlファイルがあるディレクトリ)ごとにプライベートネットワークを作成します。これにより、サービス間の通信が安全かつ容易になります。必要に応じて、カスタムネットワークを作成し、サービスを接続することも可能です。

環境変数とシークレット管理

データベースのパスワードなどの機密情報は、.envファイルやDocker Secretsなどの機能を使用して管理することが推奨されます。

# .env ファイルの例
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
POSTGRES_DB=mydb

docker-compose.yml内で環境変数を参照するには、`${VAR_NAME}`のような形式を使用します。

サービス間通信の遅延

depends_onは、サービスの起動順序を保証するだけで、サービスが完全に準備完了になったことを保証するわけではありません。データベースが起動しても、まだ初期化処理が完了していない場合があります。このような場合、Pythonアプリケーション側でデータベース接続試行の再試行ロジックを実装するか、Healthcheck機能などを活用して、データベースが利用可能になるまで待機する仕組みを導入する必要があります。

パフォーマンスチューニング

本番環境では、データベースのパフォーマンスチューニング(例: インデックスの最適化、クエリの改善)と、Dockerコンテナのリソース制限(CPU、メモリ)の調整が重要になります。

まとめ

Docker Composeは、Pythonアプリケーションとデータベースの連携を劇的に効率化する強力なツールです。docker-compose.ymlファイルでサービス、ネットワーク、ボリュームを定義することで、開発環境の構築、管理、そしてデプロイプロセスを大幅に簡素化できます。本稿で解説した基本構成と応用的な設定を理解し、適切に活用することで、より堅牢で管理しやすいアプリケーション開発を実現できるでしょう。