当サイトは、アフィリエイト広告を利用しています

【Docker × Next.js】VSCodeでNext.jsのコンテナ開発~docker-compose~

作成日:2023月12月15日
更新日:2024年02月10日

ReactのNext.jsの開発環境をDockerを使って構築し
VSCodeからコンテナ開発を行う方法をまとめる

VSCodeとDockerを使ったNext.jsの開発環境構築時の
Dockerコンテナの作成は

  • docker-composeを使ってコンテナ作成
  • VSCodeの拡張機能Dev Containersを使ってコンテナ作成

の2パターンでできた。
※コンテナ作成方法の違いなので、コンテナ開発自体は
VSCodeから行える。

また開発環境内のNext.jsのプロジェクトを
dockerのどこで永続化するかについても

  • バインドマウント
  • 名前付きボリュームを使う

の2パターンがある
どちらのパターンでもコンテナを削除しても
プロジェクトは消えないようにしている。
※コンテナ削除で消えると洒落にならないので。。。

dockerのvolumes設定方法のバインドマウントや名前付きボリュームで保存
については下記記事でまとめていますので
よければご参照ください

つまり組み合わせで下記のパターンの構築方法がある。

  • docker-cmmposeでコンテナ構築 + プロジェクトをバインドマウント
  • docker-cmmposeでコンテナ構築 + プロジェクトを名前付きボリュームで保存
  • Dev Containersでコンテナ構築 + プロジェクトをバインドマウント
  • Dev Containersでコンテナ構築 + プロジェクトを名前付きボリュームで保存

それぞれの方法をまとめる

Reatプロジェクトをコンテナ開発する場合については下記記事でまとめています

環境

下記の環境で行う

  • Windows10
  • Docker version 24.0.2(Docker for Windows)
  • VScode
  • Remote Development(VScodeの拡張機能)

Docker for Windowsのインストール方法については下記記事で 紹介しています

またVSCodeの拡張機能であるDevcontainerの
使い方については下記記事で紹介しています

docker-composeでコンテナ構築する意味

VSCodeのdevcontainerを使わずにdocker-composeを使って
コンテナ構築する場合に下記のような利点があると思う

メリット

コンテナ内でインストールは完結する

コンテナ内でNext.jsのプロジェクトの作成やパッケージの
インストールをするので、ローカル環境は汚れない。

VSCodeのdevcontainerの知識は不要

コンテナ作成自体はdocker-composeで行うので
VSCodeのdevcontainerに関する
知識は必要ない

要はコンテナ構築はdockerでして
開発はVScode上からコンテナにアクセスして行うイメージ。

デメリット

拡張機能がインストールされない

docker composeコマンドで作成したコンテナには
VScodeの拡張機能が日本語化ぐらいしかはいっていない。

そのため、コンテナ作成後、VScodeからアタッチして
コンテナ内でインストールする必要がある。

使用する拡張機能が少なければいいが、多いときはしんどい。

下記の記事で一括でインストールする方法を紹介してます。

「docker-composeでコンテナ構築 + プロジェクトをバインドマウント」で開発環境構築する

バインドマウントでプロジェクトを保持させる場合は

  • コンテナを作る
  • コンテナに入る
  • コンテナ内でnext.jsプロジェクトを作る

の手順になる。

バインドマウントを使っているため、コンテナ内でプロジェクトを
作成すれば、ホスト側にも反映される。

全体構造のイメージとしては下記のようになる 2023-12-17-16-42-05

  • hostのプロジェクトとコンテナのworkspaceはバインドマウントで紐づける
  • Next.jsプロジェクトはgitで管理する

構成

下記のような構成にする

構成
.
`-- docker
|-- .env
|-- Dockerfile
`-- docker-compose.yml

dockerフォルダにコンテナ構築関連のファイルを
固める。

コンテナを構築設定

Next.jsプロジェクトを動作させる コンテナの設定を行う

.env

環境変数を保持させるためのファイル
今回はプロジェクト名を保持させる

.env
# .envファイル
PROJECT_NAME=sample-project

任意の値に変更すれば、その名称でNext.jsの
プロジェクトを作成できる

Dockerfile

コンテナのimageを作るためのDockerfileを作成する

