VSCodeのRemote-ContainersでFlaskをやってみた

# 概要
VSCodeのRemote-Containersという拡張機能で、DockerコンテナにPython環境を作って、あれこれできるので、そのメモです。

## Dockerコンテナを使う目的
目的は２つあります。

１つ目は、ローカル環境が汚れない。
pyenv、anacondaなど環境を切り替えるものはありますが、結局ローカル依存になります。requirementsを作っても、Pythonのバージョンは？とか、コマンドなんだっけとか、なぜか入らないとか、pipとcondaは混ぜちゃいけないとか、たまになんかわからないけど全部ふっとんだりするので、もう卒業したいという気分です。

２つ目は、デプロイが楽。
近頃は、ローカルPC上でなくクラウド上で計算したり、サービスを提供したりすることがあるので、それも`Dockerfile`でて数少なくでやりたいです。

そういうわけで、すぐにこれらを得られるわけではありませんが、この記事では、Remote-ContainerでFlaskを立てるところまで記録します。

## 最初に結果

最終的にできたファイルはgithubに置いておきました。
[yo16 / simple_flask](https://github.com/yo16/simple_flask)

```最終的なファイル構成.
/simple_flask
    /.devcontainer
        Dockerfile
        devcontainer.json
    /simple_app
        /templates
            default.html
        app.py
    requirements.txt
```

けどこの記事では、作った結果や中身を伝えたいわけではなく、VSCodeでの手順なので、あまり関係ないかな。Flaskのシンプルなソースを作るのがめんどくさい人はダウンロードしてご使用くださいｗ



# 手順０：フォルダを準備

今回の環境を作るためのフォルダを作ります。今回は「simple_flask」。

``` ここまででのファイル構成.
/simple_app
```


# 手順１：Flaskを準備
まーなんでもいいので単純なものを作ります。

``` ここまででのファイル構成.
/simple_flask
    /simple_app
        /templates
            default.html
        app.py
```

Flaskの内容の説明はしませんが、app.pyに`app.run()`とか`@app.route('/')`とか書いてあります。これを`python app.py`するとFlaskのサイトが立ち上がります。

# 手順２：VSCodeで開き、Docker-Containersを準備
1. トップの`/simple_flask`フォルダをVSCodeで開く
2. 左のツールバーの機能拡張で、「remote-containers」を検索
3. インストール

![20200926_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/5fcc4cc2-b300-9b72-4e22-1a67a9e4882c.png)

# 手順３：Docker環境を作る
1. VSCodeの左下の><みたいな緑のところをクリック
2. 画面上に出てきたものから、「Remote-Containers: Open Folder in Container...」を選択
![20200926_4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/b18edce9-8ee2-5b2e-0c56-369e5655bc95.png)

3. 「simple_flask」のフォルダを選択してOpen
4. また上に出てくるので「Python 3」を選択
![20200926_5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/825242d8-b838-f0d1-9613-23286c0e7bca.png)

5. また出てくるので適切なPythonバージョンを選択
![20200926_6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/6f7e4552-eb01-7308-d4d0-ba422fae7793.png)

6. また出てくるのでOK（これが最後）
ちなみにここでチェックオフにして、0個選択済み になっても、なんかインストールされることになるのであとの手順で確認します。
![20200926_7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/d8586be5-b27b-9790-1178-4372b6f8af1c.png)

7. ここまでできると、下記のような画面になります。
ポイントは、右下のターミナルのところで、linuxっぽい画面になってます。（ほんとうにそうなんだけど）
ここはもう、Dockerコンテナに入ってbashを起動した状態になってます。
![20200926_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/15d8b2d0-eb2e-6ce4-58eb-139b80f2bcb3.png)

なのでそこでlsしてみるとこんな感じで、「simple_app」もしっかり置かれています。

```bash

root@c249cd5c6b06:/workspaces/simple_flask# ls -la
total 4
drwxrwxrwx 1 root root 4096 Sep 26 14:49 .
drwxr-xr-x 3 root root 4096 Sep 26 13:54 ..
drwxrwxrwx 1 root root 4096 Sep 26 14:49 .devcontainer
drwxrwxrwx 1 root root 4096 Sep 26 14:08 simple_app
```

Pythonも入ってます。

```bash

root@c249cd5c6b06:/workspaces/simple_flask# python -V
Python 3.8.5
```

# 手順４：Flaskをインストール

手順３の4でpythonのDockerイメージを選択しているので、Pythonは入っているものの、素の状態なので当然Flaskはありません。なので入れます。
これはまず、先ほどのコンソール上で入れます。

```bash

root@c249cd5c6b06:/workspaces/simple_flask# pip install flask
Requirement already satisfied: flask in /usr/local/lib/python3.8/site-packages (1.1.2)
Requirement already satisfied: Werkzeug>=0.15 in /usr/local/lib/python3.8/site-packages (from flask) (1.0.1)
Requirement already satisfied: click>=5.1 in /usr/local/lib/python3.8/site-packages (from flask) (7.1.2)
Requirement already satisfied: itsdangerous>=0.24 in /usr/local/lib/python3.8/site-packages (from flask) (1.1.0)
Requirement already satisfied: Jinja2>=2.10.1 in /usr/local/lib/python3.8/site-packages (from flask) (2.11.2)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.8/site-packages (from Jinja2>=2.10.1->flask) (1.1.1)
```
あれ、入ってる・・・（汗
ま、まぁ他の物を入れたいこともあると思うので、その場合はこの手順で、ということで、入っていなかったテイで進めますね～。

つぎに、今入っているモジュールを、Dockerコンテナが作られたときに自動的にインストールしてもらうために、requirements.txtを作ります。

```bash
root@c249cd5c6b06:/workspaces/simple_flask# pip freeze > requirements.txt
```

こうすると、当然Dockerコンテナの中にはできると思うのだけれど、VSCode上でもできます。
VSCodeで普通に開いて確認、編集ができます。

![20200926_9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/de7f4ca4-a89c-7dcb-fcdf-382cda320dc7.png)

これを次の手順で使います。


# 手順５：Dockerfileの確認と修正
コンテナを作成する際に動いているのが、`./dockercontainer/Dockerfile`です。

このファイルをVSCodeで開いてみると、Dockerコンテナを開くときに動くものがいろいろわかります。（microsoftのイメージを使ってるんだなーとか。）

ここで、手順２の6で説明した、`Node.js`をインストールするかしないか、選択してもしなくても、インストールすることになっているので、その辺りをコメントアウトして、nodejsは使わないようにしちゃいます。この記事の単純なFlaskではいらないのですが、必要な人は使ってください。

また逆に、手順４で作ったrequirements.txtは使われていないので、コメントを外します。/tmp/pip-tmp/へコピーして、`pip install`して、終わったら消してますね。

手を加えたDockerfileが下記です。

```Dockerfile
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/python-3/.devcontainer/base.Dockerfile

# [Choice] Python version: 3, 3.8, 3.7, 3.6
ARG VARIANT="3"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

# [Option] Install Node.js
#### comment out
# ARG INSTALL_NODE="true"
# ARG NODE_VERSION="lts/*"
# RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
#### removed "#"
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
   && rm -rf /tmp/pip-tmp

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
#     && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
```

# 手順６：もう一度Dockerコンテナを起動

変更したDockerfileを使って、もう一度コンテナを作り直します。

1. 左下の緑のところをクリック
![20200926_10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/1a9bcb3d-1f2d-4135-7061-706e4d0996d0.png)

2. 上のプルダウンから「Remote-Containers: Rebuild Container」を選択
![20200926_11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/7ff94840-9a62-93a7-8c35-7e7bbc9b1f5f.png)

これですべて完了！お疲れさまでした。


# 動作確認
右下のターミナルからpythonでapp.pyを起動すると、いつものFlaskサーバーが立ち上がります。

```bash
root@acebfd6333f5:/workspaces/simple_flask# python ./simple_app/app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

以上ですー