Docker上でNext.jsプロジェクトを作成してNext.js公式のチュートリアルを試したい。

# はじめに
普段はバックエンドがメイン。
業務でのフロントエンドはVueが少し、Reactはプライベートでちょっと触ったことあるレベル。
Reactができる方が今後の案件の幅も広がりそうなので、本格的に物作って勉強を始めようと思う。

# やりたいこと
Next.js公式のチュートリアルをDocker上でやりたい！

# 構築手順

ディレクトリ構成
```txt
(root)
└- Dockerfile
└- compose.yml
```

Dockerfile
```txt
FROM node:18.17-alpine

WORKDIR /app
```

compose.yml
```yml
services:
  app:
    build:
      context: .
    tty: true
    volumes:
      - ./src:/app
    environment:
      - WATCHPACK_POLLING=true
    command: sh -c "npm run dev"
    ports:
      - "3000:3000"
```

ターミナルで以下コマンド実行
```bash
% docker compose run --rm app sh -c 'npx create-next-app@latest nextjs-tutorial --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"'
```

実行すると・・・
```bash
[+] Creating 1/1
 ✔ Network nextjstutorial_default  Cre...                                  0.0s 
[+] Building 1.5s (6/6) FINISHED                           docker:desktop-linux
 => [app internal] load build definition from Dockerfile                   0.0s
 => => transferring dockerfile: 111B                                       0.0s
 => [app internal] load metadata for docker.io/library/node:18.17-alpine   1.5s
 => [app internal] load .dockerignore                                      0.0s
 => => transferring context: 2B                                            0.0s
 => [app 1/2] FROM docker.io/library/node:18.17-alpine@sha256:3482a20c97e  0.0s
 => CACHED [app 2/2] WORKDIR /app                                          0.0s
 => [app] exporting to image                                               0.0s
 => => exporting layers                                                    0.0s
 => => writing image sha256:5e3535a68f07f3878626cedb524d3da85f55f12337615  0.0s
 => => naming to docker.io/library/nextjstutorial-app                      0.0s
Need to install the following packages:
  create-next-app@14.2.3
Ok to proceed? (y) y
Creating a new Next.js app in /app/nextjs-tutorial.

Downloading files from repo https://github.com/vercel/next-learn/tree/main/basics/learn-starter. This might take a moment.

Installing packages. This might take a couple of minutes.

added 22 packages, and audited 23 packages in 8s

3 packages are looking for funding
  run `npm fund` for details

found **0** vulnerabilities

Success! Created nextjs-tutorial at /app/nextjs-tutorial

Inside that directory, you can run several commands:

  npm run dev
    Starts the development server.  

  npm run build
    Builds the app for production.

  npm start
    Runs the built app in production mode.

We suggest that you begin by typing:

  cd nextjs-tutorial
  npm run dev
  
npm notice 
npm notice New major version of npm available! 9.6.7 -> 10.7.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.7.0
npm notice Run npm install -g npm@10.7.0 to update!
npm notice
```

コンテナが実行され、コンテナ上にNext.jsアプリが作成された。
コンテナを起動してみる。

```bash
% docker compose up
```

```bash
[+] Running 0/0
 ⠋ Container nextjstutorial-app-1  Cre...                                  0.0s 
Attaching to app-1
app-1  | npm ERR! code ENOENT
app-1  | npm ERR! syscall open
app-1  | npm ERR! path /app/package.json
app-1  | npm ERR! errno -2
app-1  | npm ERR! enoent ENOENT: no such file or directory, open '/app/package.json'
app-1  | npm ERR! enoent This is related to npm not being able to find a file.
app-1  | npm ERR! enoent 
app-1  | 
app-1  | npm ERR! A complete log of this run can be found in: /root/.npm/_logs/2024-05-07T13_52_15_873Z-debug-0.log
app-1  | 
app-1 exited with code 254
```

エラーになった。
エラーの内容を見てみると実行しているディレクトリがダメそう。

以下はこの時点でのディレクトリの中身。
![Pasted image 20240507225710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/9ff7b5a2-f279-988d-7b9b-08801a7ec4a6.png)


srcフォルダは先ほどの `docker compose run` コマンド実行時に作成されたもの。
compose.yml の設定により./src と コンテナ上の /appが対応するので、DockerfileのWORKDIRをpackage.jsonのある /app/nextjs-tutorial に変更。

再度ビルドして起動してみる。

```bash
% docker compose up -d --build
```

```bash
[+] Building 1.6s (6/6) FINISHED                           docker:desktop-linux
 => [app internal] load build definition from Dockerfile                   0.0s
 => => transferring dockerfile: 127B                                       0.0s
 => [app internal] load metadata for docker.io/library/node:18.17-alpine   1.5s
 => [app internal] load .dockerignore                                      0.0s
 => => transferring context: 2B                                            0.0s
 => [app 1/2] FROM docker.io/library/node:18.17-alpine@sha256:3482a20c97e  0.0s
 => CACHED [app 2/2] WORKDIR /app/nextjs-tutorial                          0.0s
 => [app] exporting to image                                               0.0s
 => => exporting layers                                                    0.0s
 => => writing image sha256:af4a3be857aaaa2c31bb86035f79040864d941febbb92  0.0s
 => => naming to docker.io/library/nextjstutorial-app                      0.0s
[+] Running 1/1
 ✔ Container nextjstutorial-app-1  Sta...                                  0.1s 
```

起動成功！
localhosst:3000へアクセスして確認してみる。
![Pasted image 20240507230240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/b4b77c34-a178-a607-7492-bfb4a545040b.png)



無事にサンプルアプリが表示された。

# おわりに

Dockerfileやcompose.ymlはきっともっと良い構成があると思うが、今回はとりあえず動かせることを優先しました。
これから色々触っていきながら改良していきたいです。


## 参考サイト
- [Next.js公式チュートリアル](https://nextjs.org/learn-pages-router/basics/create-nextjs-app/setup)
- [Next.js(TypeScript) × Docker(Compose V2) 最速構築Tips.](https://qiita.com/Keichan_15/items/4fc605895fef2a33b629)
- [【Docker】仮想環境で、Nuxt.jsを立ち上げる時に起こるエラー【エラーNo2】](https://qiita.com/beanzou/items/6b851c62c8c5cd4e4c57)