Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【遅い&権限が引っかかる罠に注意】Windows(WSL2), docker-composeを用いてNuxt/Nextのプロジェクトを立ち上げる

この記事は「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」の1日目の記事です。

はじめに

ここ最近のWebページを見るとVueやReactがいろいろなところで導入されてきて「モダンで仮想DOMなフレームワークを触りたい!」と考える方もいるでしょう。
(WebページからVueやReactの雰囲気を感じ取れない場合はWappalyzerでも導入しておきましょう)

この記事ではWindowsにNode.jsをインストールせず、プロジェクトごとにNode.jsのバージョンを指定してほかの環境で再現できるようにDockerを用いてプロジェクトを立ち上げます。

環境

  • Windows 10 Home 20H2
  • Windows 10 Pro 1909

最低限WSL2が動作する環境が必要です。

WSL(Windows Subsystem for Linux)2の導入

調べると 公式のドキュメント含めて 同様な方法が出ます。私がまとめたものはこちらになります。

次の手順でWSL2のUbuntuからDockerを操作できる環境ができ上がります。

  1. WSL2を導入する
  2. Docker Desktop for Windowsを導入する

Windows Terminal向けの設定

Windows Terminalを使いたい場合はWSL2での作業が遅くなる問題を回避するため、Windows Terminalの初期ディレクトリの設定も変えておきます。

image.png

Windows Terminalの新規タブを開くボタンの横に選択肢がありますので、その「設定」から settings.json を開いて、Ubuntuがある profiles について startingDirectory の設定を //wsl$/Ubuntu/home/%USERNAME% にしましょう。

Linuxのパス (/home/) では受け付けられません。

settings.json
...
    "profiles":
    {
        "list":
        [
            {
                "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", // 環境によって違うので触らない
                "hidden": false,
                "name": "Ubuntu",
                "source": "Windows.Terminal.Wsl",
                "startingDirectory": "//wsl$/Ubuntu/home/%USERNAME%" // ここを追加する
            }
        ]
    },
...

Windows エクスプローラーからのアクセスが面倒?
//wsl$/Ubuntu/home/ となっているようにエクスプローラーからは \\wsl$\Ubuntu\home\ でファイル共有のようにアクセスできます。

そして、このディレクトリをエクスプローラーのクイックアクセスに登録すれば使い勝手がよくなります。
image.png

Nuxt/Nextを導入する

Dockerコンテナーの立ち上げを簡単にするため、docker-composeを用います。
docker-compose.yml を配置する必要がありますが、 create-nuxt-app, create-next-app は空のディレクトリしか受け付けないため、別にディレクトリを作成してDockerのVolumeに割り当てる必要があります。

あ、ここの部分はあまりWindows関係ないです

VueユーザーはNuxt

先にDockerfileで create-nuxt-app をグローバルにインストールするように指示してコンテナーを作らないと、Nuxtのプロジェクト作成に失敗します。

$ docker-compose exec frontend npx create-nuxt-app .
internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module '/root/.npm/_npx/17/lib/node_modules/create-nuxt-app/node_modules/ejs/postinstall.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! ejs@2.7.4 postinstall: `node ./postinstall.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the ejs@2.7.4 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2020-12-01T02_01_08_277Z-debug.log
Install for [ 'create-nuxt-app@latest' ] failed with code 1

そのため、ファイル構成は次の通りになります。

$ tree

├── Dockerfile
├── docker-compose.yml
├── .dockerignore
└── src <--- ここにNuxtのプロジェクトを作る

docker-compose, Dockerfileの設定内容は次の通りです。

  • コンテナーを立ち上げた後、追加でコマンドを実行できるように tty:true を追加する
  • development用のサーバーにアクセスできるようにポートを開く
docker-compose.yml
version: '3'

services:
  frontend:
    build:
      context: ./
      dockerfile: Dockerfile
    container_name: nuxt-frontend
    tty: true
    volumes: 
      - ./src:/app
    ports:
      - 3000:3000
    working_dir: /app
  • create-nuxt-app をグローバルにインストールする
Dockerfile
FROM node:lts

RUN npm install -g create-nuxt-app

また、 volumes でディレクトリと紐づけている構成になっていますが、すでにプロジェクトができている状態でコンテナーをビルドしようとすると context で指定しているディレクトリ以下をDockerデーモンにコピーするため時間がかかります。
そのため、 .dockerignore でプロジェクトのディレクトリを除外しておきます。

.dockerignore
src

コンテナーのビルドが伴うため、初回起動時やDockerfileを変更したときは --build オプションをつけます。

docker-compose up -d --build frontend

そのあとにコンテナー内でコマンドを実行してプロジェクトを作成します。
引数に . を選択して、 docker-compose.yml で指定した working_dir 直下にプロジェクトのファイルが展開されるようにします。

docker-compose exec frontend npx create-nuxt-app .

あとは、 src ディレクトリをVSCodeなどで開いたりdevelopment用のサーバーを立ち上げたりすることができます。

code src
docker-compose exec frontend yarn dev

そのままではWindowsホストからdevelopment用のサーバーに接続できないため、 nuxt.config.js にサーバーを 0.0.0.0 で開くように追記します。
設定が正しいと、 docker-compose exec でも yarn dev したときにWindowsホストのブラウザが自動的に開きます。

