VSCode + DockerでWindowsのLinux(コマンド)開発環境を構築してみる

基本Windowsをメインで使用している自分ですが、最近常々思うのがLinux系のコマンドも使用して開発したいなと。
本番環境はほぼLinux系だし、技術情報なんかもそっちのほうが多いですし。
そうなるとMacを使えと言われそうですが、やっぱり慣れ親しんだWindowsがいいんですよねｗ（わがままでスミマセン。。

と思っていたら、**VSCode** と **Docker** を組み合わせれば理想の環境を作れるという情報が！
ぱっと思いつく利点としては、

* WindowsでLinux環境(コマンド)が使える
* Dockerのコンテナに環境を作るので、開発環境の共有が容易
* プロジェクト単位でコンテナを作れば環境の競合などを考える必要なし

という訳で、早速構築してみたいと思います。
今回はWindows環境をターゲットに説明しますが、Macでも同じ環境が作れるはずです。
*ちなみに、Docker初心者もいいとこの試行錯誤状態なので、間違いなどあればご指摘頂けると助かります。*

# WindowsにDockerをインストールする
Dockerを既にインストール済みの方は飛ばしてください。

下記からWindows版のDocker Hubをダウンロードします。
https://docs.docker.com/docker-for-windows/install/

ただし、ダウンロードには Docker ID の登録が必要になるのと、（無料で登録できます。
下記システム要件となっているので注意が必要です。