dockerfile
# イメージ
FROM node:21-alpine
# パッケージ最新化とインストール
RUN apk update && apk add git curl
# workspaceディレクトリ作成
WORKDIR /workspace
  • nodeのバージョン21のイメージを使用
  • パッケージの最新化とgitとcurlをインストール
  • workspaceを作成

docker-compose.yml

コンテナはdocker-composeを使って作成する

docker-compose.yml
version: "3"
services:
next:
container_name: "next"
# Dockerfileをビルド
build:
context: .
dockerfile: Dockerfile
volumes:
# バインドマウント
- ../:/workspace
tty: true
env_file:
- .env
  • env_fileで.envの環境変数を読み込む
  • コンテナのworkspaceとホストのdockerディレクトリの親フォルダを
    バインドマウントする

これでコンテナのworkspaceでNext.jsのプロジェクトを
作成すると、ホストのdockerディレクトリと同じ階層にも
作成される

コンテナ構築

docker-composeでコンテナを構築する

docker-compose実行

dockerディレクトリに移動して docker-composeを実行する

docker-compose実行
$ cd docker/
$ docker compose up -d

コンテナが無事作成されたらVScodeからコンテナに入る
F1で実行中のコンテナにアタッチするを選択する 2023-12-15-22-13-02

すると
コンテナが出てくるので選択する 2023-12-15-22-14-07

コンテナに入れた 2023-12-15-22-16-15

Next.jsのプロジェクトを作る

コンテナ内でNext.jsのプロジェクトを
作成する

bash
npx create-next-app@latest $PROJECT_NAME \
--typescript --eslint --app --src-dir \
--import-alias --use-yarn --no-tailwind

PROJECT_NAMEには.envファイルで設定した
値が入る

コンテナ側でプロジェクト作成完了

コンテナ側でNext.jsのプロジェクトができた 2023-12-15-22-21-02

ホスト側にも作成されている

バインドマウントされているのでホスト側にも
プロジェクトがあることを確認する 2023-12-15-22-24-21

アプリケーション起動

コンテナでプロジェクトディレクトリに移動して
「yarn dev」でNext.jsのプロジェクトを起動する 2023-12-15-22-28-10 ちゃんと起動できる

コンテナ削除しても大丈夫なのか?~その1~

コンテナを削除しても、ホスト側にはプロジェクトが残っているので
コンテナを再作成したときに、ホストからコンテナにコピーされるので
問題ない。

「docker-composeでコンテナ構築 + プロジェクトを名前付きボリュームで保存」で開発環境構築する

コンテナ構築をdocker-cmmposeを使って構築し(VSCodeのDevcontainerは使わない)
プロジェクトを含むworkspaceを名前付きボリュームで永続化させる

名前付きボリュームでプロジェクトを永続化させる場合は

  • コンテナを作る && Next.jsプロジェクトを作る

の一つの手順でできる

バインドマウントと違い、ホスト側にプロジェクトはなく
コンテナ内だけにある状態になる。

注意としては、コンテナを削除してもボリュームがある限り
プロジェクトは消えないが、ボリュームを削除すると消える。

全体構造のイメージとしては下記のようになる 2023-12-17-16-49-50

  • docker関連ファイルに関してはホストからコンテナにバインドマウントする
  • コンテナ内のworkspaceごと名前付きボリュームで永続化する
  • コンテナ内のworkspace内のNext.jsプロジェクトはgitで管理する

こうすることで
Next.jsの開発をコンテナで実施でき、管理もgitでできるようになる。

構成

下記のような構成にする

構成
.
`-- docker
|-- .env
|-- Dockerfile
`-- docker-compose.yml

dockerフォルダにコンテナ構築関連のファイルを
固める。

コンテナを構築設定

コンテナ構築と同時にコンテナ内に
Next.jsのプロジェクトを作成するための設定を行う。

.env

環境変数を保持させるためのファイル
今回はプロジェクト名を保持させる

.env
# .envファイル
PROJECT_NAME=sample-project

任意の値に変更すれば、その名称でNext.jsの
プロジェクトが作成される

Dockerfile

コンテナのimageを作るためのDockerfileを作成する

