WSL2にDocker環境を構築してVSCodeのRemote-Containersを使ってみた

#はじめに
チーム内活動でコンテナを使用して開発を進めることになったので、コンテナ開発の環境を構築してみました。元々はDocker Desktopを利用していましたが、2021/8/31からDocker Desktopの組織利用（条件あり）が有料化されたため、WSL2にDocker Engineをインストールしてコンテナを構築するようにしました。

#VSCode Remote-Containersとは
VSCode Remote-Containersとは、コンテナベース（Docker利用）での開発を可能とするVSCodeの拡張プラグインです。コンテナベースでの開発のメリットは様々で、例えば以下のようなものがあります。

#### ローカルマシンに変更を加えずに開発環境を構築できる
ちょっとした技術検証で「ローカルに余計なものを入れたくない」、「変更を加えすぎて何が必要だったかが分からない」、「変なものを入れてしまったかもしれない」というのはよくあることだと思います。コンテナを利用すればすべてコンテナ内で完結するので、クリティカルな変更も気軽に試すことができます。

#### 独立した複数の開発環境を１台のマシンで保持することができる
複数のコンテナを用意すれば複数の開発環境を１台のマシンで保持することができます。また、各コンテナ間の切り替えも簡単かつスピーディに行うことができます。

#### 開発環境を第三者に正確かつ容易に展開することができる
複雑なプロジェクトでは環境構築の手順が煩雑になりがちです。DockerfileやDockerイメージを用いればどのPCにも同じ環境を自動で構築することができます。

#環境及びツール
Windows 10 バージョン 2004 以降 (ビルド 19041 以降) または Windows 11 
VSCode

# Dockerの構築
## 1.WSLのインストール
WSLとは**Windows Subsystem for Linux**の略称で、インストールすることでWindowsをLinuxのように扱うことができます。Linuxコマンドで操作できるようになるのはもちろんのこと、各種aptパッケージをインストールして利用することも可能です。実行画面は以下のようになります。
![Qiita1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/e12462b3-f1ee-760c-f48b-1db3e79d01f0.png)
インストール手順はとても簡単です。PowerShellを起動して下記コマンドを実行するだけです。ディストリビューションにはubuntuなどを指定することもできます。

```
wsl --install -d debian
```

Dockerを実行するにはWSLのバージョン2が必要なので、インストール完了後にWSLバージョンを2に設定します。

```
wsl --set-version debian 2
```

## 2.Docker Engineのインストール
WSL下でのDockerインストール手順はLinuxと同じです。公式サイトに手順が掲載されているので、そちらに従ってインストールします。

***Install Docker Engine on Debian | Docker Documentation***
https://docs.docker.com/engine/install/debian/

インストール後にDocker Daemonを起動します。これでDocker環境の構築及び実行は完了です。

```
sudo service docker start
```

# VSCode Remote-Containers環境の構築
## 拡張プラグインのインストール
最初にVSCodeプラグインをインストールします。必要なのは下記の二つです。

- Remote - Containers
- Remote - WSL

![Qiita2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/8332380e-69db-e744-d6f5-85f19ac1fd6b.png)

## プロジェクトフォルダ及びコンテナ定義ファイルの用意
次にプロジェクトフォルダとコンテナ定義ファイルを用意します。WSL下での開発となるため、プロジェクトフォルダをLinuxディレクトリに配置する必要があります。エクスプローラーのアドレスバーに"\\wsl$"と入力すればLinuxディレクトリにアクセスすることができます。下記の通り、~/project/Testをプロジェクトフォルダとして作成します。（WSL上からLinuxコマンドで作成することもできます。）
![Qiita3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/c082c91c-851a-10c0-207a-58a474f0f6fb.png)

コンテナ定義ファイルはMicrosoft公式githubアカウントから取得できます。Pythonを使いたいので、Python用の定義ファイルをダウンロードします。

https://github.com/microsoft/vscode-dev-containers/tree/v0.191.1/containers/python-3/.devcontainer

必要なファイルはDockerfileとdevcontainer.jsonです。それぞれ見ていきます。

