Next.jsのローカル開発環境をDocker + VS Code + Remote Containersで構築

はじめに

Next.jsのローカル開発環境として、DockerとVisual Studio Code(以下 VS Code)、Remote Containers拡張機能(Dev Container)を使った構築方法を試してみました。
VS Codeでコードを書きつつ、コンテナで上のNode.js実行環境で随時アプリケーションの動作確認が行えることを目標とします。

前提条件

以下の環境で作業をしています。

  • macOS Monterey (12.3.1)
  • Visual Studio Code 1.67.2
  • Docker Desktop 4.0.1

VS Codeでは、以下の拡張機能を使用します。必須ではないですが作業の効率化ができます。
Dockerのみローカル環境にインストールし、残りはDev Container上のVS Code Serverにインストールします。

名前 識別子
Docker ms-azuretools.vscode-docker
Japanese Language Pack for Visual Studio Code ms-ceintl.vscode-language-pack-ja
ES7+ React/Redux/React-Native snippets dsznajder.es7-react-js-snippets
next.js foxundermoon.next-js
Next.js snippets pulkitgangwar.nextjs-snippets

Next.jsプロジェクト作成

作業端末のターミナルアプリを開き、任意の場所に作業ディレクトリを作成します。
作業ディレクトリをバインドマウントしたNode.jsコンテナを実行して、npx create-next-appでNext.jsプロジェクトを作業ディレクトリに作成します。
このコンテナは--rmオプションを付けて実行しているので、終了と同時に削除されます。

% mkdir sample-app
% docker run --rm -it \
  -v ${PWD}/sample-app:/app:delegated \
  -w /app \
  node:16-bullseye-slim \
  sh -c "npm install -g npm@latest && npx create-next-app@latest . --ts"

(略)
Need to install the following packages:
  create-next-app@latest
Ok to proceed? (y)        ← Enterキーを押下

(略)
Success! Created app at /app
Inside that directory, you can run several commands:

  yarn dev
    Starts the development server.

  yarn build
    Builds the app for production.

  yarn start
    Runs the built app in production mode.

We suggest that you begin by typing:

  cd /app
  yarn dev

VS CodeのUIでコンテナを扱えるようにするために、VS Code拡張機能のms-azuretools.vscode-dockerをインストールします。

% code --install-extension  ms-azuretools.vscode-docker

npmでインストールした依存ライブラリが格納される./node_modulesディレクトリはソースコードの管理対象外としたいので、ここで一旦ディレクトリごと削除します。

% rm -rf sample-app/node_modules

作業ディレクトリをVS Codeで開きます。

% code sample-app

Dockerfile作成

開発環境コンテナのイメージをビルドするために、./(作業ディレクトリ直下)に下記内容のDockerfileを作成します。

FROM node:16-bullseye-slim
# 作業ディレクトリを変更
WORKDIR /app
# 依存パッケージインストール
COPY package*.json ./
RUN npm install
# アプリケーションコード全体をコピー
COPY . .
# 3000ポートを公開
EXPOSE 3000
# コンテナ実行時に組み込みサーバを起動
CMD [ "npm", "run", "dev" ]

同じく./(作業ディレクトリ直下)に下記内容の.dockerignoreを作成します。
ローカルモジュールとデバッグログがローカル環境に存在していた場合に、ビルドするコンテナイメージにそれらが混入しないようにします。

node_modules
npm-debug.log

Docker Composeファイル作成

開発環境コンテナの実行内容をサービスとして定義するために、./(作業ディレクトリ直下)に下記内容のcompose.ymlを作成します。

services:
  app:
    container_name: sample-app
    # カレントディレクトリのDockerfileからコンテナイメージをビルドして使用
    build: .
    ports:
      # ホストの3000ポートをコンテナの3000ポートにマッピング
      - 3000:3000
    volumes:
      # node_modulesがホストのカレントディレクトリに共有されないようボリュームに切り出し
      - node_modules:/app/node_modules
      # ホストのカレントディレクトリをコンテナの/appにバインドマウントして共有
      - ./:/app:cached
volumes:
  node_modules: {}

ここまで完了したら、一旦コンテナを起動して動作確認をしてみます。
エクスプローラービューのcompose.ymlを右クリックし、Compose Upをクリックします。

以下出力例のようにコンテナが実行されます。
処理完了後、任意のキーを押すとターミナルが閉じます。

> Executing task: docker compose -f "compose.yml" up -d --build <

(略)

ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。

Dockerビューから起動中のコンテナを右クリックし、Open in Browserをクリックします。

正常にコンテナが起動している場合組み込みサーバが起動しているので、以下画面がブラウザに表示されます。

Dockerビューから起動中のコンテナを右クリックし、View Logsをクリックします。
ターミナルが開かれ、コンテナ内部のログがリアルタイムに表示されます。止める時は、Ctrl + Cを入力します。

動作確認が完了したらコンテナを停止・削除します。
エクスプローラービューのcompose.ymlを右クリックし、Compose Downをクリックします。

処理完了後、任意のキーを押すとターミナルが閉じます。

> Executing task: docker compose -f "compose.yml" down <

(略)

ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。

Dev Containerファイル作成

開発環境コンテナ内でVS Code Serverを実行して開発が行えるように、./devcontainerディレクトリを作成し、その配下に下記内容のdevcontainer.jsonを作成します。

{
    "name": "Sample App",
    // コンテナ起動に使用するDocker Composeファイル
    "dockerComposeFile": "../compose.yml",
    // Dev containerとして起動するDocker Composeサービス
    "service": "app",
    // ワークスペースディレクトリ
    "workspaceFolder": "/app",
    // インストールする拡張機能
    "extensions": [
        "ms-ceintl.vscode-language-pack-ja",
        "dsznajder.es7-react-js-snippets",
        "foxundermoon.next-js",
        "pulkitgangwar.nextjs-snippets"
    ],
    // コンテナ作成後にGitをインストール
    "postCreateCommand": "apt-get update && apt-get install -y git"
}

Dev Containerの動作を確認します。
VS Codeの画面左下、緑色のボタンをクリックします。

コマンドパレットからReopen in Containerをクリックします。

初回実行時はDev Containerのビルドが完了するまで少し時間がかかります。VS Code画面右下のshow logをクリックすると、ビルド処理のログをリアルタイムに確認できます。

しばらくすると、Dev Container上のVS Codeが起動します。VS Code画面左下は以下のように表示が変化します。

Dev ContainerからローカルのVS Codeに戻る時は、上記緑色のボタンをクリックします。
コマンドパレットからReopen Flolder Locallyをクリックします。

Gitリポジトリの初期化

Dev Container上でGitが動作するか確認します。今回はGitリポジトリを初期化して新規に作成します。
Dev Containerで作業ディレクトリを開いた状態で、ソース管理ビューからリポジトリを初期化するをクリックします。

すると、Gitによるソースコード管理が有効化されます。

GitHubなどのGitリポジトリホスティングサービスと連携する場合、リモートリポジトリを適宜追加してください。
必要に応じて、以下テンプレート集のNode.gitignoreを作業ディレクトリ直下に.gitignoreという名前で保存します。Git管理から除外するファイルを指定するためのものです。
A collection of .gitignore templates

なお、リポジトリを初期化するがクリックできない場合はGitがDev Container上で正しく認識されていません。今回の検証では一度ローカルに戻り、再度Dev Containerを開き直すことで解決できました。

参考文献

Developing inside a Container
Compose ファイル
Getting Started
Node.js Web アプリケーションを Docker 化する
Create React Appはカレントディレクトリに直接展開できる
Docker Compose の bind mounts から node_modules を除外する方法

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です