Windows10+WSL2(Ubuntu)+DockerでCircleCIのローカル実行ができる環境を作る

最近はWindows環境とWSL(Windows Subsystem for Linux)2にお熱で、CircleCI力が足りないと感じたのでCircleCIのテストができる環境を作りました。
「WSLで入れたLinuxにはDockerを入れなくていいのかな…」という心配を持った以外は簡単に導入できます。

## TL;DR

 * WSL2とUbuntuをセットアップした状態でDockerを導入するとUbuntuの上でDockerの仮想マシンが動く
 * WSL2のUbuntu上にDockerを動作させるようにするとWindows, Ubuntu側の両方からDockerを操作できる
 * Ubuntu側でCircleCI CLIをインストールするとWindows側でセットアップしたDockerを使ってCIのローカル実行ができる

## 動作環境

 * Windows 10 Home 2004
 * Windows 10 Pro 1909

## WSL(Windows Subsystem for Linux)2の導入

`dism.exe` を使ってWSLに必要なLinux 用 Windows サブシステムと仮想マシン プラットフォームをインストールします。
このパッケージは **再起動しないと反映されないため、** インストールした後はWindowsを再起動します。

```
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```

次に、 Linux カーネル更新プログラム パッケージをインストールします。リンクからダウンロードしたファイルをインストールします。

https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

次のコマンドで、新しく導入するLinuxディストリビューションをWSL2の形式でインストールされるようにデフォルトのバージョンを指定します。

```
wsl --set-default-version 2
```

この作業をしないと、次で導入するLinuxがWSL1の形式でインストールされます。

## Linuxディストリビューション(Ubuntu)の導入

https://aka.ms/wslstore のリンクを使うとインストールできるLinuxディストリビューションのギャラリーがMicrosoft Storeで開きます。そこからUbuntuをインストールします。

インストールが終わったらスタートメニューからUbuntuをクリックして起動させます。 **初期設定のため数分かかりますが** 次回以降はすぐに起動します。

Ubuntuで使用するユーザー名とパスワードが求められますので、ここで設定します。

### WSL2で導入されたかの確認

ここまで終わったら、Windowsの端末(コマンドプロンプト/PowerShell)で次のコマンドを実行して、導入したLinuxディストリビューションのリストを表示します。

```
wsl -l -v
```

次のように表示されますが、

```
   NAME                   STATE           VERSION
 * Ubuntu                 Running         2
```

VERSIONが2になっていない場合は、WSL1で導入されています。
VERSION 2に変換するには「Linux カーネル更新プログラム パッケージ」をインストールしてから、WSL1で導入したLinuxに対してWSLのバージョンを2にします。

```
wsl --set-version Ubuntu 2
```

公式のドキュメントではこのVERSIONの変更は双方向でできるとされています。

### Ubuntuのパッケージの更新

Ubuntu側のパッケージも更新しておきます。
はじめに、更新が高速になるようにパッケージのソースを日本サーバーに変更します。

```
cd /etc/apt
sudo sed -i.bak -e "s/http:\/\/archive\.ubuntu\.com/http:\/\/jp\.archive\.ubuntu\.com/g" sources.list
```

次のコマンドでUbuntuのパッケージを更新できます。

```
sudo apt update
sudo apt upgrade -y
```

### Windows Terminalの導入

Ubuntuはスタートメニューから起動できますが、Windows Terminalを導入すると

 * コマンドプロンプト
 * PowerShell
 * Azure Cloud Shell
 * Ubuntu

などの端末をタブにして一つのウィンドウにまとめることができます。各端末の起動もタブを作成するだけと簡単になります。

Windows TerminalはUbuntuをインストールしたMicrosoft Storeから導入できます。


## Docker Desktop for Windowsの導入

Docker Desktop for WindowsのDockerを導入します。 **Ubuntu側にDockerは導入しません。**
次の公式ページからGet Dockerをクリックしてインストーラーを入手します。
https://hub.docker.com/editions/community/docker-ce-desktop-windows

インストーラーを実行すると"Enable WSL 2 Windows Features"のチェックボックスが入っているはずなので、確認してインストールを続けます。
Docker Desktopが起動してチュートリアルのウィンドウが表示されたら閉じます。

Windows側の端末から `wsl -l -v` でDockerの仮想環境が立ち上がっているのが確認できます。

```
wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2
```

Windowsの端末からDockerのコマンドが実行できます。

