Django アプリケーションをデバッグするには、通常、デバッグサーバーがアプリケーションコードの実行を監視し、開発者のエディタと通信する必要があります。Docker コンテナ内で実行されるアプリケーションの場合、この通信経路を確立することが課題となります。
デバッグが成功する主な要素は以下の通りです:
まず、debugpy
というPythonデバッグライブラリがアプリケーションの起動プロセスの最初期に初期化されています。これにより、Djangoフレームワークが読み込まれる前からデバッグ機能が有効になり、アプリケーション全体の実行フローを監視できるようになります。
# manage.py の先頭での初期化
import debugpy
# デバッグモードの制御
if not debugpy.is_client_connected():
try:
debugpy.listen(("0.0.0.0", 5678))
print("✅ Debugger is listening on port 5678")
except RuntimeError:
# 既に listen が呼び出されている場合は無視
print("⚠️ Debugger is already listening")
次に、Docker環境では、コンテナ内のプロセスとホストマシン上のエディタ間の通信経路が必要です。Docker Composeファイルで適切にポートフォワーディングを設定することで、コンテナ内のデバッグサーバーとホスト上のエディタが通信できるようになります。
さらに、ファイルシステムのマッピングも重要な要素です。コンテナ内のファイルパスとホスト上のファイルパスは異なりますが、launch.json
の pathMappings
設定により、エディタはブレークポイントを正確に対応付けることができます。
Docker Compose と ボリュームマウントの詳細解説
Docker Compose の役割と仕組み
Docker Compose は、複数のコンテナを定義し、連携させるためのツールです。docker-compose.yml
ファイルには、アプリケーションを構成するサービス(コンテナ)の設定が記述されています。
一般的な Django プロジェクトの docker-compose.yml
ファイルは以下のようになります:
version: '3.8' # Docker Compose のバージョン指定
services: # サービス(コンテナ)の定義開始
web: # サービス名(任意の名前)
build: . # Dockerfile がカレントディレクトリにあることを指定
tty: true # 擬似TTYを割り当て(コンテナがバックグラウンドで実行されても終了しないようにする)
volumes: # ボリュームマウントの設定
- .:/code # ホスト側のカレントディレクトリをコンテナ内の /code にマウント
ports: # ポートマッピングの設定
- "8000:8000" # ホストの8000ポートをコンテナの8000ポートに接続
- "5678:5678" # デバッグ用のポート
expose: # コンテナ間通信用にポートを公開
- 8000
- 5678
この設定により、以下のことが実現されています:
-
イメージのビルド:
build: .
の部分で、カレントディレクトリにある Dockerfile を使ってイメージをビルドするよう指定しています。これにより、アプリケーションの実行環境が構築されます。
-
コンテナの作成と実行:
web
サービスの定義全体が、このサービス用のコンテナを作成・実行する設定です。tty: true
の設定により、コンテナがバックグラウンドでも終了せず、ログ出力が可能になります。
-
ファイルシステムの共有:
volumes: - .:/code
の部分で、ホスト側のカレントディレクトリ(.
)をコンテナ内の/code
ディレクトリにマウントしています。これにより、ホスト上でファイルを編集すると、即座にコンテナ内に反映されます。
-
ネットワークポートの共有:
ports
セクション:
ports
セクションではホストマシンからコンテナへのポート接続を設定します。外部(ホストマシンやインターネット)からコンテナにアクセスするために必要です。-
- "8000:8000"
:
ホストの8000ポートへのアクセスがコンテナの8000ポートに転送されます。これにより、ブラウザでhttp://localhost:8000
にアクセスすると、コンテナ内で実行されているDjangoアプリケーションにアクセスできます。 -
- "5678:5678"
:
デバッグ用のポートも同様に接続されます。ホスト側のデバッグクライアント(VSCode/Cursor)からコンテナ内のデバッグサーバー(debugpy)に接続するために使用されます。
expose
セクション:
コンテナ間の通信用にポートを公開します。同じDocker Compose内の他のサービス(コンテナ)からアクセスできますが、ホストマシンからは直接アクセスできません。-
- 8000
:
Django アプリケーションのポートを他のコンテナ(例:Nginx や Redis など)が直接アクセスできるようにします。 -
- 5678
:
デバッグポートも同様に Docker ネットワーク内で公開されます。これにより、例えば別のデバッグツールコンテナがこのポートに接続できます。
-
この例では両方を設定していますが、実際には ports
だけで十分な場合も多いです。expose
は複数のコンテナ(例:Webサーバーとデータベース)間の通信を設定する場合に特に役立ちます。
ボリュームマウントの詳細
Docker Compose ファイルの中で特に重要なのが volumes セクションです:
volumes:
- .:/code
この一行は非常に重要な役割を果たしています:
-
.
はホスト側のパスで、Docker Compose を実行しているディレクトリ(プロジェクトのルートディレクトリ)を指します -
:/code
はコンテナ内のパスで、ホスト側のディレクトリをマウントする場所を指定しています - コロン (
:
) はホスト側とコンテナ側のパスを区切る記号です
このマウント設定により、以下のような対応関係が生まれます:
ホスト側 コンテナ側
/path/to/project/ → /code/
/path/to/project/manage.py → /code/manage.py
/path/to/project/myapp/ → /code/myapp/
この対応関係によって、以下のメリットが得られます:
-
開発の即時反映:
ホスト側でファイルを編集すると、その変更がリアルタイムでコンテナ内に反映されます。これにより、コードを変更するたびにコンテナを再ビルドする必要がなくなります。 -
永続性:
コンテナを停止または削除しても、データはホスト側に残ります。次回コンテナを起動したときも同じファイルが利用できます。 -
デバッグの一貫性:
エディタでブレークポイントを設定したファイルと、コンテナ内で実行されるファイルが同一になるため、デバッグが正確に機能します。
パスマッピングとボリュームマウントの関係
VSCode/Cursor の launch.json で設定するパスマッピング(pathMappings
)は、ボリュームマウントと密接に関連しています:
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/code"
}
]
launch.jsonの全体
{
"version": "0.2.0",
"configurations": [
{
"name": "Docker Django Debug",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/code"
}
],
"django": true,
"justMyCode": true
}
]
}
この設定は、デバッグ時にエディタとデバッガー間でファイルパスを変換するためのものです:
-
localRoot:
エディタ上でのプロジェクトのルートパス(${workspaceFolder}
は VSCode/Cursor の変数で、開いているフォルダを指します) -
remoteRoot:
コンテナ内でのアプリケーションのルートパス
例えば、ホスト側の /path/to/project
が ${workspaceFolder}
に対応し、コンテナ内の /code
がアプリケーションのルートディレクトリになっています。
重要なのは、Docker Compose のボリュームマウント(.:/code
)とデバッグのパスマッピング(${workspaceFolder}
→ /code
)が一致していることです。これにより、エディタでブレークポイントを設定した場所が、コンテナ内の正しい場所に変換されます。
ディレクトリ構造とマウントの具体例
一般的な Django プロジェクトの構造は以下のようになります:
project-root/ # プロジェクトルート
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── manage.py # Django の管理スクリプト
├── project/ # Django プロジェクト設定
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── app1/ # Django アプリケーション
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
Docker Compose のボリュームマウント(.:/code
)により、プロジェクトルートディレクトリ全体がコンテナ内の /code
にマウントされます。そのため、コンテナ内のディレクトリ構造は以下のようになります:
/code/ # コンテナ内のマウントポイント
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── manage.py
├── project/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── app1/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
デバッグ時には、launch.json
のパスマッピングにより、エディタ上の ${workspaceFolder}
がコンテナ内の /code
に対応付けられます。
より複雑なプロジェクト構造の場合
より複雑なプロジェクト構造では、Django アプリケーションがサブディレクトリに配置されることがあります:
project-root/ # プロジェクトルート
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── django_app/ # Django アプリケーションディレクトリ
├── manage.py
├── project/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── app1/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
この場合、Docker Compose のボリュームマウントは同じですが、パスマッピングを調整する必要があります:
"pathMappings": [{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/code"
}]
そして、コンテナ内で Django を実行する際には、正しいディレクトリに移動する必要があります:
cd /code/django_app
python manage.py runserver 0.0.0.0:8000
Docker コンテナ内でのコマンド実行とパス
Docker コンテナ内でコマンドを実行する際、作業ディレクトリとパスの関係も重要です。一般的な Dockerfile では:
# 作業ディレクトリの作成・設定
WORKDIR /code
# 依存関係のインストール
COPY requirements.txt .
RUN pip install -r requirements.txt
# アプリケーションのコピー
COPY . .
この設定により、コンテナ内のデフォルトの作業ディレクトリが /code
に設定されています。そのため、docker-compose exec web bash
でコンテナに接続すると、最初に /code
ディレクトリにいることになります。
デバッグの設定と実行
デバッグ用の manage.py の修正
Django アプリケーションをデバッグするには、manage.py ファイルの先頭にデバッグコードを追加します:
#!/usr/bin/env python
import os
import sys
import debugpy
# デバッグサーバーの初期化と制御
if not debugpy.is_client_connected():
try:
debugpy.listen(("0.0.0.0", 5678))
print("✅ Debugger is listening on port 5678")
except RuntimeError:
# 既に listen が呼び出されている場合は無視
print("⚠️ Debugger is already listening")
def main():
# Django の標準的な初期化コード
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
VSCode/Cursor のデバッグ設定
Docker コンテナ内の Django アプリケーションをデバッグする方法には、主に2つのアプローチがあります。
- ホストからのリモートデバッグ
- コンテナにアタッチしたウィンドウでのデバッグ
それぞれの手順について見ていきます。
ホストからのリモートデバッグ
エディタでホストの環境からリモートのデバッグサーバーにアクセスしてデバッグを行います。
.vscode/launch.json
ファイルを作成して、デバッグ設定を追加します:
{
"version": "0.2.0",
"configurations": [
{
"name": "Docker Django Debug",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/code"
}
],
"django": true,
"justMyCode": true
}
]
}
デバッグの実行手順
-
Docker コンテナを起動します:
docker-compose up -d
dockerがデスクトップアプリなどで起動できる場合は,そちらからでも問題ありません。
-
デバッグモードで Django を実行します:
docker-compose exec web bash -c "DEBUG=True python manage.py runserver 0.0.0.0:8000"
web
というのはdocker-compose.yml内のweb # サービス名(任意の名前)
の部分を指定します。
-
VSCode/Cursor でデバッグセッションを開始します:
- デバッグパネルを開く
- 「Docker Django Debug」設定を選択
- 「デバッグの開始」ボタンをクリック
-
ブレークポイントを設定して、アプリケーションにアクセスします。
コンテナにアタッチしたウィンドウでのデバッグ
dockerコンテナをアタッチしたウィンドウからデバッグを行います。
{
"version": "0.2.0",
"configurations": [
{
"name": "Docker Django Debug",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}"
}
],
"django": true,
"justMyCode": true
}
]
}
デバッグの実行手順
-
Docker コンテナを起動
docker-compose up -d
ホストでのデバッグと同じです。
-
エディタのリモートウィンドウ機能でコンテナにアタッチ
- VSCode/Cursor の「リモートウィンドウ」または「コンテナにアタッチ」機能を使用
-
アタッチしたウィンドウでプロジェクトを開く
「フォルダを開く」から適切なディレクトリ(例:/app)を選択
-
デバッグモードで Django を実行
アタッチしたウィンドウのターミナル上で以下のコマンドを実行します。DEBUG=True python manage.py runserver 0.0.0.0:8000
-
アタッチしたウィンドウでデバッグセッションを開始
- デバッグパネルを開く
- 「Docker Django Debug」設定を選択
- 「デバッグの開始」ボタンをクリック
-
アタッチしたウィンドウでブレークポイントを設定して、アプリケーションにアクセスします。