dockerfile
# イメージ
FROM node:21-alpine
# パッケージ最新化とインストール
RUN apk update && apk add git curl
# docker-composeからの引数を受け取る
ARG PROJECT_NAME
# コンテナにフォルダ作成
RUN mkdir -p /workspace/docker
# workspaceディレクトリに移動
WORKDIR /workspace
# next.jsプロジェクト生成
RUN npx create-next-app@latest ${PROJECT_NAME} \
--typescript --eslint --app --src-dir \
--import-alias --use-yarn --no-tailwind
# next.jsプロジェクトに移動
WORKDIR /workspace/${PROJECT_NAME}
# next.jsプロジェクト内にdocker関連ファイルをコピー
RUN mkdir -p /workspace/${PROJECT_NAME}/docker
COPY ./ /workspace/${PROJECT_NAME}/docker
# git初期化
RUN git init
  • nodeのバージョン21のイメージを使用
  • ARGでdocker-composeから引数(プロジェクト名)を変数に設定する
  • Next.jsのプロジェクトをnpxで非対話で実行する

このNext.jsのプロジェクト作成を非対話で行う場合
オプションを全て列挙し、要不要を書いている必要がある

tailwindを例にあげると

  • 要の場合は「--tailwind」
  • 不要の場合は「--no-tailwind」

となる。

失敗するとプロジェクトが生成されない
現在、2023年12月15日ではcreate-next-appの最新versionは「14.0.4」だが
今後、versionが上がり、オプションが追加された場合は、上記では動かない可能性
がでてくるので注意。
※追加されたオプションを追記すれば動く想定

next.jsプロジェクト内にdocker関連ファイルをコピーしているのは
docker関連ファイルをgithub等のリモートリポジトリに
退避させるため。

docker-compose.yml

コンテナはdocker-composeを使って作成する

docker-compose.yml
version: "3"
services:
next:
container_name: "next"
# Dockerfileをビルド
build:
context: .
dockerfile: Dockerfile
# docekrfileに引数を渡す
args:
PROJECT_NAME: ${PROJECT_NAME}
volumes:
# バインドマウント
- ./:/workspace/docker
# 名前付きボリューム
- next-volume:/workspace
# 環境変数読み込み
env_file:
- .env
tty: true
# 名前付きボリューム
volumes:
next-volume:
  • env_fileで.envの環境変数を読み込む
  • argsで.envの環境変数をdockerfileに渡す
  • 開発中にコンテナの変更ができるようにdockerディレクトリはバインドマウントさせる
  • volumeでプロジェクトを含むworkspaceを名前付きボリュームで永続化している

コンテナ構築

docker-composeでコンテナを構築する

docker-compose実行

dockerディレクトリに移動して docker-composeを実行する

docker-compose実行
$ cd docker/
$ docker compose up -d

コンテナが無事作成されたらVScodeからコンテナに入る
Remote Developmentを入れていれば
リモートエクスプローラータブで「開発コンテナ」を
選択すればコンテナが表示される
※F1で「実行中のコンテナにアタッチ」でもできる
2023-12-15-18-32-42

「新しいウィンドウでアタッチする」を選択すると
コンテナに入り、操作することができる 2023-12-18-00-46-21 コンテナ内にプロジェクトが作成されていることが
確認できる

Next.jsプロジェクトをgitのリモートリポジトリにpushしておく

コンテナ構築後、Next.jsのプロジェクトをgithubやgitlabのリモートリポジトリに
pushしておく。

そうしておけば、もし誤ってコンテナだけでなく、名前付きボリュームを削除してしまったとしても
コンテナのworkspace配下にリモートリポジトリからNext.jsプロジェクトをcloneすれば
復元できる。

Next.jsのアプリケーションを起動する

念のためちゃんとアプリケーションが起動できることを
確認しておく

アプリケーション起動

プロジェクトディレクトリに移動して
「yarn dev」でNext.jsのプロジェクトを起動する 2023-12-15-18-39-47 ちゃんと起動できる

コンテナ削除しても大丈夫なのか?~その2~

さらに念のためコンテナを削除しても、名前付きボリュームで
永続化させているプロジェクトは無事なのかを確認する。

プロジェクトにフォルダを作っておく

