Dockerで立ち上げた開発環境をVS Codeで開く!

待望のリモート開発機能がやってきました！

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Introducing Remote Development for <a href="https://twitter.com/code?ref_src=twsrc%5Etfw">@code</a> 🚀💻🛰️<br><br>A new set of extensions that enable you to open any folder in a container, on a remote machine, or in the Windows Subsystem for Linux (WSL) and take advantage of VS Code&#39;s full feature set. <a href="https://twitter.com/hashtag/remote?src=hash&amp;ref_src=twsrc%5Etfw">#remote</a><br><br>👉 <a href="https://t.co/ChYGQ89Y5f">https://t.co/ChYGQ89Y5f</a></p>&mdash; Visual Studio Code (@code) <a href="https://twitter.com/code/status/1124016109076799488?ref_src=twsrc%5Etfw">2019年5月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


発表記事はこちら [Remote Development with VS Code](https://code.visualstudio.com/blogs/2019/05/02/remote-development)

この機能を使うと、以下の3つの環境にVSCodeからリモート接続して開発することができるようになります。

* Docker上で動作しているWorkspace
* SSHで接続可能なリモートサーバーで動作しているWorkspace
* WindowsのWSLで動作しているWorkspace

# Docker開発環境への接続を試す

個人的に一番欲しかった Docker への接続をGoの開発環境に追加する形で試してみます。

## 試した環境

* macOS Mojave 10.14.4
* Docker Desktop 2.0.0.3
* Docker Engine 18.09.2
* VS Code 1.34.0-insider

## VS Code の設定

~~2019/05/03時点で試すには、 [Visual Studio Code - Insiders](https://code.visualstudio.com/insiders/) が必要なので、開きます。~~
2019/06/06 に [Visual Studio Code - Stable](https://code.visualstudio.com/) でも使えるようになりました！！

<img width="288" alt="スクリーンショット 2019-05-03 14.23.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/294aa9fc-6707-1115-21bd-33cc3c0c4cc3.png">

[Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) のExtensionを Insiders にインストール。 (まだ発表されたばかりで表示順序が低いのでスクロールして探す)

<img width="1005" alt="スクリーンショット 2019-05-03 14.35.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/60cf8244-f9d2-3954-00f8-cd44aabfc7d2.png">

## 開発リポジトリの設定

[Quick Start](https://code.visualstudio.com/docs/remote/containers#_quick-start-try-a-dev-container) として各開発環境をDockerで動かす例が用意されているので、参考にしつつ進めていきます。

https://github.com/Microsoft/vscode-remote-try-go を参考にしますが、docker-compose ベースではなかったので、docker-composeが使えるように少し変更を加えたものを用意したので、その環境をまず動かしてみましょう。

```sh
git clone https://github.com/yoskeoka/remote-dev-go
```

いつもならこのCloneしたディレクトリに移動するところですが、このディレクトリを Remote - Containers Extension で開きます。

開いたら、左下の青のアイコンをクリック。(Insiders を使っている人は緑)

<img width="205" alt="スクリーンショット 2019-06-07 3.08.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/d49d2b0d-668a-1e88-d98c-ae9c8dd9e197.png">

`Remote-Containers: Open Folder in Container...` を選択します。

<img width="541" alt="スクリーンショット 2019-05-03 17.04.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/b3792a04-6ec3-e44d-009c-6d1ad5c7de2b.png">

`remote-dev-go` を Clone した先のディレクトリを開きます。

開くと、 docker-compose の build が走るのでしばらく待ちます。

<img width="1103" alt="スクリーンショット 2019-05-03 17.27.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/79f92b53-cb8f-b555-0d26-530146d14a6c.png">

これでDocker内部で動作している開発環境(これを `リモート開発環境` といいます)にVS Code で接続出来ました。
通常通りに開発できますし、`~/.gitconfig` をコピーしているので、Gitの操作もローカル開発環境と同じように出来ます。

試しに Goのコードを動かしてみます。
https://github.com/Microsoft/vscode-remote-try-go から拝借した `server.go` を起動して、自動リロードがかかるように`Makefile` を用意しているので、それを実行します。

VS Codeの `TERMINAL` タブで bash を起動して make を実行します。

```sh:リモート開発環境
$ make start
reflex -g '**/*.go' -s -- sh -c "make build && ./bin/server"
[00] Starting service
[00] make[1]: Entering directory '/root/workspace'
[00] go build -o bin/server server.go
[00] make[1]: Leaving directory '/root/workspace'
[00] Server listening on port  9080
```

実行したものは `docker-compose.yml` に Port Forward の設定をしているため、ローカル開発環境からでも `curl` 等で実行できます。

```sh:ローカル開発環境
$ curl localhost:9080
Hello remote world!
```

## Git 操作

[Tips](https://code.visualstudio.com/docs/remote/troubleshooting#_avoid-setting-up-git-in-a-container-when-using-docker-compose) にある `.gitconfig` の共有を行なっているため、リモート開発環境から、 VS CodeのGit統合機能で操作することも、 `git` コマンドで操作することも出来ます。

## リモート開発環境の設定を変更した場合

リモート開発環境に接続している場合は、左下の緑ボタンから `Remote Containers: Rebuild Container` を選択して反映することができます。

## リモート開発環境へ再接続する

VS Code を開いた状態で、 左下の緑アイコンまたは、コマンドパレットから `Remote-Containers: Open Folder in Container...` を選択して、remote-dev-go リポジトリのディレクトリを再度開きます。

## リモート開発環境を完全に停止する

docker-compose で起動しているため、`docker ps` などで Docker Container を削除して下さい。

```sh
$ docker ps
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                               NAMES
dd24fb7b0c8a        remote-dev-go_remote-dev-go   "sleep infinity"         25 minutes ago      Up 25 minutes       0.0.0.0:9080->9080/tcp              remote-dev-go_remote-dev-go_1
f9f88e005b5a        phpmyadmin/phpmyadmin         "/run.sh supervisord…"   About an hour ago   Up About an hour    9000/tcp, 0.0.0.0:8080->80/tcp      remote-dev-go_phpmyadmin_1
93a095708b76        mysql:8                       "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:3306->3306/tcp, 33060/tcp   remote-dev-go_mysql_1
```

# リモート開発環境の管理

## VSCode Extensions の管理

リモート開発環境は ローカル開発環境とは別で VS Code Extensionsを追加することが可能です。

<img width="1064" alt="スクリーンショット 2019-05-03 17.47.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193814/552f94f5-58c9-5491-e2d2-005633d6eab0.png">

## settings.json の管理

`.devcontainer/settings.vscode.json` の内容をコピーする記述がリモート開発環境の`.devcontainer/Dockerfile` にあります。

今回用意している例では、 GOPATHをVS Codeに明示するために以下のようになっています。

```json:.devcontainer/settings.vscode.json
{
    "go.gopath": "/go"
}
```

## 開発用のコマンドの管理

Goで開発しているサーバーをコードの変更を検知して自動リロードをかけるための `reflex` コマンドのインストールを、 `.devcontainer/Dockerfile` に記述しています。
必要に応じて `Dockerfile`に使用するコマンドのインストールを追記していけば、開発チーム内で環境の共有が簡単に出来そうです。

## 既存の開発用コンテナとの共存

コンテナベースでのデプロイのための`Dockerfile`や、ローカル開発環境でNginx, MySQL等の依存を`docker-compose`を使って管理している場合は多いと思います。
自分の普段開発している環境でも`docker-compose.yml`で色々と立ち上げているので、その辺とうまく共存できるようにリモート開発環境が立ち上がるように設定を導入してみました。

具体的には、プロジェクトルートに元々ある(という想定の) `docker-compose.yml` には一切リモート開発環境関連の記述を入れず、`.devcontainer/docker-compose.extend.yml` にリモート開発環境の記述をしています。

```yml:.devcontainer/docker-compose.extend.yml
version: '3'
services:
  dev:
    build: 
      context: .devcontainer
      dockerfile: Dockerfile
    volumes:
      - .:/root/workspace
      - ~/.gitconfig:/root/.gitconfig
    ports:
      - 9080:9080
    command: sleep infinity
```

この追加の Docker Compose 設定については、 `.devcontainer/devcontainer.json` に

```json:.devcontainer/devcontainer.json(一部)
	"dockerComposeFile": [
        "../docker-compose.yml",
        "docker-compose.extend.yml"
    ],
```

のように書いておくことで、リモート開発環境の起動時に次のように両方をうまく読み込んでくれるため、既存のDocker関連の設定を壊す必要はありません。

```sh:リモート開発環境起動時に実行されるdocker-compose
docker-compose -f /元々の/docker-compose.yml -f /リモート開発環境用の/docker-compose.extend.yml up -d --build
```


# まとめ

これで開発のための環境をローカルに構築しなくても、 Docker と VSCode がインストールしてあれば開発出来るようになりそうです。
VS Code は Code Server として動作させ、ブラウザから操作するということも出来るようになってきているようなので、組み合わせれば Docker とブラウザさえあればどんな開発環境でもローカル環境を汚すことなく起動できるようになるかもしれません。

- [ブラウザでVS codeが使えるクラウド IDEの大本命「Coder」](https://qiita.com/MegaBlackLabel/items/bbec97db769667962bce)

また、発表当日から[ドキュメント](https://code.visualstudio.com/docs/remote/remote-overview)と[Examples](https://github.com/search?q=org%3AMicrosoft+vscode-remote-try&unscoped_q=vscode-remote-try)の充実具合が凄いです。
この開発リソースの多さが VS Code の強みと言えると思います。

# 参考

* [Try Out Development Containers: Go](https://github.com/Microsoft/vscode-remote-try-go)
* [Extending your Docker Compose file for development](https://code.visualstudio.com/docs/remote/containers#_extending-your-docker-compose-file-for-development)

リモートサーバーにSSHする場合の記事もありました。

* [VSCode公式の機能で、リモートサーバにSSHして編集する【Insiders Preview】](https://qiita.com/suzuki_sh/items/245b9817536eba808842)