Docker
Docker でデプロイするには、ビルトインの docker アダプタを使用します。このアダプタは、適切なシグナルハンドリング、静的ファイル配信、最小限の Alpine ベースイメージを備えた、プロダクション対応の Docker イメージを作成します。
マシンに Docker がインストールされている必要があります。
docker --version
追加のパッケージは不要です — アダプタは @lazarv/react-server に組み込まれています。
react-server.config.mjs ファイルにアダプタを追加します:
export default {
adapter: "docker",
};
オプションを渡してアダプタをカスタマイズできます:
export default {
adapter: [
"docker",
{
runtime: "node", // ランタイム: "node"(デフォルト)、"bun"、または "deno"
name: "my-app", // アプリケーション名(デフォルト: package.json から取得)
tag: "my-app:v1.0", // Docker イメージタグ(デフォルト: "<name>:latest")
port: 8080, // 公開ポート(デフォルト: 3000)
version: "22-alpine", // ベースイメージタグ(デフォルトはランタイムにより異なる)
},
],
};
設定オプション
runtime: Docker コンテナ内で使用するランタイム。"node"(デフォルト)、"bun"、または"deno"。Node.js は依存関係トレース付きの@lazarv/react-server/nodeを使用します。Bun と Deno は単一ファイルにバンドルされるエッジビルドを使用します。name: Docker イメージに使用されるアプリケーション名。package.jsonの name(スコープなし)または"react-server-app"にフォールバックします。tag: ビルド時に使用される Docker イメージタグ。デフォルトは"<name>:latest"です。port: コンテナ内でサーバがリッスンするポート。デフォルトは3000です。version: Docker ベースイメージタグ。Node.js のデフォルトは"20-alpine"、Bun と Deno のデフォルトは"alpine"です。
アプリケーションのビルドと Docker イメージの作成を一度に実行できます:
pnpm react-server build [root] --deploy
これにより以下が行われます:
- アプリケーションのビルド(Bun/Deno の場合はエッジビルド、Node.js の場合は標準ビルド)
- サーバ出力と静的アセットのコピー、
@vercel/nftによる依存関係トレース(Node.js のみ) .docker/出力ディレクトリにDockerfile、.dockerignore、package.jsonを生成- Docker イメージのビルド
ビルドとデプロイを個別に実行することもできます:
# アプリケーションのビルド
pnpm react-server build [root]
# Docker イメージを手動でビルド
docker build -t my-app:latest .docker
コンテナを実行します:
docker run -p 3000:3000 my-app:latest
生成された Dockerfile には以下の環境変数が設定されています:
NODE_ENV=production— React がプロダクションバンドルを使用することを保証しますPORT— サーバがリッスンするポート(デフォルト:3000)
実行時に追加の環境変数を渡すことができます:
docker run -p 3000:3000 -e MY_API_KEY=secret my-app:latest
ポートを上書きすることもできます:
docker run -p 8080:8080 -e PORT=8080 my-app:latest
--sourcemap でビルドした場合、Dockerfile に NODE_OPTIONS="--enable-source-maps" も設定されます。
アダプタの動作:
- Node.js ランタイム: 静的ファイルを配信し、SSR は
@lazarv/react-server/nodeに委譲するカスタム HTTP サーバエントリをコピーし、@vercel/nftを使用して必要なnode_modules依存関係をトレース - Bun/Deno ランタイム: すべてを単一ファイルにバンドルするエッジビルドを実行し、インライン化された静的ルートを含むスタートスクリプトを生成
- 静的アセット(JS、CSS、画像)とサーバビルド出力(RSC ペイロード、サーバコンポーネント)をコピー
- 適切なベースイメージ(
node、oven/bun、またはdenoland/deno)を使用したシングルステージ Dockerfile を生成 - Node.js の場合: 適切なシグナルハンドリングのために tini を init プロセスとして使用
- セキュリティのために非 root ユーザとして実行(Node.js と Bun)
出力構造
Node.js ランタイム:
.docker/
├── Dockerfile
├── .dockerignore
├── package.json
├── server/
│ ├── index.mjs # サーバエントリポイント
│ ├── .react-server/ # ビルド出力(RSC、サーバコンポーネント)
│ └── node_modules/ # トレースされた依存関係のみ
└── static/ # 静的アセット(JS、CSS、画像)
Bun/Deno ランタイム:
.docker/
├── Dockerfile
├── .dockerignore
├── package.json
├── start.mjs # インライン静的ルート付き生成スタートスクリプト
├── server/
│ └── .react-server/ # ビルド出力(エッジバンドル)
└── static/ # 静的アセット(JS、CSS、画像)
生成された .docker/ ディレクトリを Docker Compose で使用できます:
services:
app:
build:
context: .docker
ports:
- "3000:3000"
environment:
- NODE_ENV=production
ランタイムでモジュールが見つからない(Node.js のみ)
Node.js ランタイムは @vercel/nft を使用して依存関係をトレースします。モジュールが動的に読み込まれる場合(例: createRequire() 経由)、検出されない可能性があります。コンテナログで MODULE_NOT_FOUND エラーを確認し、必要なパッケージが package.json の dependencies に記載されていることを確認してください。Bun/Deno ランタイムは単一バンドルファイルを使用するため、この問題は発生しません。
Ctrl+C でコンテナが停止しない(Node.js のみ)
Node.js の Dockerfile は tini を init プロセスとして使用しています。docker run を -it なしで実行すると、シグナルが転送されない場合があります。以下を使用してください:
docker run -it -p 3000:3000 my-app:latest
ポートの競合
ポート 3000 が既に使用中の場合、別のホストポートにマッピングします:
docker run -p 8080:3000 my-app:latest