適当にプロジェクト内にフォルダを作る 2023-12-18-00-48-09 もしコンテナ削除時にプロジェクトも一緒に
削除されるのであれば、作成したフォルダはなくなるはず!

起動中のコンテナ確認

起動中のコンテナ確認
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09bcf617aefa docker-next "docker-entrypoint.s…" 15 minutes ago Up 15 minutes next

作成したコンテナが起動中になっている

コンテナを停止

コンテナ停止
$ docker stop next
next
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09bcf617aefa docker-next "docker-entrypoint.s…" 15 minutes ago Exited (137) 9 seconds ago next

コンテナが停止されている

コンテナを削除

コンテナ削除
$ docker rm next
next
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

コンテナが削除されている

イメージを削除

イメージも消しておく

イメージ削除
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-next latest 6c292f31600f 17 minutes ago 808MB
$ docker rmi docker-next
Untagged: docker-next:latest
Deleted: sha256:6c292f31600f86324f5a84f6cbb3ba045128729f7226a1d9ceb2ce12b041b3c7
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE

イメージが削除されている

ボリューム確認

ボリュームが残っていることを確認する

ボリューム確認
$ docker volume ls
DRIVER VOLUME NAME
local docker_next-volume

ボリュームの生存を確認

再度、コンテナする

コンテナ再作成
$ docker compose up -d

プロジェクトを再確認する

同様の手順でコンテナに入り
確認すると 2023-12-18-00-48-09 フォルダは存在しているので
プロジェクトが永続化できていることがわかる。

名前付きボリュームがあり、中にデータがある場合は
名前付きボリュームとコンテナでは
名前付きボリュームの方が同期元になり、コンテナに同期されるため
プロジェクトは消えない。 ※コンテナの中身は名前付きボリュームの値で上書きされるという意味

詳しくは下記記事でまとめています

git initして大丈夫なのか?

名前付きボリュームがある状態でコンテナ作成した時
dockerfileの最後で、「git init」しているが
gitは初期化されないかについてだが、初期化されない。
※.gitフォルダがある場合は、「git init」してもエラーになるだけなので

Devcontainerでコンテナ構築する

VSCodeのdevcontainerを使って
コンテナ構築する場合に下記のような利点があると思う

メリット

コンテナの細かい設定ができる

devcontainer.jsonに設定を書いて
細かい設定ができる

VSCodeの拡張機能であるDevcontainerの
使い方については下記記事で紹介しています

特にコンテナ作成と同時に拡張機能をインストールできるのは便利。

devcontainer.jsonの設定は使えない場合がある

devcontainer.jsonに書いた内容はVScodeから
コンテナ作成を行った場合にしか、適用されない。

つまり、ターミナル等でdocker-composeでコンテナ作成した場合は
適用されないので注意が必要。

「Dev Containersでコンテナ構築 + プロジェクトをバインドマウント」で開発環境構築する

「docker-composeでコンテナ構築 + プロジェクトをバインドマウント」に
VScodeからコンテナ作成するための設定ファイルである

  • .devcontainer/devcontainer.json

を追加するだけ

構成

追加すると構成は下記のようになる

構成
.
|-- .devcontainer
| `-- devcontainer.json
`-- docker
|-- .env
|-- Dockerfile
`-- docker-compose.yml

.devcontainer/devcontainer.json

devcontainer.jsonは下記のような感じ

js
{
// コンテナ名(vscode上の)
"name": "Next.js",
// コンテナ作成に使うdocker-comopseファイルの相対パス
"dockerComposeFile": "../docker/docker-compose.yml",
// サービス名
"service": "next",
// コンテナ内のプロジェクトのルートフォルダを指定
"workspaceFolder": "/workspace",
// コンテナ停止時のアクション
"shutdownAction": "stopCompose",
"customizations": {
"vscode": {
"extensions": [
"mhutchie.git-graph",
"AvneeshAgarwal.react-nextjs-snippets"
]
}
}
}

extensionsで拡張機能を指定しておけば
コンテナ作成時に自動で入れてくれる。

VSCodeからコンテナ作成

コンテナ作成はdocker-composeコマンドではなくVScodeから
行う

F1でコンテナで再度開く

2023-12-21-21-40-41

拡張機能もインストールされる

2023-12-21-21-42-34

「Dev Containersでコンテナ構築 + プロジェクトを名前付きボリュームで保存」で開発環境構築する

「Dev Containersでコンテナ構築 + プロジェクトを名前付きボリュームで保存」でも
同様に VScodeからコンテナ作成するための設定ファイルである

  • .devcontainer/devcontainer.json

を追加する

構成

構成も同様。

構成
.
|-- .devcontainer
| `-- devcontainer.json
`-- docker
|-- .env
|-- Dockerfile
`-- docker-compose.yml

