docker initでNextjs用のDockerfileを作る

## この記事の目的
- docker init コマンドを使ってNextjsを動かす
- Dockerについて多少なりとも理解を深める

## 対象者
- Docker初心者、これからdockerを学びたい人
- Nextjsに限らず、何かしらのプログラミング環境をDockerで生成したい

## 環境
win11
Node.js v20.9.0

## Docker構築

Dockerについては他の方の記事を読んでください。この記事を読むのにはPC上にLinuxの仮想環境つくる、の理解でOKです。
はじめにDocker Desktopをインストールします。
https://www.docker.com/products/docker-desktop/
また、Dockerへのサインアップも完了させておいてください。
Docker Desktopが正しくインストールできればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/728667/85345139-38e9-70ed-f6df-3f1c6cb7eea8.png)

## Dockerfileを生成するまで

流れとしては以下のようになります。
1. 現在の環境からハローワールドするまで環境動かす
1. docker initコマンドでDockerfileを生成する
1. 動くのを確認する
1. Dockerfileに問題があれば修正する

### docker initって何

現在ある環境から、それを生成するためのDockerfile[^1]を生成してくれます。
つまりは、一度WindowsやMacでNextjs等の環境構築後、docker initを実行することで現在と同じ環境を生成するためのDockerfileを生成してくれます。

[^1]:コンテナ（仮想環境）を作るためのイメージを生成するのに必要なファイル

### 現在の環境でNextjsを動かす
ここら辺はNextjsに限らず、任意のフレームワークや言語の開発環境を構築します。
Nextjsの場合は以下。
```bash
npx create-next-app@latest #Nextjsのプロジェクト生成
npm run dev #localhost:3000にアクセスできることを確認する
```
以下の画像のようにアクセスできればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/728667/ada6d243-bcec-a131-a124-1570bd82f666.png)

### docker initする

```bash
docker init 

#Nextjsの場合はNodeを選択
? What application platform does your project use?  [Use arrows to move, type to filter]
  Go - suitable for a Go server application
  Python - suitable for a Python server application
> Node - suitable for a Node server application
  Rust - suitable for a Rust server application
  ASP.NET Core - suitable for an ASP.NET Core application
  Other - general purpose starting point for containerizing your application
  Don't see something you need? Let us know!
  Quit

#現在のホスト（Windowsなど）にインストールされているNodeのバージョンがデフォルトで選ばれる
#そのままenterでよい
? What version of Node do you want to use? (20.9.0)

#使っているパッケージツールを選択
? Which package manager do you want to use?  [Use arrows to move, type to filter]
> npm - (detected)
  yarn
  pnpm

#アプリを起動するときのコマンド
#今回はnpm run devを入力
? What command do you want to use to start the app? [tab for suggestions]

#ポート選択
#今回は3000を入力
? What port does your server listen on?
```
以上でDockerfileが生成されます。

## 動くのを確認する

Dockerfileが生成されたら、イメージを作ってコンテナを走らせます
```bash
docker image build -t イメージ名:タグ名 .
docker run -it -p 3000:3000 -v ${PWD}:/usr/src/app -v /usr/src/app/node_modules イメージ名
```
上記コマンドを打つことで、docker runをしたときに仮想環境内でnpm run dev（docker initで選択したコマンド）が走りlocalhost:3000にアクセスできるようになります。
-pオプションで仮想環境内のポート3000にアクセスできるようになり、ホストからコンテナ内にアクセスできます。
また、-vコマンドで現在のディレクトリをコンテナの/usr/src/appディレクトリにマウントします。

詳細なコマンドの意味はgithub copilotなどに聞いてください。

私が生成したDockerfileは以下です。何かの参考にでも。
https://github.com/orukRed/orukRed.github.io/blob/nextjs/Dockerfile

## Dockerfileに問題があれば修正する
私の環境だと以下のエラーが発生しました。

```

 ⚠ You are using a non-standard "NODE_ENV" value in your environment. This creates inconsistencies in the project and is strongly advised against. Read more: https://nextjs.org/docs/messages/non-standard-node-env
   ▲ Next.js 14.0.1
   - Local:        http://localhost:3000

It looks like you're trying to use TypeScript but do not have the required package(s) installed.
Installing dependencies

If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).


Installing devDependencies (npm):
- typescript
- @types/react
- @types/node

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/src/app/node_modules/@aashutoshrathi/word-wrap
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/src/app/node_modules/@aashutoshrathi/word-wrap'
npm ERR!  [Error: EACCES: permission denied, mkdir '/usr/src/app/node_modules/@aashutoshrathi/word-wrap'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/usr/src/app/node_modules/@aashutoshrathi/word-wrap'
npm ERR! }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in: /home/node/.npm/_logs/2023-11-08T14_07_58_690Z-debug-0.log
Failed to install required TypeScript dependencies, please install them manually to continue:
npm install --save-exact --save-dev typescript @types/react @types/node

{
  command: 'npm install --save-exact --save-dev typescript @types/react @types/node'
}
```
Nextjsでtypescritp使ってるからそれかな？と思ったのですが、どうやら原因はDockerfileの以下でした。
```dockerfile
ENV NODE_ENV production
```
上記をコメントアウトすることで動きました。
```
# ENV NODE_ENV production
```
未確認で申し訳ないのですが、`ENV NODE_ENV=production`にすると動くんですかね……？

## 参考文献
https://nextjs-ja-translation-docs.vercel.app/docs/getting-started
https://architecting.hateblo.jp/entry/2020/08/13/153842
https://www.wakuwakubank.com/posts/270-docker-build-image/#index_id14
https://zenn.dev/fujiyama/articles/a9a67cd3feba83