PythonアプリケーションをDockerで動かすとき、最初につまずきやすいのは、どのファイルに何を書くかという役割分担です。
requirements.txt、Dockerfile、docker-compose.ymlの関係を理解すれば、構成を上から順に読み解けます。
Dockerイメージはアプリケーションの実行環境を組み立てるひな型であり、コンテナはそのイメージから起動する実行単位です。
Pythonパッケージだけを分離したい場合は、venvとDockerの違いを先に確認すると、使い分けが明確になります。
3つの設定ファイルの関係
三つのファイルは同じ設定を重ねて書くものではなく、それぞれ異なる範囲を担当します。
| ファイル | 担当すること | 読むとわかること |
|---|---|---|
requirements.txt |
Pythonパッケージの依存関係を記録する | アプリケーションが必要とするライブラリ |
Dockerfile |
Dockerイメージの構築手順を定義する | ベース環境、ファイル配置、インストール処理、起動方法 |
docker-compose.yml |
複数のサービスをまとめて定義する | アプリケーション、Redisなどの接続関係と起動設定 |
一つのコンテナだけで足りる構成では、まずDockerfileだけで試し、複数サービスが必要になった段階でComposeを加えると理解しやすくなります。
基本のディレクトリ構成
小規模なFlaskアプリケーションを例にすると、プロジェクトの入口は次のように整理できます。
my-python-app/
├── app/
│ ├── __init__.py
│ └── main.py
├── tests/
│ ├── __init__.py
│ └── test_main.py
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md
この構成は出発点であり、アプリケーションの規模や採用するフレームワークに合わせて分割方法を変えます。
| 項目 | 役割 |
|---|---|
app/ |
アプリケーションのソースコードを置く |
tests/ |
動作を確認するテストコードを置く |
requirements.txt |
必要なPythonパッケージを記録する |
Dockerfile |
イメージを構築する手順を書く |
docker-compose.yml |
複数サービスの構成をまとめる |
README.md |
準備、起動、停止、テストなどの手順を共有する |
requirements.txtでPythonの依存関係を管理する
requirements.txtには、アプリケーションが利用するPythonパッケージを一行ずつ記述します。
FlaskアプリケーションがHTTP通信にRequestsも使う場合、最小例は次のとおりです。
Flask
requests
バージョンを固定する場合は、パッケージ名の後ろに==とプロジェクトで検証したバージョンを書きます。
特定の古いバージョンを例として固定すると、そのままコピーした読者が古い環境を作るおそれがあるため、採用バージョンは公式情報とアプリケーションの互換性を確認して決めます。
ローカル環境では、次のコマンドで一覧に記載したパッケージをインストールできます。
python -m pip install -r requirements.txt
requirements.txtが担当するのはPythonパッケージであり、Python本体やOS側の環境は次のDockerfileで定義します。
Dockerfileでイメージの構築手順を定義する
Dockerfileは、ベースとなるイメージ、作業場所、依存関係のインストール、ソースコードの配置、起動コマンドを上から順に記述するファイルです。
次の例は、app/main.pyを起動できることを前提にした最小構成です。
FROM python:3-slim
WORKDIR /app
COPY requirements.txt .
RUN python -m pip install --no-cache-dir -r requirements.txt
COPY app ./app
CMD ["python", "app/main.py"]
| 命令 | 役割 |
|---|---|
FROM |
構築の土台にするイメージを指定する |
WORKDIR |
後続の処理で使う作業ディレクトリを設定する |
COPY |
必要なファイルをイメージ内へコピーする |
RUN |
イメージの構築中にコマンドを実行する |
CMD |
コンテナ起動時の既定コマンドを指定する |
python:3-slimは構成を説明するための例なので、実際のプロジェクトでは動作確認を済ませたベースイメージのタグを選びます。
Flask以外の選択肢も含めて構成を考える場合は、Pythonフレームワークの比較も参考になります。
docker-compose.ymlで複数のサービスをまとめる
Composeは、WebアプリケーションとRedisのように、複数のコンテナを一つの構成として起動したい場合に使います。
元の例を現在のCompose仕様に合わせて簡潔にすると、次のように書けます。
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/app
depends_on:
- redis
redis:
image: redis:alpine
| 設定 | 意味 |
|---|---|
build: . |
現在のディレクトリにあるDockerfileからWeb用イメージを構築する |
ports |
ホスト側のポート5000をコンテナ側のポート5000へ割り当てる |
volumes |
現在のディレクトリをコンテナ内の/appへ割り当てる |
depends_on |
webより先にredisを起動する依存関係を示す |
depends_onの短い書き方は起動順を示しますが、Redisが接続を受け付けられる状態まで待つ設定ではありません。
準備完了を確認してからWebアプリケーションを動かす必要がある場合は、ヘルスチェックと条件付きの依存関係を別に設計します。
このComposeファイルはコンテナ同士の構成を定義するだけなので、Flask側にもRedisへ接続する処理と設定が必要です。
Webアプリケーションがコンテナ内のポート5000で待ち受ける構成であれば、次のコマンドで構築と起動をまとめて実行できます。
docker compose up --build
確認後は、次のコマンドでComposeが管理するコンテナを停止して削除します。
docker compose down
構築を進める順序
app/にアプリケーションを書き、ローカルで起動できることを確認します。- 必要なPythonパッケージを
requirements.txtに記録します。 Dockerfileに依存関係のインストールと起動方法を書きます。- Redisなど別のサービスが必要な場合に
docker-compose.ymlを追加します。 - 構築、起動、接続、停止の手順を
README.mdへ残します。
この順序なら、問題が起きたときにアプリケーション、イメージ構築、複数サービス連携のどこで失敗したかを切り分けやすくなります。
初心者が迷いやすい点
| 症状 | 最初に確認する場所 | 確認内容 |
|---|---|---|
| Pythonパッケージを読み込めない | requirements.txtとRUN |
パッケージ名とインストール処理が一致しているか |
| コンテナがすぐ停止する | CMDとアプリケーション |
起動するファイルのパスと実行時エラー |
| ブラウザから接続できない | portsとアプリケーション |
コンテナ内の待受ポートと割り当てが一致しているか |
| Redisへの接続に失敗する | 接続設定と準備完了の判定 | サービス名、接続先、起動後に利用可能になるまでの待機 |
設定ファイルを一度に増やすより、単体で動くアプリケーションから順に確認したほうが、原因を追いやすくなります。
まとめ
requirements.txtはPythonの依存関係、Dockerfileはイメージの構築、docker-compose.ymlは複数サービスの連携を担当します。
まず小さな構成で各ファイルの境界を理解し、データベースやキャッシュなどが必要になった時点でComposeへサービスを追加すると、構成の意図を保ちやすくなります。
この記事に関連する株式会社greedenの取り組み
株式会社greedenは、PythonやDockerを用いるWebシステムについて、要件整理から設計、実装、テスト、リリース後の保守まで支援しています。構成ファイルの役割を整理し、運用しやすい開発環境を整えたい場合はご相談ください。