* Windows10 64bit版 の Pro, Enterprise or Education  
つまり、**32bit版** や **Home** では使えないということになります。(ご注意を
* CPU仮想化が有効  
基本的に有効化されていると思います。
* Hyper-Vが有効  
こちらは何もしないと無効になっているので、有効にします。方法は簡単に説明します。
* 4GB以上のメモリ  

## まずはHyper-Vを有効化
Dockerをインストールする前にHyper-Vの機能を有効化しておきます。
*※ちなみに、VirtualBoxやVMwareといった仮想化ソフトは共存できないようです*

コントロールパネルから[プログラムと機能] > [Windowsの機能の有効化または無効化]と進んで、Hyper-Vのチェックを有効にします。
![rd005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/e5b5121e-fc5a-e570-28b7-f5c5e3e0a8f9.png)

## Docker for Windowsのインストール
ダウンロードしたexeファイルを実行。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/0facc183-028d-4b9f-8bc1-f039156e373e.png" width="600">
そのままOK。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/e75b2002-9695-6b29-7350-103c30db5537.png" width="600">
これでDockerのインストールは完了です。
終了時のボタンが「Close and log out」の場合はボタンを押すとWindowsをログアウトされてしまうので、ご注意ください。
自分はこのページを作成するためのスクショを撮っていたのですが、ファイルに保存していなかったので消えましたｗ

その後、ログインまたは再起動を行うとDockerが自動的に起動してきます。
![rd004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/5f37b714-4ea5-fb8e-c450-f7340b5f10f1.png)
初回はログインを求められるので、取得していたDockerIDでログインします。
あとはタスクトレイにクジラアイコンが出て、Dockerが起動しているのが分かるかと思います。

## Dockerの設定
ワークスペースとして使用するドライブは共有ドライブとして設定し、余裕があるならリソース(CPU,メモリなど)も割り当てを増やしておくのをお勧めします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/8ff3fd6e-8877-400b-b1cd-79a9af1d8c73.png" width="600">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/f1907ff8-52b8-a0a0-75ae-284349f7a935.png" width="600">

# VSCodeの設定
お次はVSCodeの設定です。
VSCodeがインストールされていない方は、下記からインストールしてください。
https://code.visualstudio.com/

## Remote Development(拡張機能)をインストール
VSCodeを立ち上げて、拡張機能で`Remote Development`を検索して、インストールします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/fe758147-f46a-13c9-461c-ca7858e267be.png" width="600">

情報を集めている際に、拡張機能に`Remote Containers`を使用しているものもあり、どっちが良いんだ？と悩んでいたところ、

* Remote - Containers  
コンテナ(Dockerなど)への接続用
* Remote - WSL  
Windows Subsystem for Linux(WSL)への接続用
* Remote - SSH  
SSH接続用

そして、`Remote Development`はこれら３つをセットにしたもの。らしいということが判明。
であれば、フルセットの`Remote Development`で良いかとなとｗ
（今回使用するのは`Remote Containers`の機能となります。）

# Python開発環境のコンテナを作成する
ツールの設定が終わったら、お次はコンテナの作成です。
最近はPythonを使う機会が多いので、Python向けの開発環境で説明していきます。

どこか適当なフォルダを作成し、VSCodeで開きます。
ここでは`D:\workspace\docker\test_python`をワークスペースフォルダとしています。

その後、画面左下の緑部分か、F1のコマンドパレットから
`Remote-Containers: Add Development Container Configuration Files`を選択。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/f01e9461-ab2a-9cd4-4641-12cc7b87d9dc.png" width="600">
その後、開発対象を選択することになるので、`Python3`を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/93ebbfba-127a-396a-4ebb-fd78a9d2510f.png" width="600">

`.devcontainer`フォルダとその中身が自動生成され、開き直すかとポップアップが出るので、`Reopen in Container`を選択し、ワークスペースを開き直します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ac26a738-596c-c829-00af-89b931e3cffa.png" width="">

するとコンテナの作成が始まるので、作成が完了し、コンテナに接続されるまで暫し待ちます。
![rd011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ac8d7dcf-9ede-8c2b-7490-f06645e64e13.png)
そして、下記のような表示に変われば完了です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/e743dd05-ce0e-bd91-a287-c7d11d3aa1e7.png" width="">
ターミナルがコンテナにrootでログインし、bashが使用できる状態になっているのが分かると思います。
試しに`ls`コマンドを実行すると下記の通り。
![rd013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/b7615c30-461e-451f-6ad3-21fbd90a5d5b.png)
無事bashコマンドが使用できました！

次いで、`df`コマンドを実行してみます。（ここからはターミナルの結果は画像ではなく文字列で記載します。

```bash
root@a75f794aea44:/workspaces/test_python# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          74G  2.2G   68G   4% /
tmpfs            64M     0   64M   0% /dev
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
//10.0.75.1/D   224G  7.7G  216G   4% /workspaces/test_python
/dev/sda1        74G  2.2G   68G   4% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           3.9G     0  3.9G   0% /proc/acpi
tmpfs           3.9G     0  3.9G   0% /sys/firmware
```

`/workspaces/test_python`はWindowsのワークスペースフォルダがマウントされています。
なので、下記のようにコンテナ側でファイルを作成すると、

```bash
root@a75f794aea44:/workspaces/test_python# touch text.txt
root@a75f794aea44:/workspaces/test_python# ls -l
total 0
-rwxr-xr-x 1 root root 0 Jul  9 15:01 text.txt
```
![rd014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/b0e84d8d-9ded-28f5-2d3e-5309b6a7ba61.png)
この通り、Windows上でも参照できます。(この辺りまで自動でやってくれるのはホント便利です！

# 実際にプログラムを動かしてみる
では、環境の準備が整ったところで、実際にプログラムを動かしてみます。
というわけで、毎度おなじみの「Hello, World!」です。

```python:test.py
print('Hello, world!')
```
と新規ファイルを作成し、実行します。

```bash
root@a75f794aea44:/workspaces/test_python# python test.py 
Hello, world!
```
この通り、問題なく実行できました。

# デバッグしてみる
お次はデバッグしてみます。
まず、左の虫アイコンからデバッグを表示させます。
![rd015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/26268be0-f136-936b-f988-90c4a9cd3333.png)
最初は「構成がありません」と出ていると思うので、横の歯車アイコンをクリック。
すると、構成が自動生成されます。
![rd016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/eb0f269d-fc67-21e2-35e4-3a75522d3d35.png)
こんな感じですね。
今回は「Python: Current File (Integrated Terminal)」を選択します。
そして、ブレークポイントを設定して実行(F5)！
![rd017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/25cebdc9-aad4-efc3-f766-385132c1b91d.png)
この通り、ブレークポイントで問題なく止まることを確認できるかと思います。

# Djangoを動かしてみる
最後にPythonの有名どころ、DjangoでWebページを表示してみます。

```bash
root@a75f794aea44:/workspaces/test_python# pip list
Package           Version
----------------- -------
astroid           2.2.5  
isort             4.3.21 
lazy-object-proxy 1.4.1  
mccabe            0.6.1  
pip               19.1.1 
pylint            2.3.1  
setuptools        41.0.1 
six               1.12.0 
typed-ast         1.4.0  
wheel             0.33.4 
wrapt             1.11.2
```
この通り、Djangoはインストールされていないのでまずはインストール。

```bash
root@a75f794aea44:/workspaces/test_python# pip install django
Collecting django
～省略～
Installing collected packages: sqlparse, pytz, django
Successfully installed django-2.2.3 pytz-2019.1 sqlparse-0.3.0
```
プロジェクトを作成してマイグレーション。

```bash
root@a75f794aea44:/workspaces/test_python# django-admin startproject sample ./
root@a75f794aea44:/workspaces/test_python# python manage.py migrate
```
そして、起動。

```bash
root@a75f794aea44:/workspaces/test_python# python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 10, 2019 - 15:18:56
Django version 2.2.3, using settings 'sample.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
このままWindows側のブラウザから`http://127.0.0.1:8000/`にアクセスしても、もちろんアクセスできません。
あくまでもlocalhostのポート8000で起動しているのはコンテナ側なので。
ではどうするのかというと、**ポートフォワーディング**という機能を使います。
使い方は簡単です。
まずF1を押してコマンドパレットを表示し、`Remote-Containers: Forward Port from Container`を選択します。
![rd018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/d5377922-2058-a04f-da47-af957e5c3c88.png)
すると、フォワーディングする対象のリストが表示されるので、`python manage.py runserver`を選択します。
![rd019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ea038e71-f68a-6b37-b28d-94ef74af5e32.png)
これだけです。下記のような通知が表示されればOKです。
![rd020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/fb3747dc-952c-2293-5292-0a3774e3e33a.png)
簡単にいうと、Windows側のポート8000へのアクセスをコンテナ側のポート8000に転送するようにしています。

では、改めてWindows側のブラウザから`http://127.0.0.1:8000/`にアクセスしてみます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/5475c124-9774-dd8a-9246-7ee864cfb480.png" width="600">

無事DjangoのWebページが表示されました！

ちなみにDjangoをデバッグ実行したい場合は、デバッグ構成に`Python: Django`を選択して実行(F5)すれば良いです。
![rd022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/3d16a2e7-6a72-8484-9041-1cba8156ad49.png)

# 終わりに
まだまだ自分もこの環境を使い始めたばかりですが、かなり使えそうなので積極的に使っていこうかと思っています。
ほんと便利な世の中になりました(笑)

普及してきたとはいえ、Dockerを本番環境で使用するのはまだということろでも、開発環境としてなら導入の敷居も低いと思いますので、まずは開発環境からDockerを導入というのもありだと思います。

あとは、作成した開発環境の共有などの部分もそのうちまとめられたらなと。