はじめに
Windows 11 のマシン 1 台に、Django + PostgreSQL の開発・デバッグ環境を作ります。
コンテナランタイムは Docker Desktop ではなく Podman を使います。
作るもの
PostgreSQL だけをコンテナで動かし、Django は Windows 上の venv で直接動かします。
Windows 版 Podman は、WSL2 の中に Linux の仮想マシンを立て、コンテナはその中で動きます。
Windows と VM の間には 2 種類の境界があり、コストが大きく違います。
| 境界 | 通るもの | コスト |
|---|---|---|
| ポート転送 | TCP パケットだけ | ほぼ無視できる |
| ファイルのバインドマウント | ファイル I/O の 1 回ごと | 重い |
Django までコンテナに入れると、ソースコードを bind mount で VM に見せることになり、
重い方の境界をまたぐようになります。オートリロードは大量のファイルを監視し続けるため、
この影響を最も強く受けます。
一方 PostgreSQL は TCP でポートが開いていればよいので、軽い方の境界しか使いません。
コンテナ化の恩恵(環境を汚さない・捨てて作り直せる)だけを受け取れます。
環境は以下で確認しています。
| 項目 | 内容 |
|---|---|
| OS | Windows 11 (64bit) |
| Python | 3.13 |
| Django | 5.2 (LTS) |
| PostgreSQL | 17 |
| Podman | 5 系 |
1. Podman を入れる
WSL2 を有効化する
PowerShell を管理者として実行します。
wsl --install --no-distribution
Podman は専用の Linux VM を自分で用意するので、ディストリビューションは不要です。
実行後、一度 Windows を再起動してください。
Podman 本体
winget install -e --id RedHat.Podman
GUI が欲しい場合は RedHat.Podman-Desktop を追加してもかまいませんが、必須ではありません。
以下はすべて CLI だけで進みます。
VM を起動する
新しい PowerShell を開いて(PATH を反映させるため)実行します。
podman machine init
podman machine start
init は初回のみです。VM イメージのダウンロードに数分かかります。
動作確認:
podman run --rm docker.io/library/hello-world
イメージ名は完全修飾で書く
Podman は Docker Hub を暗黙の既定にしていません。postgres:17のような短縮名ではなく
docker.io/library/postgres:17と書きます。イメージ自体は Docker Hub のものがそのまま使えます。
2. Python と Compose を入れる
Python
winget install -e --id Python.Python.3.13
新しい PowerShell を開き、venv の有効化スクリプトを実行できるようにします(初回のみ、管理者権限は不要)。
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
プロジェクトと仮想環境
mkdir C:\work\sample-project
cd C:\work\sample-project
py -3.13 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install Django psycopg[binary] django-environ
プロンプトの先頭に (.venv) が付けば有効化できています。
psycopg[binary]を指定すると、コンパイル済みホイールが入るため
Windows に PostgreSQL クライアント(libpq)を別途入れる必要がありません。
Compose プロバイダ
podman compose は、Podman 自身が Compose を実装しているわけではなく、
外部の実装を呼び出すラッパーです。プロバイダを 1 つ入れる必要があります。
podman-compose は Python 製なので、Python の導入後に入れます。
venv ではなくコマンドとして使いたいので pipx 経由にします。
py -m pip install --user pipx
py -m pipx ensurepath
PATH が書き換わるので、いったん PowerShell を開き直してから実行します。
pipx install podman-compose
podman compose version
3. PostgreSQL を起動する
プロジェクト直下に compose.yaml を置きます。
services:
db:
image: docker.io/library/postgres:17
container_name: sample-db
environment:
POSTGRES_DB: appdb
POSTGRES_USER: appuser
POSTGRES_PASSWORD: apppass
TZ: Asia/Tokyo
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
データは名前付きボリュームに置きます。バインドマウントにすると Windows ↔ VM の境界で
パーミッションや性能の問題が出やすく、DB データを Windows から直接触る必要もないためです。
ファイル名は
docker-compose.ymlのままでも読み込まれます。
ただしpodman-compose.ymlは探索対象外なので、その名前にしたい場合は-fで明示が必要です。
起動します。
podman compose up -d
podman ps
接続確認:
podman exec -it sample-db psql -U appuser -d appdb -c "select version();"
よく使う操作:
podman compose stop # 停止(データは残る)
podman compose start # 起動
podman compose down -v # 破棄(データも消える)
podman compose logs -f db
ポート 5432 が埋まっている場合
Windows にネイティブの PostgreSQL が入っていると衝突します。
portsを"5433:5432"に変え、後述の.envのDATABASE_URLも
...@127.0.0.1:5433/appdbに合わせてください。
4. Django から繋ぐ
プロジェクトを作る
django-admin startproject config .
python manage.py startapp todo
フォルダ構成
sample-project/
├─ .venv/ # 仮想環境(Git 管理外)
├─ .vscode/
│ └─ launch.json # デバッグ構成
├─ config/ # プロジェクト設定
│ ├─ settings.py
│ ├─ urls.py
│ └─ wsgi.py
├─ todo/ # アプリケーション
│ ├─ models.py
│ ├─ views.py
│ ├─ admin.py
│ └─ migrations/
├─ templates/
├─ static/
├─ compose.yaml
├─ manage.py
├─ requirements.txt
├─ .env # 環境変数(Git 管理外)
├─ .env.example # .env の雛形(Git 管理)
└─ .gitignore
.gitignore:
.venv/
__pycache__/
*.py[cod]
.env
staticfiles/
db.sqlite3
環境変数を用意する
接続情報を settings.py に直接書かず、.env から読み込む形にします。
まず雛形を作ります。これはリポジトリに入れて共有します。
DJANGO_SECRET_KEY=change-me
DJANGO_DEBUG=True
DATABASE_URL=postgres://appuser:apppass@127.0.0.1:5432/appdb
これをコピーして、自分用の .env を作ります。
Copy-Item .env.example .env
.env は Git に入れず、.env.example だけを共有します。
こうすると「どのキーが必要か」はチームで共有され、実際の値は各自の手元にとどまります。
接続先を切り替えたいときも、コードを触らずに .env だけを書き換えれば済みます。
settings.py
既定の SQLite 設定を差し替えます。import environ はファイル冒頭に置いてください。
import environ
env = environ.Env()
environ.Env.read_env(BASE_DIR / ".env")
SECRET_KEY = env("DJANGO_SECRET_KEY")
DEBUG = env.bool("DJANGO_DEBUG", default=False)
DATABASES = {"default": env.db("DATABASE_URL")}
INSTALLED_APPS += ["todo"]
LANGUAGE_CODE = "ja"
TIME_ZONE = "Asia/Tokyo"
env.db() は DATABASE_URL を解析して、ENGINE / NAME / USER / HOST / PORT を
組み立ててくれます。接続情報を 1 行で書けるので、.env の見通しもよくなります。
起動する
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
http://127.0.0.1:8000/admin/ を開いてログインできれば、DB 接続まで通っています。
5. VS Code でデバッグする
拡張機能「Python」「Python Debugger」を入れ、インタープリタに .venv\Scripts\python.exe を
選択します(Ctrl+Shift+P → Python: Select Interpreter)。
.vscode/launch.json を作ります。
{
"version": "0.2.0",
"configurations": [
{
"name": "Django: runserver",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}\\manage.py",
"args": ["runserver", "127.0.0.1:8000"],
"django": true,
"justMyCode": false,
"console": "integratedTerminal"
}
]
}
"justMyCode": false にしておくと Django 内部にもステップインできます。
原因が自分のコードかフレームワークかを切り分けたいときに効きます。
使い方
-
podman compose up -dで DB を起動しておく -
views.pyなどの行番号の左をクリックしてブレークポイントを置く -
F5で起動 - ブラウザで該当 URL を開くと、その行で停止する
| 操作 | キー |
|---|---|
| ステップオーバー | F10 |
| ステップイン | F11 |
| ステップアウト | Shift+F11 |
| 続行 | F5 |
停止中は「変数」ペインで request や self の中身を確認でき、
「デバッグコンソール」で任意の式を評価できます。QuerySet を見るときはこう打ちます。
list(qs.values())
qs.query # 実際に発行される SQL
発行された SQL を見る
settings.py に追記すると、実行された SQL がターミナルに出ます。
同じクエリが何度も出ていれば N+1 を疑えます。
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {"console": {"class": "logging.StreamHandler"}},
"loggers": {
"django.db.backends": {"handlers": ["console"], "level": "DEBUG"},
},
}
DB を直接見る
python manage.py dbshell # settings の接続情報を使う
podman exec -it sample-db psql -U appuser -d appdb # コンテナに入る
psql の中では \dt でテーブル一覧、\d todo_task でテーブル定義、\q で終了です。
pgAdmin や DBeaver から localhost:5432 に繋ぐこともできます。
DB を作り直す
スキーマがおかしくなったら、ボリュームごと捨てるのが早いです。
podman compose down -v
podman compose up -d
python manage.py migrate
まとめ
- Windows + Podman では、DB だけコンテナ・Django はホストの venv が一番速い
- コンテナは Windows の上ではなく WSL2 の Linux VM の中で動く
-
.vscode/launch.jsonを置けば、F5だけでデバッグを始められる
環境構築は最初に一度やるだけに見えて、その後の開発速度に一番効いてきます。
ここに時間を使う価値は十分にあります。