Windows上でDockerが遅い時の対処法

Windowsのローカル環境に開発環境用Dockerを構築しLaravel開発を試みたのですが、ページ表示に毎回5秒くらいかかって非常に遅い

そんなはずないだろう、何か間違えているのではないかと調べたのがきっかけ

原因

DockerをWSL2ベースで動かせておらず、Windows上のファイルをLinuxファイルベースに変換する際のオーバーヘッドが原因でした。

Docker環境構築記事をググりながら進めたのですが、正しい情報で確認することは大事ですね。

WSL 2(Windows Subsystem for Linux 2)は、Windows 10およびWindows Server 2019で利用可能な機能であり、Windows上でLinuxカーネルを実行する仮想化技術です。これにより、Windowsホスト上でLinuxバイナリやツールをネイティブに実行できます。

WSL 2は、以前のWSLよりも大幅に改善されたパフォーマンスと互換性を提供します。特に、DockerなどのLinuxベースの開発ツールやアプリケーションをWindows上で実行する場合に、大幅なパフォーマンス向上が期待できます。

WSL 2は、Hyper-Vという仮想化プラットフォームを使用してLinuxカーネルをホストする仮想マシンを提供します。これにより、LinuxとWindowsの間でのリソースの分割や相互運用性が可能になります。


Dockerのパフォーマンスを向上させるには、次の方法があります。

  • DockerをWSL 2を利用した環境で実行する。
  • ソースコードをWSL 2のディストリビューション領域内に配置する。

上記を踏まえて改めて整理した構築手順を記載していきます。

Windowsで Docker + Laravel 構築手順

前提

Docker Desktopはインストール済みであること。Windows に Docker Desktop をインストール

WSL2をインストール

Docker Desktopインストール時にUbuntuもインストールしたつもりでしたが、WSL2のディストリビューションを参照するとUbuntuがありません。

PS C:\Users\syun> wsl -l -v
  NAME                   STATE           VERSION
* docker-desktop         Running         2
  docker-desktop-data    Running         2

この状態であればおとなしくWSL2インストールの手順に進みます。

最終的にはこのようなレスポンスが返ってくればOK

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

まずはPowerShell または Windows コマンド プロンプトを管理者モードで開き、wsl --install コマンドを入力し、マシンを再起動します。

wsl --install

細かい手順の参照が必要な場合はWSL を使用して Windows に Linux をインストールする方法をご覧ください。

このコマンドにより、WSL を実行し、Linux の Ubuntu ディストリビューションをインストールするために必要な機能が有効になります。

インストールが進むとUbuntuのアカウント作成を求められるので、IDとパスワードを設定します。

インストールが完了したらWSL2の設定を行います。

wsl --set-version Ubuntu 2

これでWSL2の作業は完了です。

Docker Desktopの設定変更

Docker Desktopの設定でWSL2のディストリビューションを利用可能にします。

画面上部の「設定メニュー」⇒WSL integration ⇒ Resources WSL integration と進みます。

Ubuntuを有効化する設定がありますので、キャプチャのように有効化設定を行い
「Apply & restart」ボタンを押下します。

Docker DesktopでUbuntuのWSLを有効化

アプリケーションプログラムをUbuntuの領域に配置

Ubuntu領域は下記パスになります。

\wsl.localhost\Ubuntu\home\

アドレスバーに入力するとアクセスできます。

\wsl.localhost\Ubuntu\home\[ユーザ名]\ 配下にアプリケーションプログラムを配置していきましょう。

ネットワークドライブの割り当てをしておくと後々便利です。

ネットワークドライブの割り当て設定

laravel インストール

LinuxファイルベースでLaravelを実行するために、Ubuntu領域内にLaravelをインストールします。

まずはDockerコンテナを立ち上げましょう。docker-compose.ymlのサンプルはこちら。

想定パスで指定しているのでわかりづらいですがバインドマウントでUbuntu領域を指定しています。

