WSL2でVPNをつないでいる状態だとDockerコンテナからGit pull/pushができない (wsl2 + docker環境構築手順書付)

# はじめに

おそらくこの記事を見ている方はこの記事衝撃的だったかと思います。

https://www.docker.com/blog/updating-product-subscriptions/

```
Docker "Desktop" の商用利用は250名以上の社員かつ$10M/yearの売り上げがある組織では有料サブスクリプションが必要になり、遅くとも来年2022年1月末までに契約が必要
```

とのことで、仕事でDocker Desktopを利用している方で何か別のに乗り換える必要がでてきた方も多いのではないかと思います。
私はWSL2(Ubuntu20.04)にDockerをインストールすることで、Docker Desktopから卒業することにしました。

以下の手順で環境構築を行いました。
しかし、会社で利用するとVPN接続が必須になり、WSL2のコンテナ上からGit pull/pushができなくなってしまいました。

こんな感じのエラーが出ます。([引用](https://github.com/microsoft/WSL/issues/6018))

```
140.82.121.4 port 22: Connection timed out
fatal: Could not read from remote repository.
```

ということで、まずはこの問題の解決方法を紹介した後に環境構築手順も載せたいと思います。

# 解決方法

まず、[WSLの起動時にresolv.confを再生成されないようにする](https://zenn.dev/ekuinox/articles/520500939e5242a6393c)を参考に、wsl2の設定をしていきます。

Ubuntu20.04を開きます。
まずはwsl.confを編集していきます。

```
$ sudo vi /etc/wsl.conf
```

そして以下の内容を下に追加します。

```
[network]
generateResolvConf = false
```

そのあと、コマンドプロンプトを起動してUbuntu20.04を再起動させます。

```
$ wslconfig /t Ubuntu-20.04
```

再度Ubuntu20.04を起動して、`resolv.conf`を編集します。

```
$ sudo vi /etc/resolv.conf
```

`resolv.conf`のすでに書かれている内容をすべて消して、以下を追加します。

```
nameserver 8.8.8.8
```

追加できない場合は以下

```
$ sudo rm /etc/resolv.conf
$ sudo vi /etc/resolv.conf
```

再度、コマンドプロンプトでUbuntu20.04を再起動します。

```
$ wslconfig /t Ubuntu-20.04
```

ここまでできたら、次はdockerのネットワーク設定をします。
今回なぜVPNにつながらないかというと、VPNとコンテナ内の`mtu`が異なっているからです。

コンテナ内のmtu

```
$ ip addr show dev eth0 | grep mtu
147: eth0@if148: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500
```

VPNのmtu (コマンドプロンプトで実行)

```
C:\Users\jinwa>netsh interface ipv4 show interfaces

Idx     Met         MTU          状態                 名前
---  ----------  ----------  ------------  ---------------------------
 63          25        1400  connected     VPNの名前
```

[コマンドの参考はこちらからしました](https://blog.jicoman.info/2020/12/hangup-ssh-connection-using-wsl2/)

コンテナ内はmtuが1500に対して、VPNは1400でした。
ですので、mtuをコンテナ内で1400以下に設定する必要があります。

そこで、docker-compose.ymlの一番下にネットワーク設定を加えます。

```docker-compose.yml
(省略)
networks:
  default:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: 1200
```

VPN接続しないでPushする場合は以下を設定する

.bashrcに

```sh:.bashrc
export MTU=1200
```

を追加して

```docker-compse.yml
networks:
  default:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: ${MTU:-1500}
```


**docker-compose down**をしてから再度起動します (キャッシュが効いている可能性があります)

docker runを使っている場合はオプションでmtuを設定できます。
ちなみにこの設定は`/etc/sysconfig/docker-network`に書いても大丈夫だそうです。

[docker コンテナのMTUを変更する - Changing container MTU on docker](http://aikotobaha.blogspot.com/2016/09/docker-mtu-changing-container-mtu-on.html)

ここまでできたら、docker-compose upをします。
docker-composeでポートが使われているというエラーがでたら、`docker-compose down`してから試してみてください。

[Portが衝突したときにこちらを参考にしました] (https://qiita.com/terufumi1122/items/8253a47ff24b64455fe5)

また、Docker Desktopが動いているとエラーになるので終了しているかも確かめましょう。

これでコンテナ上からVPNを経由してGitに接続できるようになりました。

# WSL2からGitができない場合

```
$ sudo ip link set eth0 mtu 1200
```

# WSL2のDocker環境構築手順

今後、会社で環境構築を教えるたびに調べるのは面倒なのでまとめておきます。

WSL2をインストールしておきます

https://docs.microsoft.com/ja-jp/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/2ed4d9a7-78c8-ca8c-f209-10aad5382ad7.png)

リンクをクリックしてファイルをダウンロードしインストールまでします
`Windows システムツールのコントロール パネルからプログラム > Windowsの機能の有効化または無効化`から`Linux用Windowsサブシステム`と`仮想マシンプラットフォーム`にチェックをいれてOKを押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/44d7e363-ea42-ced5-eeea-114620e2058b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/4c672962-1f44-4f5e-9b78-c4cab45c632d.png)


エラーがでなければ再起動になります(エラーがでましたが2回目で成功したこともありました)



Ubuntu20.04をインストールします。
Windowsの検索窓から`Microsoft Store`を調べて、クリックします。

Microsoft Storeのページが表示されたら検索窓から、`Ubuntu 20.04 LTS`を検索します。
そのあと、インストールをクリックします。
終わったら起動をクリックします。

![1631239840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/1335977f-e2ce-8838-12b9-d81374ddbca5.png)

画面が開きましたら、ユーザー名とパスワードの設定を行います。
なんでもよいですが、注意としては設定中にこの画面を閉じないようにしてください。
Rootユーザーが作成されてしまい、ユーザー作成ができなくなります。

ユーザー名(ここではwatanabejin)
![1631240027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/58f6d4e1-1e3d-38d6-ce99-04dad0308aeb.png)

パスワードを同じの2回入力(表示されないので注意)
![1631240040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/95859fa0-b543-ed39-3aa1-b50202ef9e4f.png)

できると以下のような出力があります。

```
1 update can be applied immediately.
To see these additional updates run: apt list --upgradable


The list of available updates is more than a week old.
To check for new updates run: sudo apt update


This message is shown once a day. To disable it please create the
/home/watanabejin/.hushlogin file.
watanabejin@jinwa:~$
```

ここでPowershellを開いて以下のコマンドを実行します。

```
$ wsl --set-version Ubuntu-20.04 2
$ wsl -l -v
```

以下になれば成功です。

```
  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         2
```

Ubuntu20.04に戻って`docker`をインストールします。

```
$ sudo apt-get update # ここでパスワードを求められるので先ほど設定したのを入力
# Dockerのインストール (安定板)
$ curl https://get.docker.com | sh # しばらく待つ
```

dockerがインストールできたか確認します。

```
$ docker version
```

```
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:27 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

出力されていればOKです。今回は`20.10.8`が入りました。
そのあと、dockerデーモンを起動します。

```
$ sudo service docker start
#  * Starting Docker: dockerとでればOK
$ sudo docker ps
```

```
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

動いていることが確認できました。

いまの状態ですと、dockerコマンドを実行する際に常に先頭に`sudo`を付ける必要があるのでつけなくてもいいように設定します。

```
$ sudo gpasswd -a $USER docker
```

そしてウィンドウを消してUbuntu20.04を再起動させます。
再度Ubuntu20.04を起動して、dockerデーモンを起動します。

```
$ sudo service docker start
# パスワードを入力
```

そのあとで、先ほどのコマンドをsudoなしで行います。

```
$ docker ps
```

実行できれば成功です。

次に`docker-compose`をインストールします。
[インストールはここを参考にしました](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04-ja)

```
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
```

インストールできたかを確認します。

```
$ docker-compose --version
```

```
docker-compose version 1.26.0, build d4451659
```

docker-compose 1.26.0が入っておりました。

この環境Ubuntu20.04を起動するたびにdockerデーモンを起動する必要があるためそこを起動時に実行するように設定します。

```
$ sudo vi .bashrc
```

以下の内容を下に追加します。

```
sudo service docker start
```

そして、Ubuntuのウィンドウを消して、再度起動します。
すると最初にパスワードを求められます。.bashrcでsudoコマンドを使っているためです。
パスワードを入力して、` * Starting Docker: docker `と表示されれば成功です。

では、dockerのファイルを用意してdocker-compose upをしてみます。
まずは作業用ディレクトリを用意しました

```
$ cd /home/Ubunt20.04のユーザー名/ # 私の場合cd /home/watanabejin/
$ mkdir workspace # workspaceディレクトリを作成 (名前は自由)
$ cd workspace
```

作成したディレクトリ内で試しにPython環境を作ります。
ここからはVSCodeで行います。まず拡張機能から`remote wsl`をインストールします。

![1631241815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/83ee99ba-5691-790b-50f6-d800af3a4aef.png)

そして左メニューのディスプレイマークからリモート...の横のドロップダウンリストで`WSL Targets`を選択します。

![1631241798.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/bb0d4704-30c2-643e-7cc9-87b78afe4979.png)

そして、Ubuntu-20.04の横にあるディレクトリマークをクリックします。
すると別ウィンドウが開きます。これがUbuntu20.04の中になります。

先ほど作成したディレクトリを開きます。
`ctrl + k + o`で上にディレクトリが表示されるので、先ほど作成したディレクトリを選択してOKを押します。

![1631242067.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/ce0be62a-7ddb-f58a-5e96-a26c72d2b772.png)

ここからはいつものVSCodeの使い方になります。
試しにPythonのDocker環境を作ります。
[こちらを参考に作ります](https://qiita.com/reflet/items/4b3f91661a54ec70a7dc)

以下のファイルを作成します。

```
/workspace
┣ Dockerfile
┣ docker-compose.yml
```

```Dockerfile
FROM python:3
USER root

RUN apt-get update
```

```docker-compose.yml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/'
    tty: true
```

そして以下のコマンドでコンテナを起動します。

```
$ docker-compose build
$ docker-compose up -d

# コンテナに入る
$ docker exec -it python3 bash
```

これで環境構築終了です。
コンテナ内でVPN接続を使う場合は上を参考にここから設定してみてください。

# おわりに

需要がありそうということで、最近乗り換えたときの内容をそのまま記事にしてみました。
VPNの接続はたまたまできたというかんじなので設定が正しいかは各自判断お願いします。


# 参考
- [WSLの起動時にresolv.confを再生成されないようにする](https://zenn.dev/ekuinox/articles/520500939e5242a6393c)
- [using nord vpn connection - unable to clone and push repositories to github from wsl2 #6018](https://github.com/microsoft/WSL/issues/6018)
- [docker コンテナのMTUを変更する - Changing container MTU on docker] (http://aikotobaha.blogspot.com/2016/09/docker-mtu-changing-container-mtu-on.html)
- [VPN 接続時に WSL2 の SSH がハングアップした場合の解決方法]
(https://blog.jicoman.info/2020/12/hangup-ssh-connection-using-wsl2/)
- [docker コンテナのMTUを変更する - Changing container MTU on docker](http://aikotobaha.blogspot.com/2016/09/docker-mtu-changing-container-mtu-on.html)
- [【Docker】Rails+MySQLの環境をDockerで構築中「ポートの衝突」に遭遇してから解決するまで] (https://qiita.com/terufumi1122/items/8253a47ff24b64455fe5)
- [dockerで簡易にpython3の環境を作ってみる](https://qiita.com/reflet/items/4b3f91661a54ec70a7dc)
- [WSL2 内の Ubuntu 20.04 で VPN をつないだときだけ ssh できない](https://zenn.dev/mallowlabs/articles/ssh-on-wsl2-with-vpn)
- [WSLからDocker Desktop for Windowsを使う](https://kawadev.net/wsl-docker-desktop/)
- [待ってました CUDA on WSL 2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)
- [Dockerコマンドをsudoなしで実行する方法](https://qiita.com/DQNEO/items/da5df074c48b012152ee)
- [Ubuntu 20.04へのDocker Composeのインストールおよび使用方法](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04-ja)
- [UbuntuにGitをインストールする](https://qiita.com/tommy_g/items/771ac45b89b02e8a5d64)
- [1.6 使い始める - 最初のGitの構成](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-%E6%9C%80%E5%88%9D%E3%81%AEGit%E3%81%AE%E6%A7%8B%E6%88%90)
- [WSLのバージョン確認・変更方法を現役エンジニアが解説](https://codeaid.jp/blog/wsl2%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%A8%E6%9B%B4%E6%96%B0%E6%96%B9%E6%B3%95/)
- [WSL のインストール](https://docs.microsoft.com/ja-jp/windows/wsl/install)