VScodeからリモート先環境やリモート先のコンテナ環境で開発する方法

## はじめに
VScodeを使ってリモート先の環境上で開発ができるとのことを聞いたので試してみた。


## 実行環境
【ローカルPC】
　　・Windows 10 pro
　　・VScode 1.50.1
　　・OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5

【リモート先の環境】
　　・Ubuntu 18.04 LTS（GCP上）
　　・docker 19.03.13
　　・python3系

## 手順
１．リモート先サーバのセットアップ
２．ローカルPCのパッケージ追加＆設定編集
３．VScodeからリモート先ホストにSSH接続
４．VScodeからリモート先のコンテナ内にSSH接続


## １．リモート先サーバのセットアップ

### SSH鍵設定

**GCP上のVMインスタンスにSSH接続できる様に設定**
　[【GCPのVMインスタンスにローカルPCからSSH接続】](https://qiita.com/smiler5617/items/34626dfd74c5eefcd885)を参考に。
　※鍵の生成はこのタイミングでしている。公開鍵はサーバー側にアップロード。秘密鍵は後で使う。

### Pythonインストール
　※VScodeからの接続後、リモート先の環境を使えているか確認するため

```shell:
# python3系がインストールされているか確認
$ sudo python --version
$ sudo python3 --version

# python3系がなければ、以下を実行
$ sudo apt update
$ sudo apt install -y python3
$ sudo apt install -y python3-pip
```

Pythonパッケージのインストール

```shell:
$ pip3 install numpy pandas beautifulsoup4
#　※pythonのパッケージは、後でチェックすることが目的なので、一応ローカルPCに入っていないパッケージを入れておく。
```

### dockerのインストールとコンテナ作成

**dockerのインストール**
　[【Dockerコンテナ内のUbuntuではsystemctlは使えない】](https://qiita.com/smiler5617/items/2a33d1aba0174480e9d3)の手順１を参考に。
　※dockerのバージョンは`docker=ce=5:19.03.14~3-0~ubuntu-bionic`

**コンテナ環境にダイレクトにSSH接続するための鍵ペアを用意**
　鍵の生成は最初の手順と同様。　※ホストと同じ鍵でもいいが、今回は別途作成。

**コンテナの作成**

```shell:
$ sudo docker container run -it -d -p 20022:22 --name test_con python:3

# コンテナに入ってパッケージをインストール
$ sudo docker container exec -it test_con /bin/bash
```


```shell:コンテナ内のコマンド
apt update 
apt install nano

# SSHの鍵設定
apt install -y openssh-server
mkdir /var/run/sshd
mkdir /root/.ssh/
nano /root/.ssh/authorized_keys
#　※公開鍵の中身をコピー

## pythonのパッケージインストール
pip install numpy pandas peewee

# SSHサーバ起動
/usr/sbin/sshd -D
```


## ２．ローカルPCのパッケージ追加＆設定編集

### VScodeを起動し、`Remote - SSH` をインストール

### ローカルPCの`.ssh/config` ファイルの編集

![Qiita-no025_img01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/6aa2f28e-6c95-c622-5d11-ab056cde5c55.jpeg)

設定ファイルの中身は以下を参考に編集。

```config:.ssh/config
Host gcp
 HostName 【GCPの外部IP】
 User 【SSH接続するユーザー名】
 Port 【ポート番号】　※記載がない場合、22番ポートとなる。
 IdentityFile 【秘密鍵までのパス】
```

### コマンドプロンプト上からSSH接続できるか確認

```shell:コマンドプロンプト
> ssh gcp

# 恐らく、パスフレーズの入力を求められる。
```

※1）秘密鍵のアクセス制限が緩すぎるとエラーになる。

```shell:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'C:\\Users\\秘密鍵までのパス' are too open.
```

※2）リモート先のPublickeyのアクセス権限が緩いと接続できない。[700] or [744] に設定しておく必要がある。

```shell:
Permission denied, please try again.
```

## ３．VScodeからリモート先ホストにSSH接続

### VScodeからSSH接続
![Qiita-no025_img02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/d03d6050-a56c-f956-317f-32b0aa13cec7.jpeg)

新しいウィンドウが開くので、そこでターゲットホストの OS カテゴリーで`Linux`を速やかに選択する
![Qiita-no025_img03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/24ceddcc-e882-4e7d-32fa-3cc100a3657a.jpeg)
　※初回の接続時、OSカテゴリー選択を行わないと`Could not establish connection to　....` となり接続できない。

**bashからリモート先環境を利用できているか確認**
　初めて接続した状態ではTERMINALが `1.install` になっているため、『+』をクリックしbashを追加する。
![Qiita-no025_img04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/533c42c0-f433-1c2f-603c-e5e5fa50117b.jpeg)
リモート先の環境をちゃんと利用できているか試しに確認

```shell:
$ python3

>>> import numpy
>>> from bs4 imoprt BeautfulSoup
```

**実行できればOK！**


## ４．VScodeからリモート先のコンテナ内にSSH接続

### ローカルPCの`.ssh/config` ファイルにコンテナの接続情報を追加

設定ファイルの中身は以下を参考に編集。

```config:.ssh/config
Host gcp
 HostName 【GCPの外部IP】
 User 【SSH接続するユーザー名】
 Port 【ポート番号】　※記載がない場合、22番ポートとなる。
 IdentityFile 【秘密鍵までのパス】

Host gcp_container
 HostName 【GCPの外部IP】
 User 【SSH接続するユーザー名】　※今回は、コンテナ内にユーザー作成などしていないため [root]
 Port 【ポート番号】　※ポートマッピングしたホスト側のポート番号（今回の場合だと20022）
 IdentityFile 【秘密鍵までのパス】　※上記のホストとは別の鍵
```

　※一旦この段階で、コマンドプロンプトやTeraTermなどからのSSH接続を試す。

**手順3**と同じ様にVScodeからSSH接続を行い、コンテナの環境をちゃんと利用できているか確認
![Qiita-no025_img05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/bb12c01d-5334-190b-7a14-94f805a6db02.jpeg)
接続完了後、TERMINALより以下を実行。

```shell:
$ python

>>> import pandas 
>>> imoprt peewee
```

**実行できればOK！**