Proxy環境下のWSL2でDockerを動かす

企業によっては社外リソースへのアクセスはプロキシサーバー経由という決まりがあり，開発環境の構築に苦労されている方も少なくないかと思います．

今やWSL2やDockerはWindows PCで開発する上で欠かせないものとなっており，開発メンバーにも設定をお願いするのですが，プロキシに阻まれ上手くいかないといった場面に遭遇することが中々減らないの悩みの種だったりします．

プロキシ設定に関する記事はQiitaの中にも数多くあるのですが，手順通りに進めても上手くいかない，別のトラブルに遭遇して解決方法を更に探さないといけないことがあったため， 私の環境で上手くいった手順を1つの記事としてまとめてみました．

## WSL2のインストール

[Microsoftのページ](https://docs.microsoft.com/ja-jp/windows/wsl/install)に日本語で手順が記載されているため, この記事では手順の詳細は書きません．Windowsのバージョンによって手順が異なることもあって余計な混乱の元になるかと思います. 皆さんのPCのWindowsのバージョンを確認し, 対応する手順を公式ページで確認することが一番良いと思います．
 
少ないとは思いますが, Microsoft Storeへのアクセスも禁止されているケースもあるでしょう. その場合は[Windows Serverへのインストール](https://docs.microsoft.com/ja-jp/windows/wsl/install-on-server)の手順でWSLを入れることができます. 以前の私の環境では以前このような状況に会っていて，これで無理やりデスクトップPCにWSLを入れていました．

## WSL2のプロキシ設定

まずは`apt`や`curl`といった基本的なコマンドのプロキシ認証を突破するため, `.bashrc`に次の項目を追記します.

```~/.bashrc
export HTTP_PROXY=http://<ユーザー名>:<パスワード>@proxysrv:port/
export HTTPS_PROXY=${HTTP_PROXY}
```

`ユーザー名`, `パスワード`, `propxysrv`, `port`の部分は皆さんの環境に合わせて置き換えてください．私が所属する会社では`HTTP_PROXY`, `HTTPS_PROXY`どちらも同じ設定にする必要があるため上記のような書き方となっています．間違って`https://...`と書き始めてしまう人がいたのでこのような記述を推奨しています．

また，`ユーザー名`, `パスワード`が不要なケースもあると思います．その時は`http://<ユーザー名>:<パスワード>@proxysrv:port/`を`http://proxysrv:port/`と置き換えてください．

設定ができたら次のコマンドを実行して, `.bashrc`のプロキシ設定を読み込みましょう.

```shell
source ~/.bashrc
```

上手くいっているか心配な場合は`echo $HTTP_PROXY`で確認しましょう．
これでDockerをインストールする準備が整いました.

## Dockerのインストール

基本的には[公式ドキュメント](https://docs.docker.com/engine/install/ubuntu/)通りに進めれば良いのですが, `sudo`で外部リソースにアクセスする場合は現在の環境変数を保持してコマンドを実行する`-E`オプションをつける必要があります．そのため実行するコマンドには若干の差異が出てきます.

まずはDockerのインストールに必要なパッケージを取得します.

```shell
$ sudo -E apt update
$ sudo -E apt install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
```

次にDockerの公式GPGキーを追加します.

```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```

`apt`でDockerをインストールするため, アクセスするリポジトリを追加します.

```shell
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

最後にDockerエンジンをインストールします.

```shell
$ sudo -E apt update
$ sudo -E apt install docker-ce docker-ce-cli containerd.io
```

バージョン確認を行い, 以下のように表示されればインストール成功です．

```shell
$ sudo docker --version
Docker version 20.10.14, build a224086
```

## `sudo`なしでのDocker実行設定

DockerデーモンはUnixソケットに紐づいているため, `docker`コマンドを実行するときは`sudo`を基本的につける必要があります. `sudo`をつけずに`docker`コマンドを実行したい場合は以下のコマンドを実行しましょう.

```shell
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
```

この後の手順は上記のコマンドを実行したものとして記述しています．
設定しなくても残りの設定は進めることはできますが，`docker`コマンドの実行は適時読み替えてください．

## Dockerのプロキシ設定

### Dockerクライアントのプロキシ設定

`~/.docker/config.json`を作成し, `.bashrc`と同じプロキシ設定を記述しましょう.

```~/.docker/config.json
{
  "proxies":
  {
    "default":
     {
       "httpProxy": "http://<ユーザー名>:<パスワード>@proxysrv:port/",
       "httpsProxy": "http://<ユーザー名>:<パスワード>@proxysrv:port/",
     }
   }
}
```

### Dockerクライアントのプロキシ設定

`/etc/systemd/system/docker.service.d/override.conf`ファイルを作成し, こちらも `.bashrc`と同じプロキシ設定を記入します.

```/etc/systemd/system/docker.service.d/override.conf
[Service]
Environment = 'http://<ユーザー名>:<パスワード>@proxysrv:port/' 
Environment = 'http://<ユーザー名>:<パスワード>@proxysrv:port/' 
```

`sudo systemctl edit docker`で記入するという方法もあるのですが, WSLで実行すると以下のようなエラーが出てしまいます.

```shell
$ sudo systemctl edit docker
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
```

`systemd`が`PID1`で動作していないというエラーなのですが，これはWSL特有の問題となっており, `systemctl`コマンドが使えないだけでなく, `docker`にプロキシ設定が反映されないことに繋がっています. 私の環境では`service`コマンドを使って`docker`を起動してもプロキシ設定が反映されず, `genie`というパッケージを使うことで解決を図りました.

ここでは`genie`の詳細については触れませんが, 興味があれば[GitHubリポジトリ](https://github.com/arkane-systems/genie)の`README.md`やWikiを覗いてみてください.

## `genie`のインストール

こちらもDocker同様, [公式ドキュメント](https://arkane-systems.github.io/wsl-transdebian/)の手順をベースに`sudo`使用時の違いに気を付けながらコマンドを実行していきます．

公式ドキュメントでは最初に`lsb-release`のインストールが必要となっていますが, Dockerインストール時にすでに入っているので作業は不要です．

まずは次のコマンドを使って`apt`がアクセスするリポジトリを追加します.
ここでは`sudo -E -s`を実行し, 現在の環境変数を使用しつつ`root`ユーザーへと切り替えてから実行してください．（確認が面倒で私はこのような手順で実行してしまいました）

```shell
wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg

chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg

cat << EOF > /etc/apt/sources.list.d/wsl-transdebian.list
deb https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main
deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ $(lsb_release -cs) main
EOF

apt update
```

ここからは元のユーザーで実行しています．
`apt`コマンドで`genie`をインストールしましょう.

```shell
sudo -E apt update
sudo -E apt install -y systemd-genie
```

インストールが成功していれば下記のようにバージョンが確認できます．

```
$ genie --version
genie 2.3
```

`genie`コマンド実行時には起動までに時間がかかります．
そこで`/etc/genie.ini`を編集し, systemd-timoutを書き換えます（この場合は240秒から10秒へと変更）.

```/etc/genie.ini
[genie]
#systemd-timeout=240
systemd-timeout=10
clone-env=WSL_DISTRO_NAME,WSL_INTEROP,WSLENV,DISPLAY,WAYLAND_DISPLAY,PULSE_SERVER
secure-path=/lib/systemd:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
clone-path=false
target-warning=true
update-hostname=true
update-hostname-suffix=-wsl
resolved-stub=false
```

`genie`の実行に時間がかかるのは, 1つ以上のサービスが正常に起動しなかったことを意味するのですが，今回の内容からは話がそれてしまうのでここでは深く入り込みません．

とにかく，これでProxy環境下でDockerを実行する準備は整いました.

## Proxy環境下でDockerの動作手順

以下のコマンドで`genie`を実行します.

```shell
genie -s
```

初回は起動に時間がかかるので, 気長に待ちましょう.
また，警告メッセージがいくつか出ますが, Dockerを動かすことには支障がないので無視してもらって大丈夫です．
起動に成功すると以下のように表示が切り替わります.

```shell
username@hostname:~$ #genie 実行前
username@hostname-wsl:~$ #genie 実行後
```

次にdockerを起動し, プロキシ設定が反映されているか確認しましょう.

```shell
$ sudo service docker start
$ docker info
(略)
HTTP Proxy: http://xxxxx:xxxxx@proxysrv:port
HTTPS Proxy: http://xxxxx:xxxxx@proxysrv:port
(略)
```

最後にdockerイメージを取得して実行できるか確認しましょう

```shell
$ docker run hello-world
```

`genie`を実行してからの動作がおかしいと感じた場合は, Windows側から一度WSLを止めてから再度実行すると良いと思います．

```powershell
wsl --shutdown
```

## 参考URL

- [WSLのインストール](https://docs.microsoft.com/ja-jp/windows/wsl/install)
- [UbuntuでのDockerエンジンのインストール](https://docs.docker.com/engine/install/ubuntu/)
- [Dockerエンジンインストール後の設定](https://docs.docker.com/engine/install/linux-postinstall/)
- [プロキシサーバーを使用するためのDockerの設定](https://docs.docker.com/network/proxy/)
- [genieのGitHubリポジトリ](https://github.com/arkane-systems/genie)
- [genieのインストール準備](https://arkane-systems.github.io/wsl-transdebian/)