VSCode + Remote Container でtypescriptの開発環境を試す。

# 1. はじめに
- 転職によって、これまで主で開発していたC++に加えて、他の言語でのソフトウェア開発も実施する必要が生じました。
- 勉強のため、自分の個人利用するUbuntuに開発環境をDockerで整えようと思ったのですが、開発ではいちいち「コンテナにログインして〜」をやりたくない（コンテナを意識したくない）と思いました。
    - SW開発環境の現場では、Dockerに慣れていない人もいるので、開発環境の配布を意識するならば、Dockerを意識させたくない、という気持ちもあります。
- そのため、VSCodeからDockerコンテナの生成＆そのままコーディングができるRemote-Containersをお試ししてみようと思います。
   - 例として、typescriptの環境を構築します。 

# 2. 参考ページ
1. [Microsoft社提供のNode.js & TypeScript](https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/typescript-node)<br>
Microsoft社がGithub上でMITライセンスで公開しているdevcontainerのサイト。基本的な使い方はこのページに記載されています。
1. [【図解】VScodeのRemote Container拡張機能とは？わかりやすく
](https://penpen-dev.com/blog/vscode-remote-container-toha/) <br>
Remote Containerの構成をわかりやすく図解していただいています。全体像を把握する際に参考にさせていただきました。
1. [UbuntuにVSCodeをインストールする3つの方法](https://qiita.com/yoshiyasu1111/items/e21a77ed68b52cb5f7c8)<br>
UbuntuへのVSコードのインストール方法を参照しました。
1. [VSCodeのRemote-ContainerでReact(Node.js+TypeScript)環境をサクッと構築する。](https://qiita.com/tukki0210/items/3496fba336aaee202456)<br>
今回の検証内容は、ほぼこちらのページに記載されている内容をベースとしています。

# 3. 動作環境
## 3.1 ホストサーバ
- OS : Ubuntu 20.04
- CPU : Intel(R) Pentium(R) CPU G4560 @ 3.50GHz
- RAM : 8GB
- Software
    - Docker : 20.10.5
    - VSCode : 1.59.0

## 前提事項
- 参考ページ[[3](https://qiita.com/yoshiyasu1111/items/e21a77ed68b52cb5f7c8)]に記載されるMicrosoft社のリポジトリからVSCodeをインストールしています。
- 参考ページ[[4](https://qiita.com/tukki0210/items/3496fba336aaee202456)]に記載されるVSCodeプラグインのDockerとRemote-Containers、日本語化はインストール済みとしています。

# 4. おためし
## 4.1. Microsofts社のdevcontainer
- 適当にプロジェクトフォルダを定めて、VSCodeの「フォルダを開く」からフォルダを開く。
    - ここでは「typescript-dev」というフォルダで作業します。typescriptフォルダは空フォルダです。
- 「表示」→「コマンドパレット」を開きます。
![AddConfig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/e1352e21-3883-3308-24a4-936aa7ca0971.png)
- コマンドパレットに「type」と入力して、補完される「Node.js & TypeScript」を選択します。選択すると、Node.jsのバージョンを聞かれるので、defaultの16を選択します。
![SelectTypeScript.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/bd7ec8f5-b278-50a9-bbee-6843a39bbf14.png)
![SelectTypeScript2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/0a0b0369-e015-4579-510e-24e145b62f93.png)
- プロジェクトフォルダにtypescriptのremote container関連のコンフィグがダウンロードされます。
![InstalledConfig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/21c83f1c-ebdd-8006-78d9-a855a5d69a5c.png)
- VSCode左下にある「＞＜」みたいなボタンを押下して、「Reopen in Container」を押下します。
    - 押下すると、VSCodeがtypescript開発用のdockerコンテナを生成します。
![ReopenInContainer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/9527070d-d6cf-53ef-d554-7d10ebf1fe5b.png)
- 左側のツリーが下図のようになり、コンテナ内での開発環境を示すようになります。
![inContainer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/41538674-0508-b05a-8707-41b521facd29.png)
- ターミナルでコンテナの稼働状態を確認すると、以下のようになります。

```bash
$ docker container ls
CONTAINER ID   IMAGE                                                     COMMAND                  CREATED         STATUS         PORTS     NAMES
f1b712497ba1   vsc-typescript-dev-845af54d9de0baec27ffa4e44fac638d-uid   "/bin/sh -c 'echo Co…"   4 minutes ago   Up 4 minutes             blissful_ishizaka

$ docker image ls
（必要な箇所のみ）
REPOSITORY                                                TAG     IMAGE ID       CREATED         SIZE
vsc-typescript-dev-845af54d9de0baec27ffa4e44fac638d-uid   latest  153522c4976f   15 hours ago    1.12GB
mcr.microsoft.com/vscode/devcontainers/typescript-node    0-16    74a984db505d   4 days ago      1.12GB
```
- VSCode左下にある「＞＜」みたいなボタンを押下して、「Show Container Log」を押下して、コンテナ起動までのログを確認すると、build -> runの順で起動がしていることがわかります。
    - 起動時に、ホスト側のプロジェクトフォルダを/workspace以下にマウントしているようです。
    - VSCode右下のターミナルエリアで、「＋」を押下するとコンテナ内ターミナルを開くことができます。
![ShowContainerLog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/6fdb097c-9c8c-4e50-9440-f3abca721572.png)

```bash
（中略）
Run: docker build -f /（プロジェクトdirのパス）/typescript-dev/.devcontainer/Dockerfile -t vsc-typescript-dev-845af54d9de0baec27ffa4e44fac638d --build-arg VARIANT=16 /（プロジェクトdirのパス）/typescript-dev/.devcontainer
（中略）
Run: docker run --sig-proxy=false -a STDOUT -a STDERR --mount type=bind,source=/（プロジェクトdirのパス）/typescript-dev,target=/workspaces/typescript-dev --mount type=volume,src=vscode,dst=/vscode -l vsch.local.folder=/（プロジェクトdirのパス）/typescript-dev -l vsch.quality=stable -l vsch.remote.devPort=0 --entrypoint /bin/sh vsc-typescript-dev-845af54d9de0baec27ffa4e44fac638d-uid -c echo Container started
```

- VSCodeのツリーからプロジェクトフォルダ直下にHelloWorld.tsファイルを作成し、以下のようなHelloWorldを記述します。
![MakeHelloWorld.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/1aed7d02-f4c2-85dd-0467-76db560705da.png)

```typescript
console.log("HelloWorld! TypeScript.");
```

- VSCode上部の「実行」→「デバッグなしで実行」を実行したとき、デバッグコンソールエリアに「HelloWorld! TypeScript.」が表示されれば成功です。
    - または、ターミナルエリアでコマンドでコンパイルすることもできます。

```bash
node ➜ /workspaces/typescript-dev $ ls
HelloWorld.ts
node ➜ /workspaces/typescript-dev $ tsc HelloWorld.ts 
node ➜ /workspaces/typescript-dev $ ls
HelloWorld.js  HelloWorld.ts
node ➜ /workspaces/typescript-dev $ nodejs HelloWorld.js
HelloWorld! TypeScript.
node ➜ /workspaces/typescript-dev $ 
```

- 終了するときは、VSCode左下にある「＞＜」みたいなボタンを押下して、「リモート接続を終了する」を押下することで終了できます。
    - コンテナはstop状態となる。（rmはされない）

## 4.2. 所感
- 使用してみたところ、そのまま使うと、毎回Docker buildが実行されて、コンテナイメージが増得てしまうことが微妙に感じました。
    - ただし、これはdevcontainer.jsonの設定でdockerComposeFileを指定すればよさそうです。
    - ↑　docker-compose.ymlでimageを指定できるのですが、指定したimageをベースにVSCodeがさらにdocker buildしてしまう状態です。UIDに基づいてbuildが走っているっぽいのですが、原因がよくわからないです。（ご存知の方がいらっしゃいましたら教えていただきたく。。。）
- ただ、VSCodeの「Reopen in Container」でコンテナを開かなくても動作中のコンテナにattachすることもできるので、その方式でも良い気がします。

## 4.3. Attachでコンテナ接続
- フォルダ内のファイル構成は以下のような感じです。
    - docker-compose.ymlで指定するimageは4.1.で利用したMicrosoft社提供のイメージを使用します。

```bash
$ tree ../typescript-dev/
../typescript-dev/
├── HelloWorld.ts
└── docker-compose.yml

0 directories, 2 files

$ cat docker-compose.yml 
version: '3'
services:
  develop-env:
    image: mcr.microsoft.com/vscode/devcontainers/typescript-node:0-16-buster
    volumes:
      - ./:/workspace/
    command: sleep infinity
```

- VSCodeを開き、プロジェクトのフォルダを開きます。
- docker-compose.ymlファイルで右クリック→「Compose Up」でコンテナを起動させます。

![ComposeUp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/f5634036-04ac-0e18-15b9-f15b5a3ed331.png)

- VSCode左下にある「＞＜」みたいなボタンを押下して、「Attach to Running Container...」を選択します。
    - どのコンテナにアタッチするか問われるので、コンテナを選択します。
    - 選択後、コンテナにアタッチした状態で別ウィンドウでVSCodeが開きます。
    - コンテナにアタッチしたVSCodeにて、プロジェクトフォルダを開けば開発ができる。

![AttachContainer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/e6109abf-5403-b19e-75bd-1158760699b5.png)
![ProjectFolderInContainer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/4eb1db81-dcd6-9625-2919-98df001e8c81.png)

- 終わりするときは、docker-compose.ymlファイルで右クリック→「Compose Down」でコンテナを停止＆削除させます。

# 5. おわりに
- Remote Container便利ですね。巷でみなさんが活用されているのがよくわかりました。
- docker-compose.yml指定時のdevcontainerの挙動（再度buildが走る）がちょっとよくわからないです。。。
- Attachが使えるだけでもすごく便利です。既存の開発環境コンテナにVSCode Serverを入れ込みたいくらいです。