ぼく「Djangoのリモートデバッグも出来ないエディターなんて…」VSCode「それ、できるで。」~docker-compose編~

# はじめに

VSCode「そう。`Remote Development`ならね。」

ぼく「なん…やて…」

# 目次

- [前提条件](#前提条件)
- [Remote Developmentのインストール](#remote-developmentのインストール)
- [設定ファイルの追加](#設定ファイルの追加)
- [リモートデバッグの開始](#リモートデバッグの開始)
- [デバッグの開始](#デバッグの開始)

## 前提条件

VSCode「docker-composeでのデバッグをやっていくから、まずは下のわかりやすい記事を参考に環境構築を行ってな。」

ぼく「手前味噌やな。」

- [DockerでDjangoの開発環境を再構築！！！！](https://qiita.com/nokonoko_1203/items/e345f899ac9ac700d6a8)

VSCode「フォルダ構成は以下の通りになっているはずやで。」

```shell-session:tree
containers
├── django
│   ├── Dockerfile
│   ├── Pipfile
│   ├── Pipfile.lock
│   ├── config
│   │   ├── __init__.py
│   │   ├── asgi.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── db.sqlite3
│   ├── entrypoint.sh
│   ├── manage.py
│   └── static
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── nginx.conf
└── postgres
    ├── Dockerfile
    └── sql
        └── init.sql
```

VSCode「ほんだら、containersディレクトリをワイ（VSCode）開いてな。」

ぼく「あいよ。」

## Remote Developmentのインストール

VSCode「[Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)をインストールしてな。左下にこんな感じの青いマークが出てればインストール完了や」

<img width="184" alt="image1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/0e0d4477-bfe6-9ef6-2d87-dd089cad2d82.png">

## 設定ファイルの追加

VSCode「次にデバッグ用の設定ファイルを追加していくで。」

VSCode「出てきた青いアイコンをクリックしてな。」

ぼく「あいよ。」

VSCode「したら上にメニューが出てくるやろ？そん中から`Remote-Containers: Add Development Container configuration Files...`を選択してな。」

<img width="604" alt="image2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/b640ce7e-c7df-18d4-e791-acb1e3b92d56.png">

VSCode「そのあと`From 'docker-compose.yml'`を選択や。」

<img width="602" alt="image3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/783951a0-8624-0f71-dedd-283e5e2ded3c.png">

- デバックしたいサービスを選択(今回はDjango)を選択
<img width="601" alt="image4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/c927bdb4-ce8d-01d4-5f14-890371dac055.png">

VSCode「するとプロジェクトのルートに`.devcontainer`ディレクトリと、その中に`devcontainer.json`及び`docker-compose.yml`が出来上がるから、`devcontainer.json`を以下のように書き換えてな！」

VSCode「この辺は実務で使ったりする場合は任意の環境に置き換えて使ってな！」

ぼく「設定ファイル周りはようハマるからきーつけなあかんな。」

```json:devcontainer.json
{
  // 任意の名前を入力
  "name": "djnago containers",
  // Remoteでログインしたいコンテナを作成するためのdocker-composeファイルを指定してください。
  "dockerComposeFile": "docker-compose-debug.yml",
  // 起動したいサービスを選択
  "service": "django",
  // コンテナに入ったときに最初にここで指定したものがカレントディレクトリになります
  "workspaceFolder": "/usr/src/app/",
  // シェルを選択
  "settings": {
    "terminal.integrated.shell.linux": "/bin/bash"
  },
  // vscode拡張機能を選択
  "extensions": ["ms-azuretools.vscode-docker", "ms-python.python"],
  // vscodeを閉じた時のコンテナの挙動を設定
  // noneでコンテナの起動を継続する
  "shutdownAction": "none"
}
```

VSCode「次にデバッグ用のymlに書き換えていくで！`.devcontainer`ディレクトリ内の自動生成された`docker-compose.yml`を`docker-compose-debug.yml`とかに修正し、既存の`docker-compose.yml`の内容をコピーしてな。」

VSCode「今の段階ではサービスが`django`と`postgres`と`nginx`の3つあるけど、デバッグ時にいちいちnginxから配信しなくてええから、以下のように修正してな。これも環境に合わせて任意に変えてな。」

- 修正点
 - nginxサービスを削除
 - djangoサービスにデバッグ用のポート8888を開放
 - Dockerfileやマウントディレクトリなどのパスを修正

```yml:docker-compose-debug.yml
version: '3.7'
services:
    django:
        container_name: django
        build: ../django
        command: python3 manage.py runserver 0.0.0.0:8000
        volumes:
            - ../django:/usr/src/app/
        ports:
            - 8000:8000
            # デバッグ用にポートを追加
            - 8888:8888
        env_file:
            - ../django/.env
        depends_on:
            - postgres

    postgres:
        container_name: postgres
        build: ../postgres
        volumes:
            - sample_postgis_data:/var/lib/postgresql/data
            - ../postgres/sql:/docker-entrypoint-initdb.d
        env_file: ../postgres/.env_db
        ports:
            - 5433:5432

volumes:
    sample_postgis_data:
```

## リモートデバッグの開始

VSCode「今はこんな感じのディレクトリになっとるはずやな。」

ぼく「せやな。」

```shell-session:tree
containers
├── .devcontainer
│   ├── devcontainer.json
│   └── docker-compose-debug.yml
├── django
│   ├── .env
│   ├── Dockerfile
│   ├── Pipfile
│   ├── Pipfile.lock
│   ├── config
│   │   ├── __init__.py
│   │   ├── asgi.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── db.sqlite3
│   ├── entrypoint.sh
│   ├── manage.py
│   └── static
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── nginx.conf
└── postgres
    ├── .env_db
    ├── Dockerfile
    └── sql
        └── init.sql
```

VSCode「いよいよデバッグしていくわけやけど、すでに`docker-compose.yml`でコンテナを立ち上げている場合は一旦停止させておいてな。デバッグ時にコンテナを立て直すんやけど、元々のymlファイルが同じものを使っているから名前が競合してうまく立ち上がらんくなるで。」

VSCode「停止を確認したら下の青いアイコンを押して、次は`Remote-Containers: Open Folder in Containers...`をクリックして、`.devcontainer`が存在するディレクトリ（今回の例では`containers`）を選択してな。」

<img width="597" alt="image5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/5e3e107d-f619-3dab-8375-b671c4f6599b.png">

VSCode「ちなみにすでにコンテナが立ち上がっている場合は`Remote-Containers: Attach to Running Containers...`を選択するとすでに起動中のコンテナにログインできるんやけど、`devcontainer.json`で作成した設定が反映されず、拡張機能がインストールされないから注意な」

ぼく「これもハマりポイントやな。メモメモ…」

VSCode「ディレクトリを選択すると新しいウィンドウが開いて、以下のような表示が画面右下に出るで。コンテナ起動中やからしばらく待ってな」

ぼく「結構長いで。気長にいこうな。せっかちは嫌われるで。」

VSCode「ちなみに青文字の`Starting with Dev Container`をクリックするとコンテナ起動に必要なプロセスのログがリアルタイムでみれるで。エラーが起きたら停止してまうねんけど、このログでどこが悪いのか見れるで。」

VSCode「まぁ、大抵はパス間違いか、名前の競合やろけどな。」

<img width="466" alt="image6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/8164daf1-c55f-fda4-401f-736909684762.png">

VSCode「無事立ち上がったら、コンテナ内のディレクトリが表示されて、シェルも指定のディレクトリをカレントディレクトリとして開いており、起動したコンテナにアタッチされたことが確認できるで。」

<img width="1791" alt="image7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/74e8f1a5-a77d-b531-ba29-33c2ac1c6c1b.png">

VSCode「拡張機能もインストール済みや。」

ぼく「そもそも、拡張機能はインストールしたいものを`devcontainer.json`で明示的に書いてあげないとダメなんやな…」

<img width="317" alt="image8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/90fe14ab-45ce-7d22-a94a-bf15073e970e.png">

## デバッグの開始

VSCode「`実行とデバッグ`のアイコンをクリックし、`launch.jsonファイルを作成します`をクリックして…」

<img width="362" alt="image9.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/4db1c2e8-bd85-a9a2-6971-b0f4c7ed3263.png">

VSCode「その後、`Docker Debug ins Container`をクリックし…」

<img width="609" alt="image10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/18b00997-6b8f-078e-e191-8b6a343b5090.png">

VSCode「んで`launch.json`の編集画面が開くので以下のように編集して完成や！」

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            // 表示名
            "name": "django container",
            // 言語
            "type": "python",
            // デバッグ時の挙動。実行の他にもある
            "request": "launch",
            // 動作させるファイルへのパス
            "program": "${workspaceFolder}/manage.py",
            // デバッグで使用するターミナルを選択。VSCode外のターミナルを起動することもできる
            "console": "integratedTerminal",
            // プログラム実行時の引数
            "args": [
                "runserver",
                "--noreload",
                "0.0.0.0:8888"
            ],
            "django": true
        }
    ]
}
```

VSCode「最後にプログラムを実行するために、画面左下からインタープリタを選択するで(今回の例であればpython3.8を選択)」

<img width="559" alt="image11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/9d39e19f-558b-ee4e-390c-860297edbf0e.png">

VSCode「一通りの設定が終わると、`実行とデバッグ`の項目が以下のようになり、再生ボタンのような緑色の三角アイコンをクリックすることで、指定した`0.0.0.0:8888`でデバッグサーバーが立ち上がるんや。」

<img width="362" alt="image12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/3ecb0533-ce7d-5c8a-35cd-7b9dd62baa23.png">

VSCode「ボタンを押した後にブラウザから`localhost:8888`に接続するといつもの画面が見れるようになっているはずや」

ぼく「ほんまや。」

<img width="1040" alt="image13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/84f7bba4-6e3e-271d-d407-d335c6cd2745.png">

VSCode「あとはデバッグを行いたい箇所にブレークポイントを設定してブラウザなどからブレークポイントを設置した関数が実行されるようなURLにアクセスすると、VScode上でリクエストの内容がみれたり、変数が確認できたりするで！」

VSCode「`VSCode デバッグ`とかでググったら細かいやり方たくさん出てくるから調べてみてな！」

ぼく「VSCode神やな！ほなさいなら。」

お　し　ま　い