.devcontainer/devcontainer.json

devcontainer.jsonも同様にする

js
{
// コンテナ名(vscode上の)
"name": "Next.js",
// コンテナ作成に使うdocker-comopseファイルの相対パス
"dockerComposeFile": "../docker/docker-compose.yml",
// サービス名
"service": "next",
// コンテナ内のプロジェクトのルートフォルダを指定
"workspaceFolder": "/workspace",
// コンテナ停止時のアクション
"shutdownAction": "stopCompose",
"customizations": {
"vscode": {
"extensions": [
"mhutchie.git-graph",
"AvneeshAgarwal.react-nextjs-snippets"
]
}
}
}

docker-compose.yml

docker-compose.ymlに少し追記する

docker-compose.yml
version: "3"
services:
next:
container_name: "next"
# Dockerfileをビルド
build:
context: .
dockerfile: Dockerfile
# docekrfileに引数を渡す
args:
PROJECT_NAME: ${PROJECT_NAME}
volumes:
# バインドマウント
- ./:/workspace/docker
- ../.devcontainer:/workspace/.devcontainer
# 名前付きボリューム
- next-volume:/workspace
# 環境変数読み込み
env_file:
- .env
tty: true
# 名前付きボリューム
volumes:
next-volume:

コンテナ内からdevcontainer.jsonを
参照できるように、バインドマウントに追加する

dockerfile

dockerfileにも少し追記する

dockerfile
# イメージ
FROM node:21-alpine
# パッケージ最新化とインストール
RUN apk update && apk add git curl
# docker-composeからの引数を受け取る
ARG PROJECT_NAME
# コンテナにフォルダ作成
RUN mkdir -p /workspace/docker
RUN mkdir -p /workspace/.devcontainer
# workspaceディレクトリに移動
WORKDIR /workspace
# next.jsプロジェクト生成
RUN npx create-next-app@latest ${PROJECT_NAME} \
--typescript --eslint --app --src-dir \
--import-alias --use-yarn --no-tailwind
# next.jsプロジェクトに移動
WORKDIR /workspace/${PROJECT_NAME}
# next.jsプロジェクト内にdocker関連ファイルをコピー
RUN mkdir -p /workspace/${PROJECT_NAME}/docker
COPY ./ /workspace/${PROJECT_NAME}/docker
# next.jsプロジェクト内に.devcontainerをコピー
RUN mkdir -p /workspace/${PROJECT_NAME}/.devcontainer
COPY ./ /workspace/${PROJECT_NAME}/.devcontainer
# git初期化
RUN git init

.devcontainerをgitで管理するため
nextjsプロジェクト内に作成しておく。

VSCodeからコンテナ作成

こちらもVScodeからコンテナ作成を行う

F1でコンテナで再度開く

2023-12-21-21-54-18

拡張機能がインストールされる

2023-12-21-21-53-04

next.jsプロジェクト確認

コピーした

  • docker
  • .devcontainer

ディレクトリがあることを確認する 2023-12-21-21-53-33

まとめ

Next.jsをコンテナ開発する方法をまとめてみた。
バインドマウントを使用する方が直観的にわかりやすく
リスクも少ないから良いかなとおもっていたが
思いの他、動作が遅くなるので、名前付きボリュームの方を
使うようにしようと思う。

後、docker-composeでコンテナを作るのは楽だが
VScodeの拡張機能を初期インストールできないのがけっこうめんどいと
感じた。

個人的には

  • コンテナはVScodeのDevContainerで作る
  • 永続化は名前付きボリューム

の組み合わせが良さそうだと感じている。

今後、開発を進める上で判断したい。

参考

新着記事

目次
タグ別一覧
top