当サイトは、アフィリエイト広告を利用しています
Pythonではデバッグを行う場合
を使って実行するのが第一選択肢になる。
そしてPythonの「debugpy」を使ったデバッグ構成パターンは
Python実行場所├─ ローカル│ └─ デバッグ操作位置:同一環境│ ├─ デバッグ方式:launch│ └─ デバッグ方式:attach│ ├─ debugpy起動形態:埋め込み(import debugpy)│ └─ debugpy起動形態:外部起動(python -m debugpy)│└─ コンテナ├─ デバッグ操作位置:同一環境(コンテナに入る)│ ├─ デバッグ方式:launch│ └─ デバッグ方式:attach│ ├─ debugpy起動形態:埋め込み│ └─ debugpy起動形態:外部起動│└─ デバッグ操作位置:別環境(ホストから接続)└─ デバッグ方式:attach├─ debugpy起動形態:埋め込み└─ debugpy起動形態:外部起動
がある。
詳しくは下記記事参照
当記事ではこの構成パターンのうちの
について実装サンプルを使って解説する。
コンテナ × 同一環境デバッグとは
のこと。
ここでいう同一環境とは
が同じコンテナ内にあるという意味。
つまり
Dockerコンテナ├─ VS Code├─ Python└─ debugpy
のような構成になる。
逆に、ホストOS上のVS Codeからコンテナ内Pythonへ接続する構成は
になる。
コンテナ × 同一環境デバッグは
といった特徴がある。
実際の開発では、Pythonをローカルではなく
ことが多い。
その理由は
ため。
そのため、コンテナ内でVS Codeを操作し、同じコンテナ内のPythonをデバッグできるようにしておくと便利。
コンテナ × 同一環境では以下の3パターンが存在する。
それぞれのパターン別に実装して動作を確認する。
今回の構成は以下。
|-- .vscode| `-- launch.json|-- Dockerfile|-- docker-compose.yml|-- main.py`-- requirements.txt
debugpy
# 軽量&最新系に更新(2026時点で安定して使いやすい)FROM python:3.12-slim# pipを最新化 + キャッシュ削減RUN python -m pip install --upgrade pip && \pip install --no-cache-dir --upgrade setuptools wheel# 作業ディレクトリWORKDIR /workspace# 依存関係を先にコピー(レイヤーキャッシュ最適化)COPY requirements.txt .# パッケージインストール(キャッシュ無効)RUN pip install --no-cache-dir -r requirements.txt
version: "3"services:python3:container_name: "container_python3"# Dockerfileをビルドbuild:context: .dockerfile: Dockerfiletty: true# プロジェクトをバインドマウントvolumes:- .:/workspaceports:- "1000:8888"
/workspace を作業ディレクトリにする tty: true でコンテナを起動状態にしておく VScodeで上記のプロジェクトを開く
VScodeでコンテナにアタッチするための拡張機能として
上記プロジェクト直下で
docker compose up -d
を実行してコンテナを起動させる
これで
が同じコンテナ内で動作する構成になる。
launchはVS CodeがPythonプロセスを起動してデバッグする方式。
コンテナ × 同一環境では
ため、VS Codeからコンテナ内Pythonを直接起動できる。
仕組みは
VS Code(コンテナ内)↓(起動)Python(コンテナ内 / debugpy付き)↓デバッグ開始
のようになるイメージ。
VS CodeがPythonをdebugpy付きで実行させることでデバッグを開始する。
実際にコンテナ内Pythonをlaunchデバッグしてみる。
作成するファイルは
で構成は
|-- .vscode| `-- launch.json`-- main.py
になる。
VS Codeの実行とデバッグから作成できる。
{"version": "0.2.0","configurations": [{"name": "Python デバッガー: コンテナ launch","type": "debugpy","request": "launch","program": "${workspaceFolder}/main.py","console": "integratedTerminal"}]}
${workspaceFolder} はコンテナ内の /workspace を指す pathMappings は不要 def main():print("hello1")print("hello2")print("hello3")print("hello4")print("hello5")if __name__ == "__main__":main()
launchではVS CodeがPythonプロセスを起動するため、最もシンプルにコンテナ内デバッグできる。
attachは既に動いているPythonプロセスに後からデバッガを接続する方式。
コンテナ × 同一環境でもattachではdebugpyの起動形態が
の2種類あるので、パターン別に実装して動作を確認する。
「debugpy起動形態:埋め込み」はdebugpyをPythonプロセスに埋め込む方式。
debugpyを埋め込んだPython(コンテナ内で実行中)↓VS Code(同じコンテナ内)が接続
のようになるイメージ。
launchデバッグとは異なり, VS CodeがPythonをdebugpy付きで実行はしてくれないので
debugpy埋め込み済みのPythonをコンテナ内で実行し、
同じコンテナ内のVS Codeからアタッチしてデバッグを開始する。
実際にdebugpy埋め込み済みPythonスクリプトをattachデバッグしてみる。
作成するファイルは
で構成は
|-- .vscode| `-- launch.json`-- main.py
になる。
import debugpy# デバッグクライアント(VS Codeなど)からの接続を受け付けるためのサーバを起動するdebugpy.listen(5678)# デバッグクライアントが接続されるまで、ここでプログラムの実行を完全に停止するdebugpy.wait_for_client()def main():print("hello1")print("hello2")print("hello3")print("hello4")print("hello5")if __name__ == "__main__":main()
{"version": "0.2.0","configurations": [{"name": "Python デバッガー: attach","type": "debugpy","request": "attach","justMyCode": false,"connect": {"host": "localhost","port": 5678},"pathMappings": [{"localRoot": "/","remoteRoot": "/"}]}]}
localhost:5678 で接続できる pathMappingsは本来は
"pathMappings": [{"localRoot": "${workspaceFolder}","remoteRoot": "/app"}]
のようにローカルからコンテナをリモートデバッグする際にVSCodeのdebugpyが
を相互変換するための設定である。
ただ今回のようにDev Containerを使ってVSCodeでコンテナにアタッチしてる場合、
VS Code側とPython側はどちらもコンテナ内のLinuxパスを参照するので
ホストOSのパスとコンテナ内パスを変換する必要はない。
ただし、Pythonが実行するコードが必ず /workspace 配下にあるとは限らない。
コンテナビルド時にインストールされたパッケージやライブラリは、site-packages など /workspace 外に配置される場合がある。
そのため「パスを書き換えるため」の設定ではなく
同一コンテナ内のパスをそのまま対応付ける目的で次のように設定する。
"pathMappings": [{"localRoot": "/","remoteRoot": "/"}]
としておくと実務上扱いやすい。
これにより /workspace 外に配置された site-packages なども含めて、同一コンテナ内のパスをそのまま解決できるようになる。
なお、pathMappingsを書かない場合でも、VS Code側とPython実行側のパスが完全一致していれば動作することは多い。
ただし、実行されるコードが site-packages 側になる場合など、VS Codeが認識しているパスとPython実行時の実体パスがズレると
といった問題が発生する場合がある。
※launch起動の場合はVS Code自身がPythonプロセスを起動するので不要
まずはコンテナ内でPythonスクリプトを実行する。
python main.py
実行後はVS Codeからの接続があるまで、プログラムが待っているので動かない。
その後にVS Codeのattachデバッガを実行すると、デバッグが開始される。
「debugpy起動形態:外部起動」はdebugpyを実行時に指定して起動する方式。
具体的には起動するコマンドで指定する。
python -m debugpy↓対象スクリプト実行↓VS Code(同じコンテナ内)が接続
のようになるイメージ。
こちらもlaunchデバッグとは異なり, VS CodeがPythonをdebugpy付きで実行はしてくれないので
Pythonを実行するコマンドでdebugpyを指定する。
その後、VS Codeからアタッチしてデバッグを開始する。
実際にPythonスクリプトをdebugpy付きで外部起動してattachデバッグしてみる。
作成するファイルは
で構成は
|-- .vscode| `-- launch.json`-- main.py
になる。
def main():print("hello1")print("hello2")print("hello3")print("hello4")print("hello5")if __name__ == "__main__":main()
debugpy起動形態:埋め込み実装例と同じ
{"version": "0.2.0","configurations": [{"name": "Python デバッガー: attach","type": "debugpy","request": "attach","justMyCode": false,"connect": {"host": "localhost","port": 5678},"pathMappings": [{"localRoot": "/","remoteRoot": "/"}]}]}
まずはコンテナ内でPythonスクリプトをdebugpy付きで実行する。
python -m debugpy --listen 5678 --wait-for-client main.py
--wait-for-client を指定しないと終了してしまうので指定する --wait-for-client を指定しなくても問題ない その後にVS Codeのattachデバッガを実行すると、デバッグが開始される。
外部起動はdocker-compose.ymlのcommandに書くこともできる。
例えば以下のようにする。
services:app:build: .tty: trueworking_dir: /workspacevolumes:- .:/workspacecommand: python -m debugpy --listen 5678 --wait-for-client main.py
この場合は
docker compose up
でdebugpy付きのPythonプロセスが起動する。
その後、同じコンテナ内で開いたVS Codeからattachする。
ただし、スクリプトでは実行後に終了してしまうため、
--wait-for-client を指定しておくと動作確認しやすい。
launchとattachの違いは「誰がPythonプロセスを起動するか」にある。
コンテナ × 同一環境の場合でも、この違いは同じ。
という違いになる。
コンテナ × 同一環境では
が同じコンテナ内で動作している。
そのため
localhost で接続できる pathMappings が不要 という特徴がある。
これは
VS Code(コンテナ内)↓ localhostdebugpy(コンテナ内)
という接続になるため。
一方で、ホストOS上のVS Codeからコンテナ内Pythonへ接続する場合は
VS Code(ホスト)↓ ポート公開debugpy(コンテナ内)
になる。
この場合は
が必要になる。
今回の記事はあくまで
のため、そこまでは扱わない。
実際に実務ではどう使い分けるべきかをまとめておく。
のように、コンテナ内で簡単なPythonツールの動作確認や開発をする場合に使うことが多い。
のように、実際のシステム開発ではAPIサーバーを起動して、
VS Codeでアタッチしてデバッグする場合に使うことが多い。
attachはさらに2パターンに分かれる。
コンテナ内で単体開発
docker composeで起動するアプリ
attach内の選択
まとめると
という違いになる。
実務では
となることが多い。
特にコンテナ環境では
を分離できるattachが重要になる。