WindowsでDockerを使う時、正しくファイル配置しないと激重になるので注意

# 概要

WindowsでDockerを使う時、
Windowsの設定、Dockerの設定、アプリコードの配置
などを正しい状態にしておかないと
アプリがすごく重い状態になってしまいます。

正しく設定するだけで、
人によってはかなり動作が速くなると思うので
その方法を解説します。

下記のようなDockerのエラーメッセージが表示された人がいるかもしれませんが、
このエラーの解決方法も解説しています。
> Docker Desktop - Filesharing
> Docker Desktop has detected that you shared a Windows file into a WSL 2 container, which may perform poorly.
> Click here for more details.

![キャプチャ (1).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/4f9691ad-1ac8-8bc2-a7ca-8c44585b0ad5.png)


# 結論

まず最初に結論を言います。
この記事で解説する
WindowsでDockerの動作を速くする方法は、
・DockerをWSL2ベースで動かす
・ソースコードをWSL2ディストリビューション領域内に配置する
です。

これを見て、
「知っていた」「もうやってる」という人もいると思います。
もしそうじゃない人は、読み進めてください。

# なぜ遅いのか、なぜ速くなるのか

作業を始める前に、なぜ
・DockerをWSL2ベースで動かす
・ソースコードをWSL2ディストリビューション領域内に配置する
をすると速くなるのかについて説明します。

仕組みや理論についてはどうでもいいから
設定方法だけ知りたい、
という人はこの章は読み飛ばしてください。


## Docker Desktop Hyper-VとWSL2

まず、DockerのHyper-VベースとWSL2ベースの違いです。
Docker Desktopは、Hyper-VベースとWSL2ベースの2つの方式があります。
元々はHyper-Vベースだけで、後からWSL2ベースが利用可能になりました。
ここ最近インストールした人は勝手にWSL2ベースになっている場合が多いです。

あまり詳しい仕組みの解説は避けますが、（というか僕も詳しく知らない）
Hyper-VベースではHyper-V上にLinux仮想マシンを立ててそこでDockerを実行していたのですが、
WSL2ではWindows用に最適化されたLinux上でDockerを実行するため、
色々と性能が良くなっているらしいです。

https://docs.docker.jp/docker-for-windows/wsl.html#docker-desktop-wsl-2
>また、Docker Desktop は WSL 2 で導入された動的メモリ割り当て機能も活用できるため、リソースの消費を著しく改善します。つまり、Docker Desktop は、コンテナのビルドのような CPU とメモリを大量に必要とするタスクでも、 CPU とメモリを必要量しか使わないため、より速く実行できます。
>
>さらに、WSL 2 はDocker デーモンのコールド・スタート後は、起動に必要な時間が著しく早くなります。Docker デーモンの起動に、現在の Docker Desktop のバージョンでは数十秒かかるのと比べ、2秒以下です。


## ファイルの配置

WSL2ベースでDockerを使う場合、
アプリコードをWSL2のディストリビューション領域内に配置すると性能が良くなります。

逆に言うと、
アプリコードをWindowsホスト側に配置すると性能が悪くなります。
（具体的に、どこに配置すればいいの？という話は後ほど出てきます）

この性能劣化の原因は、
WindowsとLinux間でのファイルシステム変換処理です。
WindowsとLinuxではファイルシステム（ファイルの保存形式みたいなもの）が違い、
DockerはWSLのLinux上で実行されます。
もしファイルがWindows側に配置された状態で
Dockerを動かすと、いちいち全てのファイルをLinux用に変換する必要があるため処理が遅くなります。

なので、ファイルを最初からLinux領域に配置することで
この変換処理を不要にし、性能をよくしましょうということです。

記事冒頭に書いたこのDockerエラーはまさにこのファイル配置のことを言っています。

> Docker Desktop - Filesharing
> Docker Desktop has detected that you shared a Windows file into a WSL 2 container, which may perform poorly.
> Click here for more details.

（WindowsとWSL間でファイル共有している状態なので、このままだと性能悪いですよ。というメッセージ）

この仕様の影響を受けやすいのは、ファイルが大量に存在するアプリを使っている場合です。
RailsやLaravelなどのように、フレームワークの大量のソースコードを読み込むようなアプリでは
影響が大きいと思います。

逆に、フレームワークなどを使わず少量のファイルのみのアプリの場合は、
この記事の通り設定をしても大した性能の違いは出ないと思います。

Docker公式サイトでも、このファイル配置について言及されています。
（ただし、具体的にどこにどうファイルを置けばいいのか、というのが初心者には読み取りづらい気がする）

https://docs.docker.jp/docker-for-windows/wsl.html#wsl-bestpractices



# 設定作業

これから設定作業を解説していきますが、
・WSL2自体が有効になっていない人
・WSL2は有効だがDockerがWSL2ベースになっていない人
・DockerがWSL2ベースになっているがソースコードの配置場所が正しくない人
など、人によっていろいろ状態が違い、
それぞれ必要な作業が違います。

手順1つ1つの中で、
自分がその設定をする必要があるか、不要かの確認方法も書いていますので
設定不要だった場合はどんどん飛ばしていってください。

