VSCodeとRemote-Containersとリモートdocker-daemonで最強の環境を手に入れる

# はじめに
開発環境構築は開発において最初の関門であり、面倒だし複雑な作業です。

- 従来の環境と衝突して全てが壊れる
- チームのメンバーと微妙に環境が異なってトラブルが発生する
- 環境構築手順が複雑でミスしやすい
- 何かが起きた時に原因究明が難しい

基本編では環境開発の面倒さを解決し、応用編ではさらにセキュリティと開発体験を両立した新しい開発を提案します。
この方法はほとんどの言語に適用可能ですが、今回は開発環境構築が面倒な言語の一つである**python**を例に説明します。

# 目次
1. 基本編: Remote-Containersを使って開発環境レス開発をする
2. 応用編: Remote-Containers + Cloud + シンクライアントPCで最強の環境を手に入れる
3. 実践編: 実際の開発チームで活用するパターン**(後日追記予定)**

**応用編からが本命です**

# 基本編: Remote-Containersを使って開発環境レス開発をする
[VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)の[Remote-Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)というExtensionをご存知ですか？
知っていたらこの基本編を飛ばし応用編へどうぞ！

公式ページのイメージ図です
![architecture-containers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309112/b5014b03-a612-64fe-9c23-61cd090925f1.png)


簡単にRemote-Containersを説明すると、開発環境をdocker containerで構築し、その中でコードを実行するが、コードの編集やデバッグは手元のVSCodeで行えるという神Extensionです。

開発環境をcontainerに閉じ込めるので

- PCの開発環境を汚さない
- 環境が全てコード化されていて、git管理しやすい
- 開発メンバー間で環境が必ず同じになる

などのメリットがあります。デメリットはほぼありません。
宗教上の理由でVSCodeを使えない人以外は使った方がいいレベルのExtensionです。
こちらに関しては既に様々な記事が書かれているので、導入方法などはそちらを参考にしてください。

### Remote-Containersの参考リンク

- [公式紹介ページ](https://code.visualstudio.com/docs/remote/containers)  
安心と信頼の公式ページ。
- [VS CodeでDocker開発コンテナを便利に使おう](https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0)  
こちらを先に読むと公式ページの内容が頭に入ってきやすくなるかも

## 基本編まとめ
「巨人の肩の上に立つ」ということで基本編の詳しい説明はこの記事ではしませんでしたが、是非参考リンクを見て導入してみてください。
もう開発環境構築で悩むことはなくなります。
(pythonの環境構築ツール戦争にも終止符が打たれるといいなぁ)

# 応用編: Remote-Containers + Cloud + シンクライアントPCで最強の環境を手に入れる
こちらがこの記事の本命です！
Remote-Containersの基本は抑えた前提で話を進めます。

## 概要説明

Remote-Containersはdocker上で開発を行うツールですので、実はローカルPCのdocker-daemonを使う必要はありません。
つまり、以下のような構成が可能です。

![design.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309112/a9ac652a-cdee-0a4f-d8df-e8a8b3c4a8fe.png)

ここで重要なのは

- 秘匿性が高く、持ち出したくない「ソースコード」
- マシンパワーが必要な「ビルド & デバッグ」

がリモートマシン上。というところと

- キー入力などレスポンスが気になる「IDE」
- 流出しても大した影響のない「Remote-Contaienrs用設定ファイル」

がローカルマシン上。というところ。
つまり、**ローカルマシンは弱々スペックなシンクライアントPCで、VSCodeとその設定だけを保持。ソースコードとデバッグは強いリモートサーバ上**という構成が可能。
これは、開発体験とセキュリティを両立しており、新しい開発スタイルになりうるのではと思っています。

## 実際にやってみる on GCP
今回は手元のPCとGCP上のインスタンスを用いて実際に構築してみる。
AWSでも、Azureでもなんでも大丈夫です。GCP以外を使いたい人は適宜読み替えてください。

### 前提
- GCPが使える状態になっている
- gcloudコマンドが使える状態になっている

### GCP上にインスタンスを構築し、sshの設定を保存する
GCPにはコンテナを立てることに特化したVMイメージが用意されているので、今回はそちらを使います。
zoneはご自由に設定してください。

```shell
gcloud compute instances create [instance_name] \
--image-family cos-stable \
--image-project cos-cloud \
--machine-type n1-standard-1
```

インスタンスが立ち上がったら、sshしてみます。

```shell
gcloud compute ssh [instance_name]
```

無事にsshができたらsshの設定を手元のPCに書き出します。

```shell
gcloud compute config-ssh
```

これで、sshの鍵が手元のPCに保存され、`ssh [instance_name].[zone].[project_name]`でsshできるようになります。試してみてください。

### VM上にプロジェクトを作成する
VMにsshしてください。既に`git`コマンドが入っていると思うので、任意のプロジェクトをgitからcloneしてください。  
特に思いつかない場合は`app.py`と`requirements.txt`を作成してください。
アクセス権には注意してください。containerの中から触るのでdockerグループにアクセス権が必要です。
面倒であれば今回は`chmod 777 -R [プロジェクトディレクトリパス]`でとりあえずアクセス権ガバガバにしておいてください。

### 手元のPCの上にRemote-Conteinrs用の設定ファイルを作成する
設定ファイル用のディレクトリを作成して、そこにRemote-Container用の設定ファイルを配置します。pythonプロジェクトを例にして説明します。
まずは設定ファイルが入っているmicrosoftのサンプルプロジェクトをcloneします。

```shell
git clone https://github.com/microsoft/vscode-remote-try-python.git
```

python用のファイルがいろいろ入っているので、

- .devcontainer
- .vscode

以外は全て削除してください。
次に、Remote-ContaienrsプラグインでGCP上のVMのdocker-daemonを使う設定を追加します。
`.vscode`の中に`setting.json`を作成し、以下を書き込みます。

```json
{
    "docker.host": "ssh://[container_name].[zone].[project_name]"
}
```

次にプロジェクトのマウント対象ディレクトリを変更します。
`.devcontainer/.devcontainer.json`に二つのkey-valueを追記します。

```json-doc
"workspaceMount": "source=[GCP上のprojectのフルパス],target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace"
```

この設定で、GCP上でcontainerを立てた時に、先ほど作成したプロジェクトをマウントするようにします。

### Remote-Containersで開発する
vscodeのRemote-Containersプラグインのメニューから`Reopen in Container`を選択すると、GCPのVM上のdocker-daemonに接続し、containerを立て、そこでプロジェクトを開きvscodeを接続します。  
あとは、自由に開発できます！

# まとめ
今回は基本編と応用編に分けて説明しました。
基本編やRemote-Containerの詳しい説明は省いてしまいましたが、Remote-Containerを普通に使用するだけでも、開発環境構築が不要になったり、メンバー間で環境が統一できたりとかなりのメリットがあります。
さらに、応用編で紹介したリモートのdocker-daemonを使用する方法を使うことで、手元のPCにコードを置かない、計算リソースを強力なPCに寄せる運用が可能になります。セキュリティと開発体験を両立した開発手法だと考えています。

ぜひ試してみてください。