VS CodeのRemote-Containersでリモートサーバー上のコンテナーの開発を行う方法

（2020/7/16追記修正）

- 2020/7/15に開催された [VS Code Meetup #6](https://vscode.connpass.com/event/176699/) にて本記事に関連する発表を行いました。
 - 資料：[Remote-Containersの接続先ホストにFedora CoreOSを使う](https://speakerdeck.com/tnk4on/using-fedora-coreos-for-remote-containers)

# 概要
- ローカル端末上のVS CodeでRemote-Containersを実行し、リモートサーバー上のコンテナーに直接接続して開発を行えるようにする
 - ローカル端末上でコンテナーは起動しない
 - ローカル端末上でDockerデーモンは起動しない（ただしDocker CLIのみ必要）
- リモートサーバーへはRemote-Containers実行時に自動でSSH接続する
 - VScodeが自動接続するので、別途SSH接続等は不要
- Forward Port/Publish Portを使いコンテナーのポートへ接続を行う
  - ローカル端末のブラウザ等で動作テストができる

# 環境
- ローカル端末: MacBook Pro(macOS Catalina)
    - VS Code: 1.41.1
    - Extentions: 
        - Remote-Containers：0.85.0〜0.94.0のどれか
        - Remote-SSH

- リモートサーバー: RHEL 7.7
  - docker-ce: 19.03.5
  - containerd: 1.2.10
  - runc: 1.0.0-rc8+dev
  - docker-init: 0.18.0

## 構成図
![remote-containers_arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526320/70d14b78-2bc2-077b-6fbb-5c4e6b6a5497.png)


# 経緯
Mac上でVS Code + Remote-Containersの開発環境を整えようとして、Docker Desktop for Macのバグに遭遇。

- macOS CatalinaにおいてDocker Desktop for Mac stable版（2.1.0.5）でDockerが起動しない
- Edge版（2.1.7.0）でDockerは起動するものの、`com.docker.hyperkit`のプロセスがCPU100%で張り付く（ファンが爆音に）

GitHubのIssueを見てみると、Dockerが起動しないことやプロセスの暴走バグは以前から続いていて今後も改善が期待できない。

  - [Issues · docker/for-mac](https://github.com/docker/for-mac/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc)


また、VS Codeのドキュメントにもプロセス暴走のバグについて記載有り。

  - [Docker limitations#](https://code.visualstudio.com/docs/remote/containers#_docker-limitations)

試行錯誤した結果、Mac上でDockerを動かすことをやめてLinuxサーバー上でDockerを動かし、そこへリモート接続する環境を模索することにした。
しかしながら、Remote-Containersのデフォルト設定ではローカルのDocker環境でコンテナーを起動するので、リモートサーバーへ接続する方法を探して実現してみた。


# Remote-Containersでリモートサーバーへの接続方法
>VS Code、Extentionsの導入、設定についての説明は省略。

## 対象のドキュメント

 - [Advanced Container Configuration](https://code.visualstudio.com/docs/remote/containers-advanced#_developing-inside-a-container-on-a-remote-docker-host)

`Developing inside a container on a remote Docker host`というタイトルで説明されている。

## 設定方法
設定は簡単で、`setting.json`に`docker.host`の行を追加してVS Codeを再起動するだけ。

**`setting.json`の設定例**

```
    "docker.host": "ssh://root@192.168.1.60"
```

リモートサーバーへのSSH接続には鍵認証が必要なので設定を行う。

VS CodeでのSSH設定のドキュメントはこちら。

 - [Visual Studio Code Remote Development Troubleshooting Tips and Tricks](https://code.visualstudio.com/docs/remote/troubleshooting#_configuring-key-based-authentication)

サーバー/クライアント双方で鍵の準備ができたら、VS Code用の設定を行う。
>In VS Code, run Remote-SSH: Open Configuration File... in the Command Palette (F1), select the SSH config file you wish to change, and add (or modify) a host entry in the config file as follows to point to the file:

実際にはSSHコンフィグの設定なので直接変更しても問題ないと思われる。
`IdentityFile`の行を追加して鍵の場所を指定。

**~/.ssh/configの設定例**

```
Host 192.168.1.60
  HostName 192.168.1.60
  User root
  IdentityFile ~/.ssh/id_rsa
```

これでリモートサーバー上のコンテナーへRemote-Containersで直接接続ができるようになる。
SSHプロトコル以外にTCPプロトコルを使った方法もあるようだが未検証。




# Forward Port
Remote-Containers起動直後はローカル端末とリモートサーバー上のコンテナーは隔離されているので、コンテナー内のポートへ直接接続ができない。そこでForward Portを追加して、ローカル端末のポートをコンテナー内のポートへ転送を行う。

### 対象のドキュメント

 - [Temporarily forwarding a port](https://code.visualstudio.com/docs/remote/containers#_temporarily-forwarding-a-port)

### 手順
1. コンテナー内でテストしたいサーバー等を起動し、ポートがリッスンしていることを確認
1. F1→`Remote-Containers: Forward Port from Container...`を選択。
1. `Forward XXXX`を選択（XXXXはコンテナー内で起動したポート番号）
1. ローカル端末のブラウザーやcurlコマンドで`http://localhost:XXXX`へ接続（MacのSafariでlocalhostを指定した場合エラーになるので、127.0.0.1に置き換えると接続できる）

# Publish Port
Forward Portでコンテナー起動の都度設定を行うのが手間な場合は、Publish Portを設定してコンテナー起動時に常にポート転送がされる設定をする

### 対象のドキュメント
 - [Always publishing a port](https://code.visualstudio.com/docs/remote/containers#_always-publishing-a-port)

### 手順
1. `devcontainer.json`に`addPort`の設定を追加しポートを指定する。
1. F1→`Remote-Containers: Rebuild Container`を選択。コンテナーをリビルド。
1. コンテナー内でテストしたいサーバー等を起動し、ポートがリッスンしていることを確認
1. ローカル端末のブラウザーやcurlコマンドで`http://リモートサーバーのIP又はFQDN:XXXX`へ接続

**`devcontainer.json`の設定例（docker:9000、コンテナー:5000）**

```
	"appPort": ["9000:5000"],
```
上記の例で`docker ps`を実行すると、対象のコンテナーIDの`PORTS`が`0.0.0.0:9000->5000/tcp`になる。

# まとめ

VS Codeでシームレスなコンテナー開発環境を整えることができた。ローカル端末にはVS Codeのみ用意すれば良く、Dockerデーモンの起動すら不要（Docker CLIのみ必要）。リモートサーバーを起動しておくことと、常にネットワーク接続を必要とすることが条件だが、十分におつりが来る程度にはストレスフリーな開発環境が構築できたと思う。
Remote-Containersを使ったコンテナー開発の参考にしてください。

→関連記事：[Remote-ContainersでPodmanを使う動作検証（随時更新）](https://qiita.com/tnk4on/items/05d6b0567fb076e5b757)