docker-compose で動いている環境に、開発用コンテナを追加して vscode で開発する (devcontainer.json は使わない方針で)

## つまりどういうことだってばよ？

はい。何を言ってるか分かりづらいですね。
ということで図解してみます。

まず現状の開発環境が次のような環境とします。

![memo.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/93188c85-7a6a-6f17-83ed-d3f77d58ad02.png)

`docker-compose up -d` をすることで下記のコンテナが起動。

- Nginx
- forntend
- backend
- DB

それぞれのコンテナは docker のネットワークにつながっているので通信可能。
frontend と backend は host 側のソースファイルのディレクトリをマウントして動いている感じです。

まぁ、よくある構成かと思います。
これに backend 開発用のコンテナを追加し、そこで開発をする。というのが今回の目的です。

![memo.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/075d8de5-6d95-53e2-3f55-cc90de1e4413.png)

既存の backend を使ってもいいのですが、まぁせっかくなので別々にして環境をスッキリさせた方が良いのでは！という感じですね。

## 要約すると

- 開発用のコンテナを作る
- vscode からコンテナに attach
- Let's 開発！

## ということで

お試しの環境には FastAPI が提供している "Full Stack FastAPI PostgreSQL" テンプレートを使用します。
ただ、本記事執筆の段階ではメンテが止まっていて手を入れないと動きません。
そちらについては下記の記事をご参照ください。

https://qiita.com/YoshiK159753/items/e9b902ba6b325fe8c679

で、 `docker-compose up -d` でコンテナ群を起動します。

```text
$ docker-compose ps
              Name                             Command               State                 Ports              
--------------------------------------------------------------------------------------------------------------
full-stack-fastapi-                 /start-reload.sh                 Up      80/tcp, 0.0.0.0:8888->8888/tcp,::
postgresql_backend_1                                                         :8888->8888/tcp                  
full-stack-fastapi-                 bash /worker-start.sh            Up                                       
postgresql_celeryworker_1                                                                                     
full-stack-fastapi-                 docker-entrypoint.sh postgres    Up      5432/tcp                         
postgresql_db_1                                                                                               
full-stack-fastapi-                 flower --broker=amqp://gue ...   Up      0.0.0.0:5555->5555/tcp,:::5555->5
postgresql_flower_1                                                          555/tcp                          
full-stack-fastapi-                 nginx -g daemon off;             Up      80/tcp                           
postgresql_frontend_1                                                                                         
full-stack-fastapi-                 /entrypoint.sh                   Up      443/tcp, 0.0.0.0:5050->5050/tcp,:
postgresql_pgadmin_1                                                         ::5050->5050/tcp, 80/tcp         
full-stack-fastapi-                 /entrypoint.sh --providers ...   Up      0.0.0.0:80->80/tcp,:::80->80/tcp,
postgresql_proxy_1                                                           0.0.0.0:8090->8080/tcp,:::8090->8
                                                                             080/tcp                          
full-stack-fastapi-                 docker-entrypoint.sh rabbi ...   Up      15691/tcp, 15692/tcp, 25672/tcp, 
postgresql_queue_1                                                           4369/tcp, 5671/tcp, 5672/tcp 
```

まずはここに開発用のコンテナを追加します。
名前をつけて run する感じですね。
`fastapi-backend-dev` の部分をよしなに書き換えてください。

```bash
docker-compose run --name fastapi-backend-dev backend
```

で、コンテナを起動させたら止めましょう。

次に vscode のリモートエクスプローラーから作ったコンテナに attach します。
リモートエクスプローラーを見ると先ほど作成したコンテナの名前があるはずです。
(vscode の拡張機能については割愛します。[この辺](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)をご参照です)

![memo.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/6041f55f-7652-127e-34dd-c5a6276e6c67.png)

コンテナがあったら `右クリック -> Attach in New Window` などでコンテナに attach します。

attach したら作業ディレクトリを開きましょう。
"Full Stack FastAPI PostgreSQL" テンプレートを使用しているのであれば `/app` が作業ディレクトリになるはずです。

あとは通常の開発と同じ、、、なはず。

### pytest で debug してみる

vscode から pytest で debug してましょう。

まず事前情報です。
"Full Stack FastAPI PostgreSQL" テンプレートの backend の環境では python 3.9 と 3.7 が共存していました。

`backend.dockerfile` に記載がありますが、環境としては 3.7 が正となるようなので vscode で参照する python を 3.7 にします。

![memo.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/ecb4d823-1b65-0c2f-b8aa-477664cae888.png)

あとはよしなにですね。
`app/tests/crud/test_item.py` など開いて pytest から debug しましょう。

![Peek 2023-05-04 23-33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/1f438073-785f-eedd-dd42-c271e27edc8f.gif)

### lint したり保存と同時にフォーマットしたり

lint したり保存と同時にフォーマットできるようにしてみます。

まず、次の拡張機能を追加しましょう。

- ms-python.black-formatter
- ms-python.isort

次に `.vscode/settings.json` に追記します。

```diff_json:.vscode/settings.json
 {
+  "editor.formatOnSave": true,
+  "python.linting.enabled": true,
+  "python.linting.flake8Enabled": true,
+  "python.linting.mypyEnabled": true,
+  "[python]": {
+    "editor.defaultFormatter": "ms-python.black-formatter",
+    "editor.codeActionsOnSave": {
+      "source.organizeImports": true
+    },
+  },
+  "black-formatter.args": [
+    "--config",
+    "pyproject.toml"
+  ],
+  "isort.args": [
+    "--settings-file",
+    "pyproject.toml"
+  ],
 }
```

としておくと。。

![Peek 2023-05-04 23-46.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22897/5b3e002d-acfa-c5db-1c8c-fa3fe1b4700e.gif)

gif では分かりづらいですが `=` の箇所にスペースを大量に入れた後に保存しています。
結果として最初に状態に戻っている、というわけです。

素晴ら！ :tada: 

ただし、ホスト側に `.vscode/settings.json` が追加されますので誤ってコミットしないように ignore するようにしておきましょう。

## 欠点

欠点としては、コンテナを作り直すと vscode の拡張機能などがリセットされますので再度インストールが必要です。

devcontainer.json を使えば、この辺を自動化できるのかなぁ。。。


以上です！お疲れさまでした！