• トップ
  • ブログ一覧
  • 【VSCode】Pythonのデバッグ環境整備してみた【Docker】
  • 【VSCode】Pythonのデバッグ環境整備してみた【Docker】

    Python(FastAPI)の開発環境を作っていく上で、デバッグ環境をどう作るの?ってなったので色々調べてみました。

    この記事では「VSCodeからデバッグサーバを起動し、デバッグを実行できる状態」を目指します。

    環境構成は以下です。
    - インフラ:Docker
    - エディタ:VSCode
    - 言語:Python(FastAPI)

    Dockerコンテナ作成

    FastAPIのコンテナ(とMySQLコンテナ)を作るためのファイルです。
    - Dockerfile

    1
    2FROM python:3.10-bullseye
    3ENV PYTHONUNBUFFERED=1
    4ENV PYTHONPATH=/src
    5
    6WORKDIR /src
    7
    8# pipを使ってpoetryをインストール
    9RUN pip install poetry
    10
    11# poetryの定義ファイルをコピー
    12COPY pyproject.toml poetry.lock ./
    13
    14# poetryでライブラリをインストール (pyproject.tomlが既にある場合)
    15RUN if [ -f pyproject.toml ]; then poetry install --no-root; fi
    16
    17
    18# uvicornのサーバーを立ち上げる
    19ENTRYPOINT ["poetry", "run", "uvicorn", "api.main:app", "--host", "0.0.0.0", "--reload"]

    - docker-compose.yml

    1version: '3.9'
    2services:
    3  api:
    4    build: .
    5    volumes:
    6      - .:/src
    7    ports:
    8      - "${API_PORT}:8000" # .envに環境変数で任意に設定(その他も同様)
    9    container_name: api
    10    env_file:
    11      - .env
    12    environment:
    13      - DATABASE_URL=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@db:3306/${MYSQL_DATABASE}
    14  db:
    15    image: mysql:8.0
    16    platform: linux/arm64
    17    volumes:
    18      - db-data:/var/lib/mysql
    19    ports:
    20      - "${DB_PORT}:3306"
    21    container_name: db
    22    env_file:
    23      - .env
    24volumes:
    25  db-data:

    - pyproject.toml

    1[tool.poetry]
    2name = "sample-app"
    3version = "0.1.0"
    4description = ""
    5authors = ["Your Name "]
    6readme = "README.md"
    7
    8[tool.poetry.dependencies]
    9python = "^3.9"
    10fastapi = "^0.111.0"
    11uvicorn = {extras = ["standard"], version = "^0.29.0"}
    12tortoise-orm = "^0.20.0"
    13aiomysql = "^0.2.0"
    14
    15
    16[tool.poetry.group.dev.dependencies]
    17pytest-asyncio = "^0.23.6"
    18httpx = "^0.27.0"
    19pre-commit = "^3.7.1"
    20
    21[tool.pytest.ini_options]
    22asyncio_mode = "auto"
    23
    24[build-system]
    25requires = ["poetry-core"]
    26build-backend = "poetry.core.masonry.api"

    これらをプロジェクトのルートに置いた上で以下を実行し、コンテナを作成・起動します。
    docker compose build
    docker compose up -d

    VSCodeセットアップ

    Microsoft製の拡張機能、Pythonをインストールします。
    この拡張機能を入れると付属でdebugpyを使ったデバッグ用の拡張機能Python Debuggerも使えるようになります。

    デバッグサーバの構築

    ポート追加

    デバッグサーバが稼働するポートとリクエストを待ち受けるポートを追加します。
    docker-compose.ymlに追記します。(.envも忘れずに)

    1version: '3.9'
    2services:
    3  api:
    4    build: .
    5    volumes:
    6      - .:/src
    7    ports:
    8      - "${API_PORT}:8000"
    9      - "${DEBUGGER_PORT}:5678" # これを追加
    10      - "${DEBUG_API_PORT}:8001" # これを追加
    11    container_name: api
    12    env_file:
    13      - .env
    14# 略

    debugpyインストール

    プロジェクトにdebugpyをインストールします。
    コンテナ内からデバッグサーバを起動し、リッスンするために使います。(後述)

    コンテナに入って以下コマンドを実行します。
    poetry add --group dev debugpy

    vscodeデバッグ起動設定

    ここがこの記事で一番肝心箇所になります。
    .vscodeディレクトリに以下のファイルを作成します。
    - launch.json

    1{
    2    "version": "0.2.0",
    3    "configurations": [
    4        {
    5            "name": "Python: Remote Attach",
    6            "type": "debugpy",
    7            "request": "attach",
    8            "connect": {
    9                "host": "localhost",
    10                "port": 5678
    11            },
    12            "pathMappings": [
    13                {
    14                    "localRoot": "${workspaceFolder}",
    15                    "remoteRoot": "/src"
    16                }
    17            ],
    18            "preLaunchTask": "Start Uvicorn with Debugpy from local",
    19        }
    20    ]
    21}

    - tasks.json

    1{
    2    "version": "2.0.0",
    3    "tasks": [
    4        {
    5            "label": "Start Uvicorn with Debugpy from local",
    6            "type": "shell",
    7            "command": "docker exec -it api bash -c 'poetry run python -m debugpy --listen 0.0.0.0:5678 --wait-for-client --log-to-stderr -m uvicorn api.main:app --host 0.0.0.0 --port 8001'",
    8            "isBackground": true,
    9            "presentation": {
    10                "reveal": "always",
    11                "panel": "dedicated"
    12            },
    13            "problemMatcher": {
    14                "owner": "custom",
    15                "pattern": {
    16                    "regexp": "^$"
    17                },
    18                "background": {
    19                    "activeOnStart": true,
    20                    "beginsPattern": ".*",
    21                    "endsPattern": "wait_for_client()"
    22                }
    23            }
    24        }
    25    ]
    26}

    # 説明
    launch.jsonには、debugpy拡張機能を使ったデバッグ起動の設定情報が記載されています。

    • ローカルホストの5678番はコンテナの5678番と紐づくように設定しているので(.envにて)、VSCodeとDockerがここで繋がります
    • ローカル(VSCodeのプロジェクトルート)のファイルはリモート(コンテナ)の/srcとマッピングしています
    • preLaunchTaskは、VSCodeのデバッグ起動前に実行したい処理を指定します。(tasks.jsonの内容)

    tasks.jsonには、コンテナ内でデバッグ用のFastAPIをポート8001番で起動し、ポート5678番でクライアント(VSCode)からの通信を待機するコマンドが記載されています。

    • problemMatcherにて、VSCode側にデバッグセッションが正常に開始したことを伝え、このpre-taskの終了をVSCodeに伝えます

    いざ、デバッグ

    これで準備は出来たのでデバッグを実行します。
    ブレークポイントを設定し、そこで止まることを期待します。

    - main.py

    1from fastapi import FastAPI
    2from fastapi.middleware.cors import CORSMiddleware
    3from starlette.config import Config
    4from starlette.datastructures import CommaSeparatedStrings
    5
    6config = Config("/src/.env")
    7
    8app = FastAPI()
    9origins = config("CORS_ORIGINS", cast=CommaSeparatedStrings, default="")
    10
    11app.add_middleware(
    12    CORSMiddleware,
    13    allow_origins=origins,
    14    allow_credentials=True,
    15    allow_methods=["*"],
    16    allow_headers=["*"],
    17)
    18
    19@app.get("/hello")
    20async def hello():
    21    name: str = 'yamada'
    22    return {f'message: hello { name } !!'} # ここにブレークポイントを設定

    以下エンドポイントにGETでリクエストを送ります。
    localhost:{設定したPort}/hello

    指定した場所で処理がとまりました。

    おわり

    これまで所属していたプロジェクトでは既にデバッグ環境があり、あまり意識してこなかったところだったので勉強になりました。
    これに留まらず、開発のストレスを減らしたり、効率化のためにも環境構築やインフラ周りは引き続き調査していきます。

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    たけちゃん(エンジニア)
    たけちゃん(エンジニア)
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background