```
docker run -it hello-world
```

任意のコンテナーをpullして立ち上げると `docker images` のリストに登録されます。

```
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        10 months ago       13.3kB
```

別途導入していないはずのUbuntu側からも同様なDockewrの操作ができます。これでDockerを使用するCircleCI CLIでローカル実行ができるようになります。

## CircleCI CLIの導入

Ubuntuの端末で作業します。次のコマンドでCircleCI CLIをインストールします。

```bash
sudo sh -c "curl -fLSs https://circle.ci/cli | bash"
```


## CircleCIアカウントの設定

CircleCIのアカウントをCLIに登録します。CircleCIのアカウントを持っていない場合は[新規作成します。](https://circleci.com/ja/signup/)

CircleCI CLIをインストールしたら `circleci setup` を実行します。
"CircleCI API Token"と表示されたらCircleCIのダッシュボード右下に表示されている自分のアイコンをクリックしてUser Settingsを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/e7636ddf-ca33-e9e8-6030-7bbbb1caa482.png)

Personal API TokensをクリックするとAPI Tokenのリストが表示されるのでCreate New Tokenをクリックして新しく作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/cc0e895a-dc6c-3f42-43c0-9ed3eb7f9b8e.png)

新規作成するAPI Tokenの名前を入力するとTokenが表示されますが、 **再度表示することができないため** コピーをして先ほどのCLIの設定で入力して受け付けられた後に、ダイアログを閉じましょう。

API Tokenを使って通信できるか確認するためにCircleCI CLIの画面にはユーザー名が表示されます。


## ローカル実行するためのプロジェクトの作成

CircleCIのローカル実行はGitで管理されているプロジェクトが必要です。新しくディレクトリを作成した後で `git init` を実行してGitを使うようにします。

```bash
mkdir sample-project
cd sample-project
git init
```

Ubuntuで初めてGitを使う場合は、コミットしたユーザーの名前とメールアドレスを登録する必要があります。

```bash:登録例
git config --global user.email "41146529+ysd-marrrr@users.noreply.github.com"
git config --global user.name "ysd-marrrr"
```

何かファイルを作成してGitのコミットを作成します。

```bash
echo "Hello World!" > README.md
git add README.md
git commit -m "1st commit"
```

Gitで何かコミットしたらCircleCIの設定ファイルを作ります。

```bash
mkdir .circleci
```

`.circleci` ディレクトリに `config.yml` を作成します。

```yml:./.circleci/config.yml
version: 2.0
jobs:
  build:
    docker:
      - image: circleci/ruby:2.4.2-jessie-node
    steps:
      - checkout
      - run: echo "Hello World"
```

ローカル実行前に設定ファイルを確認できます。 "Config file at .circleci/config.yml is valid."で設定ファイルが正しいことがわかります。

```
circleci config validate
```

準備できたらローカル実行しましょう。

```
circleci local execute
```

Success!と表示されたら成功です！
ここで `docker images` を実行すると一連の操作で使ったCircleCIのイメージがローカルに登録されています。

### Windowsの端末からDockerイメージを確認する

ここでWindowsの端末から同様に `docker images` を実行するとCircleCIのイメージが登録されています。

```
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
circleci/picard     latest              b85648cb1ea4        45 hours ago        94.5MB
hello-world         latest              bf756fb1ae65        10 months ago       13.3kB
circleci/ruby       2.4.2-jessie-node   54898fcdc277        2 years ago         968MB
```

Windowsで導入したDockerがUbuntuから使うことができましたね！WSL2とDocker Desktop for Windowsを用いるとUbuntuで改めてDockerを導入する必要はないということになります。

## 参考

Windows Subsystem for Linux (WSL) を Windows 10 にインストールする | Microsoft Docs
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

Docker Desktop for WindowsのバックエンドとしてWSL2を使用する | Developers.IO
https://dev.classmethod.jp/articles/docker-desktop-for-windows-on-wsl2/

Windows Subsystem for Linux 2(WSL 2)をセットアップしてみた | Developers.IO
https://dev.classmethod.jp/articles/how-to-setup-wsl2/

Ubuntu 18.04のWSL上へのインストールと初期設定
http://www.aise.ics.saitama-u.ac.jp/~gotoh/HowToInstallUbuntu1804OnWSL.html#toc11

CircleCI のローカル CLI の使用 - CircleCI
https://circleci.com/docs/ja/2.0/local-cli/