version: '3'
services:
  nginx:
    image: syunbiz03/nginx
    container_name: "dc"
    build:
      context: ./docker/nginx
    ports:
      - 8080:80
    volumes:
      - ./:/src

  app:
    image: syunbiz03/app
    container_name: "app"
    build:
      context: ./docker/php
    depends_on:
      - mysql
    ports:
      - 5173:5173
    volumes:
      - ./:/src
      - /src/node_modules
      - /src/vendor
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini

  mysql:
    image: mysql:8.0.37
    command: --max_allowed_packet=32505856
    container_name: "dc_mysql"
    volumes:
      - ./docker/mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=root
    ports:
      - 3306:3306

  redis:
    image: redis:alpine
    container_name: "redis"
    ports:
      - 16379:6379

コンテナが立ち上がったらLaravelのインストール先であるコンテナ名 : app のサーバに入ります。

docker compose exec app bash

Laravelのプロジェクトを作成します。

composer create-project laravel/laravel --prefer-dist myapplication

依存関係のインストール

Laravelのお作法にのっとってこの辺りのコマンドも実行していきます。

composer install
chmod -R ug+rwx storage
php artisan storage:link

npm インストール

WSL2にnpmをインストールします。

こちらのページを参考にしています。Node.js を Linux 用 Windows サブシステム (WSL2) にインストールする

sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
nvm install --lts
nvm use --lts
npm update

参考サイトではUbuntu コマンド ラインからインストールすると記載されていますが、Laravelをインストールしたコンテナで引き続き作業することをお勧めします。Ubuntuからインストールすると権限周りで面倒なことになります。

これで一通りの作業は完了です。

最後に npm run dev コマンドを実行してサーバにアクセスすれば、ページが表示されます。

パーミッションの設定

Windows のデフォルトユーザと Ubuntu のデフォルトユーザの違いにより、そのままの状態では Windows 上からファイル更新できません。IDEなどが使えないためこのままでは非常に不便です。

ファイルの所有者を見るとプロジェクト内のファイルは所有者が root になっています。

Ubuntuディレクトリのパーミッション一覧

しかしWindows上から新規で作成したファイルは下記のようにユーザID : 1000 ( Windows のデフォルトユーザ)になっています。
test.txtが新規で作成したファイルです。

Windowsのデフォルトユーザ

この問題を解決するためには、Ubuntu上でユーザID:1000のアカウントを作成し、所有者を変更します。
Ubuntu上の所有者のグループもデフォルトであるwww-dataに変更しておきましょう。

ユーザID:1000のアカウントを作成

アカウント名は「dev」、グループはwww-dataに設定します。

useradd -u 1000 dev -G www-data

新規で作成したアカウントのデフォルトグループを「www-data」に変更しておきます。

usermod -g www-data dev

所有者の変更

プロジェクト内のファイル所有者を一括で変更します。併せてパーミッションも変更しておきます。

chown -R dev:www-data myapplication
chmod -R 775 myapplication

プロジェクトフォルダ自体の所有者はrootに戻す

これをやらないと npm run dev コマンド実行時にエラーになりました。

原因追及できていませんが取り急ぎ解決する方法として所有者を元に戻します。

chown root:root myapplication

ログファイルのパーミッション変更

ログファイルはシステム側が自動で作成していくので、こちらも併せて設定が必要です。

下記の記事を参考に設定します。

Laravel
Laravel logのPermission denied対応

作業中に遭遇した各種エラー

sh: 1: vite: not found

npmのインストールに問題がある可能性があります。

下記コマンドを試してみてください。

npm update

Cannot find module @rollup/rollup-linux-x64-gnu

npmのインストールに問題がある可能性があります。

下記コマンドを試してみてください。

npm update

sh: 1: node: Permission denied

npm run dev コマンド実行時に発生したエラーです。プロジェクトのパーミッションをrootから変更したことが原因。

sh: 1: node: Permission denied

コマンドを実行する root ユーザに合わせてプロジェクトフォルダの権限を変更します。

chown root:root myapplication

コメントを残す