### Dockerfile
Dockerイメージをビルドするための定義ファイルです。VSCode Remote-Containersの場合はDockerfileを指定するだけでDockerイメージのビルドからコンテナの立ち上げまで自動で行われます。

Dockerファイルについて詳しく知りたい場合はDocker公式サイトをご参照ください。
***Dockerfile reference | Docker Documentation***
https://docs.docker.com/engine/reference/builder/

### devcontainer.json
devcontainer.jsonはコンテナの設定ファイルです。VSCodeやコンテナの細かい設定まで記載できるので使い慣れると非常に便利です。

```json-doc:
{
    //VSCode上で表示されるコンテナ名
	"name": "Python 3", 
    //Dockerイメージビルド時の設定
	"build": {
        //Dockerfileの指定
		"dockerfile": "Dockerfile",
        //ビルドの実行パス（devcontainer.jsonからの相対パス）
		"context": "..",
        //Dockerfileで定義した引数の指定
		"args": { 
			// Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8, 3.9
			"VARIANT": "3",
			// Options
			"NODE_VERSION": "lts/*"
		}
	},

	//コンテナ作成完了時に適用するデフォルトの設定
	"settings": { 
		"python.pythonPath": "/usr/local/bin/python",
		"python.languageServer": "Pylance",
		"python.linting.enabled": true,
		"python.linting.pylintEnabled": true,
		"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
		"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
		"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
		"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
		"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
		"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
		"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
		"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
		"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
	},

	//コンテナ作成完了時に自動でインストールするVSCodeの拡張プラグイン
	"extensions": [
		"ms-python.python",
		"ms-python.vscode-pylance"
	],

	//ローカルマシンに転送するコンテナのポート番号リスト
	// "forwardPorts": [],

	//コンテナ作成完了時に自動で実行するコマンド
	// "postCreateCommand": "pip3 install --user -r requirements.txt",

	//コンテナにログインするユーザ
	"remoteUser": "vscode"
}
```

上記以外にも様々なフィールドがあり、公式ドキュメントで詳しく説明されています。

***devcontainer.json reference***
https://code.visualstudio.com/docs/remote/devcontainerjson-reference

準備ができたら~/project/Testの下に.devcontainerという名のフォルダを作成して上記ファイルを格納します。
![Qiita4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/dee52525-b1c4-c864-be89-298df949f165.png)


## Remote-Containerの実行
いよいよRemote-Containerを実行します。WSLを起動して下記コマンドで先ほど作成したプロジェクトフォルダに移動します。

```shell
cd ~/project/Test
```

その後、下記コマンドを実行してVSCodeを起動します。

```shell
code .
```

初回実行の場合はVSCodeのアップデート確認が行われますが、問題なく完了すればVSCodeが立ち上がります。ステータスバーの一番左には「WSL:Debian」と表示されており、WSL下でフォルダを開いていることを表しています。
![Qiita5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/89a2393d-ee21-5165-65b6-876f8adbd757.png)
「F1」ボタンを押してコマンドパレットを開きます。表示された画面で「>Remote-Containers: Reopen in Container」と入力して実行します。
![Qiita6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/c78df440-3e7b-11ba-988e-67d771346c63.png)
しばらく待てばDockerイメージのビルド及びコンテナの作成が完了します。ステータスバーで先ほど「WSL:Debian」と表示されている部分を確認すると表示が「Dev Container: Python 3」に変わっているので、コンテナ内でフォルダを開いていることが分かります。
![Qiita7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/88b417c7-f483-7ac2-dd22-a5f9a06e9661.png)
拡張プラグインもインストールされています。
![Qiita8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/543c2a03-acc1-f990-8aa6-e35df76768e1.png)
ターミナル画面でPythonコマンドを実行したら無事表示されました。
![Qiita9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169128/b38dcbcc-dcc5-e711-a7e0-533e78302487.png)
これでRemote-Containersの環境が構築できました。

#まとめ
以上、WSL2でVSCodeのRemote-Containersを使ってみました。次は実際にこの環境を使って開発したものを記事にまとめたいと思います。