:warning::warning::warning:
本記事ではディストリビューション名を全て「Ubuntu」として記載していますが、
インストール方法によって「Ubuntu-20.04」のようにバージョン番号が付きます。
記事にあるコマンドや、コマンド結果については適宜バージョン番号付きとして読み替えてください。
※本来はUbuntu以外のディストリビューションでも問題ないですが、シンプルな解説にするためUbuntuを利用する前提で進めます
※現行環境に修正中のコードがあればコミット、プッシュしておきましょう（またはzipでバックアップしておく）

## WSL2をインストールする

:warning:  コマンドプロンプトは管理者権限で実行すること

管理者権限でコマンドプロンプトを開き、
まず下記コマンドで状態確認。

```shell
wsl --status
```

レスポンス

```shell
既定の配布: Ubuntu
既定のバージョン: 2
```

「既定のバージョン」に2が表示されればこの手順はスキップでOK。
「既定のバージョン」に1が表示されたりコマンドヘルプが表示される場合は
下記コマンドを実行してWSL2をインストール。

```shell
wsl --install
```

インストール完了後、PCを再起動。
もう1度 `wsl --status` で状態確認して
「既定のバージョン」に2が表示されればOK。

うまくいかない場合は下記の公式手順に従い、
各機能の有効化や更新などを行う。
https://docs.microsoft.com/ja-jp/windows/wsl/install-manual

## Ubuntuディストリビューションをインストール

まず下記コマンドで状態確認。

```shell
wsl -l -v
```

レスポンス

```shell
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop         Running         2
  docker-desktop-data    Running         2
```

NAMEにUbuntuがあり、VERSIONが2であればこの手順はスキップでOK。
（先ほど`wsl --install`を実行した場合は自動でインストール済みのはず）

Ubuntuがなければ下記手順に従ってインストールする。
https://docs.microsoft.com/ja-jp/windows/wsl/install-manual#step-6---install-your-linux-distribution-of-choice

VERSIONが1の場合は下記コマンドでバージョン2にする。

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

Ubuntuインストール後、PCを再起動する。

## WSLメモリ使用量を制限する

WSL上でDockerを動かすと
PCの全てのメモリを使われてしまい、
PC全体が重くなってしまう場合がある。

タスクマネージャーで「Vmmem」という項目が
PC搭載メモリのほとんどを使ってしまっているような状態の場合、対策したほうがいい。
![13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/1278974b-a193-1355-59e4-e433183a672a.png)


その場合は
`C:\Users\{ユーザ名}\` の下に、下記内容で `.wslconfig` というファイルを作成する。

```..wslconfig
[wsl2]
memory=8GB
``` 

これで、WSLが利用する最大メモリ量を制限できる。
※設定するmemoryの量は、自分のPCの搭載メモリ量やWSLの用途に合わせて検討すること

ファイル作成後、PCを再起動する。


## DockerをWSL2ベースにする

まずはDocker Desktop自体をアップデートする。
タスクトレイのdocker右クリック→「Download update...」
をクリックし、アップデートを実行。
（すでに最新バージョンの場合はこの作業は不要）

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/554ef3c5-7f6d-f987-22c6-0faca24cac00.png)



タスクトレイdocker右クリック→「Settings」→「General」を表示。
「Use the WSL 2 based engine」にチェックが付いていればOK。
チェックがなければチェックを付ける。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/85198a54-199b-2324-87b0-f2bd50045e8b.png)


## DockerでUbuntuディストリビューションの利用を許可する

タスクトレイdocker右クリック→「Settings」→「Resources」→「WSL INTEGRATION」を表示。
「Enable integration with additional distros:」の下に
先ほどインストールしたUbuntuが表示されているのでスイッチをオンにする。
「Apply & Restart」をクリックし設定反映。

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/61734e5b-3aa0-858a-1f2d-4b6078f70ad6.png)


## アプリコードをUbuntu領域内に配置

エクスプローラを開き、アドレスバーに
「\\\wsl$\Ubuntu」を入力するとWSLのUbuntu領域内を開くことができる。
この領域内にアプリコードを配置する。（「\\\wsl$\Ubuntu\mnt\c」以外で）
一般的には「\\\wsl$\Ubuntu\home\\{ユーザ名}\」の配下に配置することが多い。

既存環境のアプリコードをコピーしてきて配置すると、
パス設定やファイルの権限設定などで不具合が発生する可能性があるので、
Gitから新しくソースコードをcloneし、
ライブラリ類（Composer、Gem、npmなど）のインストールなどもWSL配下で改めて実行したほうがいい。
※インストール方法によってはUbuntuにバージョン番号が付くので、「\\\wsl$\Ubuntu-20.04」のようにバージョン番号も入力する

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/0b047d63-f49f-fcfe-c63c-e5c8b896b28b.png)


# おわりに

これで、設定は完了です。
後はいつものように
`docker-compose up` や `docker run` などのコマンドを実行してアプリを起動し、
速くなったかどうか確認してみましょう。

また、Dockerの仕組みや使い方の解説記事なども書いていますので
ぜひこちらものぞいてみてください。
[Dockerで環境構築するための最低限の概念理解](https://qiita.com/minato-naka/items/e9cd026747693759800c)

# 参考
https://docs.microsoft.com/ja-jp/windows/wsl/install
https://docs.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-containers
https://docs.docker.jp/docker-for-windows/wsl.html
https://www.docker.com/blog/new-docker-desktop-wsl2-backend/
https://penpen-dev.com/blog/vt-x-amd-v-hyper-v/
https://www.creationline.com/lab/42842
https://www.kubalog.com/docker/docker_tech/install-on-windows10-with-wsl2/