nuxt.config.js
export default {
  server: {
    port: 3000,
    host: '0.0.0.0',
  },

image.png

プロジェクトにファイルを保存できない場合は後述する対策を試してください。

ReactユーザーはNext

Next.jsのプロジェクトを作る場合は、Node.jsのコンテナーで npx create-next-app を実行するだけです。事前にコンテナーに仕込むものはありません。

そのため、ファイル構成は次の通りになります。

$ tree

├── docker-compose.yml
└── src <--- ここにNextのプロジェクトを作る
docker-compose.yml
version: '3'

services:
  frontend:
    image: node:lts
    container_name: next-frontend
    tty: true
    volumes: 
      - ./src:/app
    ports:
      - 3000:3000
    working_dir: /app

docker-compose でコンテナーを立ち上げてから、コマンドを実行してプロジェクトを作成します。
引数に . を選択して、 docker-compose.yml で指定した working_dir 直下にプロジェクトのファイルが展開されるようにします。

docker-compose up -d frontend
docker-compose exec frontend npx create-next-app .

あとは、 src ディレクトリをVSCodeなどで開いたりdevelopment用のサーバーを立ち上げたりすることができます。
こちらは特に設定変更しなくてもdevelopment用のサーバーに接続できます。

code src
docker-compose exec frontend yarn dev

image.png

プロジェクトにファイルを保存できない場合は後述する対策を試してください。

罠1: Windowsファイルシステムではフロントエンドのコンパイルが遅い

Windows Terminalの環境構築例で startingDirectory の設定を \\wsl$/Ubuntu/home/%USERNAME% にすべきとありますが、その理由がこちらになります。

デフォルトのままUbuntuのタブを開くとWindowsファイルシステムがカレントディレクトリになります。 /mnt/c/ になっているやつですね。
WSL2のUbuntuからアクセスすると厄介で、アクセスが非常に遅くなります。 "WSL2 slow" で検索するとさんざん報告されています。

そのため、WSL上で作業する場合はLinuxのファイルシステム (/mnt/c のようにWindowsのドライブレターが含まれない)に移動しましょう。

試しに Nuxt.js製の簡単なポートフォリオ のプロジェクトを yarn install して yarn generate で静的ファイルにビルドするまでの時間を確かめてみましょう。

WSLのファイルシステム(/home)の場合
$ /usr/bin/time -p yarn install

Done in 33.09s.
real 33.50
user 26.22
sys 21.91

$ /usr/bin/time -p yarn generate

Done in 7.67s.
real 7.92
user 14.26
sys 0.60
Windowsファイルシステム(/mnt/c/Users/)の場合
$ /usr/bin/time -p yarn install

Done in 304.11s.
real 304.39
user 71.74
sys 117.38

$ /usr/bin/time -p yarn generate

Done in 158.66s.
real 158.95
user 33.10
sys 11.48

Windowsファイルシステムで作業してしまうと驚きの遅さ & PCのファンが思いっきり回ります。
処理中にAdvent Calendarの記事だって書けます。

罠2: プロジェクト作成後に権限が引っかかってファイルの編集できない

こちらはUbuntu(Linux)でDockerを動かした環境での問題になります。

create-nuxt-app などで立ち上げたプロジェクトを編集しようとすると権限の問題で保存に失敗する問題です。

Failed to save 'nuxt.config.js': Unable to write file 'vscode-remote://wsl+ubuntu/home/yoshida-m/frontend/src/nuxt.config.js' (NoPermissions (FileSystemError): Error: EACCES: permission denied, open '/home/yoshida-m/frontend/src/nuxt.config.js')

これはDockerコンテナーからホストのディレクトリに紐づけているボリュームに対して書き込みをするとrootユーザーの所有権で作成されるためです。

いったんプロジェクトを立ち上げた後、WSL2で使っているグループ名とユーザー名を控えてから chown でプロジェクトのディレクトリに対して一括で設定変更すると解決します。

$ id
uid=1000(yoshida-m) gid=1000(yoshida-m) groups=1000(yoshida-m),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)
sudo chown -R yoshida-m:yoshida-m src

このほかに何かいい方法がないか探っています。

参考

Windows10 WSL2にLinux居城を爆誕させる - Qiita
https://qiita.com/v2okimochi/items/f53edcf79a4b71f519b1#%E9%96%8B%E7%99%BA%E7%94%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AFwsl%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%86%85%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F

wsl2が異常に遅くてホットリロードも効かないとき - Tamaosa
https://www.tamaosa.com/2020/wsl2/

ysd_marrrr
小学生からHTML, 高専・大学はWebアプリ(CakePHP 2.x)とスマートフォンアプリ(ObjC, Java)を作ったりしました。 HTML/CSS/JS/Vue.jsとかPHP, Node.jsなどWebで何かを作ることにフォーカスします。パソコンを触るのが好きなのでLinux/AWS/Python/シェルスクリプト…などなどに脱線します。
https://www.y-mix.dev/
opst
情報技術と社員力でお客様を成功に導く Make IT Your Success
https://www.opst.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away