diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..fb5e3ae --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,42 @@ +{ + "name": "Pixel Paint War Dev", + "dockerComposeFile": "../docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspace", + + // コンテナ作成時に実行する機能 (Features) + // pnpmがイメージに含まれていない場合の保険として追加推奨ですが、 + // typescript-node:20 イメージには通常含まれています。念のため明示。 + "features": { + "ghcr.io/devcontainers/features/node:1": { + "version": "20", + "pnpm": "latest" + } + }, + + // VS Code 拡張機能の自動インストール + // 環境定義書の推奨リストを反映 + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "EditorConfig.EditorConfig", + "ms-vscode.hexeditor", + "GitHub.copilot" + ], + "settings": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" + } + } + }, + + // コンテナ起動後の初期化コマンド + // 1. 依存関係のインストール (frozen-lockfileなしで柔軟に) + // 2. 共通パッケージ(shared)のビルド + "postCreateCommand": "pnpm install && pnpm --filter @repo/shared build", + + // コンテナ内のユーザー + "remoteUser": "node" +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b0d6233 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,54 @@ +# ================================================================ +# Stage 1: Builder (ビルド用の環境) +# ================================================================ +FROM node:20-slim AS builder + +# pnpmの準備 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +WORKDIR /app + +# 1. 依存関係の定義ファイルをコピー +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ +COPY apps/server/package.json ./apps/server/ +COPY packages/shared/package.json ./packages/shared/ + +# 2. 依存関係をインストール +RUN pnpm install --frozen-lockfile + +# 3. ソースコードをコピー +COPY packages/shared ./packages/shared +COPY apps/server ./apps/server + +# 4. ビルド(共通ライブラリ -> サーバーの順) +RUN pnpm --filter @repo/shared build +RUN pnpm --filter server build + +# 5. 開発用ライブラリを削除(本番に必要なものだけ残す) +# ENV CI=true +# RUN pnpm prune --prod + +# ================================================================ +# Stage 2: Runner (実行専用の軽量環境) +# ================================================================ +FROM node:20-slim AS runner + +WORKDIR /app + +# Builderステージから、動かすのに必要なファイルだけをコピー +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/apps/server/node_modules ./apps/server/node_modules +COPY --from=builder /app/apps/server/dist ./apps/server/dist +COPY --from=builder /app/apps/server/package.json ./apps/server/ +COPY --from=builder /app/packages/shared/dist ./packages/shared/dist +COPY --from=builder /app/packages/shared/package.json ./packages/shared/ + +# 実行環境の設定 +ENV NODE_ENV=production +USER node + +# サーバーを起動 +WORKDIR /app/apps/server +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/apps/client/vite.config.ts b/apps/client/vite.config.ts index b5663a6..2591ed7 100644 --- a/apps/client/vite.config.ts +++ b/apps/client/vite.config.ts @@ -5,6 +5,10 @@ export default defineConfig({ plugins: [preact()], server: { - host: true + host: true, // 0.0.0.0 でリッスンして外部アクセスを許可 + port: 5173, // ポート固定 + watch: { + usePolling: true // WSL2/Docker間のファイル変更検知を確実にする + } } }) diff --git a/apps/server/package.json b/apps/server/package.json index 5aec1eb..be42c55 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -2,9 +2,11 @@ "name": "server", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "dist/index.js", "scripts": { "dev": "tsx watch src/index.ts", + "build": "tsc", + "start": "node dist/index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 92df8af..7d8c7af 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1 +1,22 @@ -console.log("Server is running!"); \ No newline at end of file +import { WebSocketServer } from "ws"; + +// サーバーをポート3000で起動(これで常駐モードになります) +const wss = new WebSocketServer({ port: 3000 }); + +console.log("Pixel Paint War Server started on port 3000"); + +// クライアントからの接続を待ち受けるイベント +wss.on("connection", (ws) => { + console.log("New client connected!"); + + ws.on("message", (message) => { + console.log("Received:", message); + ws.send(`Server received: ${message}`); + }); + + ws.on("close", () => { + console.log("Client disconnected"); + }); + + ws.send("Welcome to Pixel Paint War Server!"); +}); diff --git a/apps/server/tsconfig.json b/apps/server/tsconfig.json index 5f884bd..1ed84b5 100644 --- a/apps/server/tsconfig.json +++ b/apps/server/tsconfig.json @@ -5,15 +5,14 @@ "moduleResolution": "NodeNext", "lib": ["ES2022"], "strict": true, - "noEmit": true, + "outDir": "./dist", + "rootDir": "./src", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", - "paths": { - "@repo/shared": ["../../packages/shared/src/index.ts"] - } + "baseUrl": "." + /* "paths" は削除します(pnpm のワークスペース解決を使用するため) */ }, "include": ["src/**/*"], - "exclude": ["node_modules"] -} \ No newline at end of file + "exclude": ["node_modules", "dist"] +} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..923905c --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,11 @@ +services: + game-server: + build: + context: . + dockerfile: Dockerfile + container_name: pixel-paint-server-prod + restart: unless-stopped + ports: + - "3001:3000" + environment: + - NODE_ENV=production diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..77b6cba --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + app: + container_name: pixel-paint-war-dev + # 開発用イメージ: Node.js v20 (定義書準拠) + image: mcr.microsoft.com/devcontainers/typescript-node:20 + + # 永続化とボリュームマウント + volumes: + # カレントディレクトリをコンテナ内の /workspace にマウント + - .:/workspace:cached + + # コマンドの上書き (コンテナを常時起動させる) + command: sleep infinity + + # ネットワーク設定 + # Client(5173) と Server(3000) のポートを開放 + ports: + - "5173:5173" + - "3000:3000" + + # 環境変数 + environment: + - NODE_ENV=development + # pnpmのストアをローカルと分離して高速化したい場合は設定推奨(今回はシンプルにします) + + # ユーザー権限 (Nodeイメージ推奨のユーザー) + user: node \ No newline at end of file diff --git "a/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" "b/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" index ea61c96..ee0305c 100644 --- "a/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" +++ "b/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" @@ -32,6 +32,9 @@ 2-1. 構成一覧 root/ + ├── .devcontainer/ # Dev Containers設定 + ├── docker-compose.yml # 開発用コンテナ構成定義 + ├── Dockerfile # 本番サーバー・デプロイ用定義 (Multi-stage) ├── package.json # pnpm workspace 定義 ├── pnpm-workspace.yaml # ワークスペース設定 ├── .npmrc # 依存関係解決の設定 @@ -83,8 +86,8 @@ ・Package Manager: pnpm ・Build Tool: tsup (高速で軽量なTypeScriptバンドラ) ・Serialization: Custom Binary (Standard DataView API) - - 採用理由: ライブラリ依存をなくし、仕様書要件(30KB/s以下)を満たす最適化を行うため。 - - 用途: 座標データ、入力情報の圧縮通信。 + - 採用理由: ライブラリ依存をなくし,仕様書要件(30KB/s以下)を満たす最適化を行うため. + - 用途: 座標データ,入力情報の圧縮通信. 3-2. フロントエンド (Client) ・Build Tool: Vite @@ -109,28 +112,59 @@ ・Test: Vitest (共通ロジックの単体テスト用) ・AI Assistant: GitHub Copilot Pro, Gemini Pro +3-5. インフラ・コンテナ技術 (Infrastructure) + ・Containerization: Docker + - 採用理由: 開発環境(Dev Containers)と本番環境の差異を排除するため. + ・Orchestration: + - Dev: Docker Compose (ボリュームマウントによるホットリロード) + - Prod: Docker Compose (再起動ポリシーとポート開放のみの最小構成) + ・Deployment Image: Multi-stage Build (Node.js Slim) + - ビルド戦略: + 1. Builderステージ: 全依存をインストールし,TypeScript (Shared -> Server) をコンパイル. + 2. Prune: `pnpm prune --prod` により開発依存を削除. + 3. Copy: pnpmの仕様(シンボリックリンク)に対応するため,`node_modules` を明示的にコピーする. + 4. Runnerステージ: 必要な `dist` と `node_modules` のみをコピーし,イメージサイズを最小化する. + 4. 開発マシンの前提条件 (Prerequisites) ------------------------------------------------------------------------ -以下のツールがインストールされていること. +本プロジェクトは Docker (Dev Containers) による開発環境統一を推奨する. +これにより、ホストOS(Windows/Mac)の環境を汚さずに構築が可能となる。 - 1. Node.js (v20.x LTS) - $ node -v +4-1. 【必須】ホストマシンにインストールするもの + 以下のツールのみ,開発者のPC(ホストOS)にインストールが必要である. - 2. pnpm (Corepack enabled or standalone install) - $ pnpm -v + 1. Docker実行環境 + - Docker Desktop (最新版) + - WSL2 (Windowsの場合必須) - 3. VS Code (推奨エディタ) - 以下の拡張機能を導入推奨: + 2. エディタ + - VS Code (Visual Studio Code) + + 3. VS Code 拡張機能 + - Dev Containers (ID: ms-vscode-remote.remote-containers) + ※ これが「必須」である.これさえあれば,以下の開発ツール群は自動セットアップされる. + + 4. アカウント・AI + - GitHub Copilot Pro (Student) + - Gemini Pro (学校提供ライセンス) + +4-2. 【自動】コンテナ内に構築されるもの (インストール不要) + 以下のツールは `devcontainer.json` に定義済みであり,コンテナ起動時に + 自動的にインストール・設定されるため,手動導入は不要である. + + 1. Runtime & Package Manager + - Node.js (v20.x LTS) + - pnpm (Latest) + + 2. VS Code 拡張機能 (コンテナ内) - ESLint - - Prettier - Code formatter - - EditorConfig for VS Code - - Hex Editor (バイナリパケットのデバッグ用・Microsoft公式) - - GitHub Copilot (要ログイン確認) - - 4. AI・アカウント環境 - - 学校提供の Gemini Pro へのアクセス権限確認 - - GitHub Copilot Pro (Student) の有効化確認 + - Prettier + - EditorConfig + - Hex Editor + + ※ ホスト側で `node -v` や `pnpm -v` を実行する必要はなく, + 全て VS Code の「ターミナル (コンテナ接続済)」で行う. 5. 実装上の重要ルール (Implementation Rules) diff --git "a/docs/01_Env/ENV_02_\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206\346\233\270.txt" "b/docs/01_Env/ENV_02_\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206\346\233\270.txt" index f8d5e5b..f0678f1 100644 --- "a/docs/01_Env/ENV_02_\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206\346\233\270.txt" +++ "b/docs/01_Env/ENV_02_\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206\346\233\270.txt" @@ -198,7 +198,7 @@ 1. プロジェクト作成 $ cd ../../apps/client $ pnpm create vite . --template preact-ts - ※ 実行中に表示される選択肢には以下のように回答すること: + ※ 実行中に表示される選択肢には以下のように回答すること: ? Use rolldown-vite (Experimental)? » No ? Install with pnpm and start now? » No @@ -261,44 +261,76 @@ } -4. 開発ツール設定 (Dev Tools Setup) +4. Docker環境での開発開始 (推奨手順) +------------------------------------------------------------------------ +本プロジェクトは VS Code の Dev Containers 機能を使用する. +これにより Node.js, pnpm, ESLint 等の環境が自動構築される. + +4-1. プロジェクトを開く + 1. VS Codeを起動し,「ファイル > フォルダを開く」からプロジェクトルートを選択する. + +4-2. コンテナでの再起動 (Reopen in Container) + 以下のいずれかの方法で,開発環境をコンテナ内に移行する. + + 【方法A: ステータスバーから】 + 1. ウィンドウ左下の緑色(または青色)の「><」アイコンをクリックする. + 2. 表示されるメニューから「Reopen in Container」を選択する. + + 【方法B: コマンドパレットから】 + 1. [F1] または [Ctrl+Shift+P] を押下する. + 2. "Reopen" と入力し,「Dev Containers: Reopen in Container」を選択する. + +4-3. 初回ビルドの待機 + 1. 初回起動時は Dockerイメージのビルドと npmパッケージのインストールが行われる. + (数分〜十数分かかる場合がある) + 2. 右下に "Starting Dev Container" 等の通知が表示されている間は待機する. + +4-4. 起動確認 + 1. 左下のアイコンが「Dev Container: Pixel Paint War Dev」と表示されていることを確認する. + 2. VS Codeのターミナルを開き (`Ctrl + @`),パスを確認する. + + 成功例: node@...:/workspace$ + (Windowsのパス C:\Users... ではなく Linux形式になっていれば成功) + + 3. 動作確認コマンドを実行する. + $ pnpm --filter client dev + + ブラウザで http://localhost:5173 にアクセスし,画面が表示されれば環境構築完了である. + + +5. 開発ツールの確認 (Tools Verification) +------------------------------------------------------------------------ +Dockerコンテナ起動完了後、定義済みのツールが正しく自動導入されているか確認する. +※ 手動でのインストールは不要である. + +5-1. VS Code 拡張機能 + 拡張機能サイドバーを開き、"Dev Container: Pixel Paint War Dev" セクションに + 以下がインストール済みであることを確認する. + + ・ESLint + ・Prettier - Code formatter + ・EditorConfig for VS Code + ・Hex Editor + ・GitHub Copilot + +5-2. AI アシスタント設定 + GitHub Copilot Pro + - VS Code 右下のアイコンから、GitHubアカウントへのログイン状態を確認する. + + +6. 構成確認 (Configuration Check) ------------------------------------------------------------------------ -4-1. VS Code 拡張機能 - 推奨エディタである VS Code に以下の拡張機能をインストールする. - - ■ 必須拡張機能 - ・ESLint - ・Prettier - Code formatter - ・EditorConfig for VS Code - - ■ 推奨拡張機能 - ・Hex Editor (バイナリパケットのデバッグ用・Microsoft公式) - ・GitHub Copilot - -4-2. AI アシスタント設定 - 開発効率化のため,以下のAIツールのアカウント設定を確認する. - - 1. Gemini Pro - ・学校提供ライセンスでのアクセス権限を確認する. - - 2. GitHub Copilot Pro - ・Student Developer Pack が有効化されているか確認する. - ・VS Code 右下のアイコンからログイン状態を確認する. - - -5. 構成確認 (Configuration Check) ------------------------------------------------------------------------- - -5-1. 最終ディレクトリ構成 +6-1. 最終ディレクトリ構成 構築完了時点で,以下のディレクトリおよびファイルが存在することを確認する. SkillSemiWebGame/ <-- プロジェクトルート + ├── .devcontainer/ <-- 【重要】Docker設定 + │ └── devcontainer.json ├── .git/ <-- git init で作成 ├── .gitignore <-- Git除外設定 - ├── .npmrc <-- 依存解決設定 + ├── docker-compose.yml <-- Docker構成 ├── package.json <-- ルート定義 - ├── pnpm-lock.yaml <-- pnpm install で自動生成 ├── pnpm-workspace.yaml <-- ワークスペース定義 ├── node_modules/ <-- 依存ライブラリ │ @@ -329,7 +361,7 @@ ├── package.json <-- buildスクリプト定義あり └── tsconfig.json <-- tsup/typescript設定用 -5-2. 重要ファイル設定確認 +6-2. 重要ファイル設定確認 各パッケージの連携設定が正しいか確認する. ■ root/pnpm-workspace.yaml @@ -351,19 +383,16 @@ "@repo/shared": "workspace:*" -6. 動作確認 (Verification) +7. 動作確認 (Verification) ------------------------------------------------------------------------ -6-1. ビルド確認 - ルートディレクトリから全体の依存関係をインストールし,ビルドを試行する. - - $ cd ../../ - $ pnpm install - $ pnpm --filter @repo/shared build +7-1. ビルド確認 + ※ 注意: 以下のコマンドは全て「Dev Container内のターミナル」で実行すること. + $ pnpm --filter @repo/shared build ※ shared のビルドが成功することを確認する. -6-2. 開発サーバー起動 +7-2. 開発サーバー起動 モノレポ構成のため,個別のディレクトリに移動せず,プロジェクトルートから --filter オプションを使用して各アプリを起動する. ※ ターミナルを2つ開き,両方を同時に起動した状態で開発を進めることを推奨. @@ -398,4 +427,42 @@ ・動作確認を終了し,開発サーバーを停止させる場合は,ターミナル上で 「Ctrl + C」を押下する. ・停止後はブラウザでURLにアクセスしても接続不可となるが,再度起動 - コマンドを実行すればいつでも再開可能である. \ No newline at end of file + コマンドを実行すればいつでも再開可能である. + + +8. 本番デプロイ手順 (Production Deployment) +------------------------------------------------------------------------ +本番環境(サーバー)へのデプロイは,Dockerを使用して最適化されたイメージを作成して行う. + +8-1. +構成ファイルの準備 + プロジェクトルートに以下のファイルが存在することを確認する. + 1. Dockerfile (Multi-stage build構成) + - `pnpm prune` 後の `node_modules` コピー処理が含まれていること. + 2. docker-compose.prod.yml (本番起動用) + - ポート設定: "3001:3000" (ホスト側3001番 -> コンテナ側3000番) + +8-2. +ローカルでの本番稼働テスト + 開発環境(Dev Container)と同時に起動する場合,ポート衝突を避けるために + ホスト側のポートをずらして起動する. + + 1. ビルドと起動 (WSL/ホスト側のターミナルで実行) + $ docker compose -f docker-compose.prod.yml up -d --build + + 2. 稼働確認 + $ docker compose -f docker-compose.prod.yml ps + ・Stateが "Up" であり,"Restarting" を繰り返していないことを確認する. + + 3. ログ確認 + $ docker compose -f docker-compose.prod.yml logs -f + ・"Pixel Paint War Server started on port 3000" と表示されれば成功. + + 4. ブラウザ接続確認 + ・URL: http://localhost:3001 + ・表示: "Upgrade Required" と表示されれば,WebSocketサーバーとして正常に稼働している. + +8-3. +停止と削除 + テストが終了したらリソースを解放する. + $ docker compose -f docker-compose.prod.yml down \ No newline at end of file diff --git "a/docs/01_Env/ENV_05_Docker\351\201\213\347\224\250\346\223\215\344\275\234\343\202\254\343\202\244\343\203\211.txt" "b/docs/01_Env/ENV_05_Docker\351\201\213\347\224\250\346\223\215\344\275\234\343\202\254\343\202\244\343\203\211.txt" new file mode 100644 index 0000000..be89f13 --- /dev/null +++ "b/docs/01_Env/ENV_05_Docker\351\201\213\347\224\250\346\223\215\344\275\234\343\202\254\343\202\244\343\203\211.txt" @@ -0,0 +1,82 @@ +======================================================================== +Docker 運用・操作ガイド (Docker Operations Guide) +======================================================================== + +1. 目的 (Objective) +------------------------------------------------------------------------ +本ドキュメントは,Pixel Paint War プロジェクトにおける Docker の日常的な +操作コマンドと,トラブルシューティング手順をまとめたものである. +本プロジェクトでは「開発環境」と「本番環境」で異なる運用を行う. + + +2. 開発環境 (Development Environment) +------------------------------------------------------------------------ +VS Code の Dev Containers 機能を使用する. + +2-1. +基本操作 + ・起動: VS Code でプロジェクトを開き,「Reopen in Container」を実行する. + ・停止: VS Code を閉じる(自動的に停止する). + ・ターミナル: VS Code 内のターミナルを使用する. + +2-2. +コンテナの再構築 (Rebuild) + 依存関係の不整合や設定変更が反映されない場合に実行する. + 1. コマンドパレット (F1) を開く. + 2. 「Dev Containers: Rebuild Container」を選択する. + 3. キャッシュを無視したい場合は「Rebuild Without Cache」を選択する. + + +3. 本番環境 (Production Environment) +------------------------------------------------------------------------ +手動で Docker Compose コマンドを実行する. +※ 必ず WSL (Windows) または ホストOSのターミナルで実行すること. + +3-1. +基本コマンド + ■ 起動 (ビルド込み) + $ docker compose -f docker-compose.prod.yml up -d --build + + ■ 状態確認 + $ docker compose -f docker-compose.prod.yml ps + + ■ ログ確認 (リアルタイム) + $ docker compose -f docker-compose.prod.yml logs -f + + ■ 停止 + $ docker compose -f docker-compose.prod.yml down + +3-2. +ポート仕様 + ・ホスト側ポート: 3001 + ・コンテナ内ポート: 3000 + ・接続確認URL: http://localhost:3001 + ※ 開発用コンテナ (Port 3000) との衝突を避けるため,3001番を使用する. + + +4. トラブルシューティング (Troubleshooting) +------------------------------------------------------------------------ + +4-1. +ビルドエラー・反映漏れへの対処 + 修正したコードが反映されない,または原因不明のエラーが出る場合, + キャッシュを使わずに強制的に再ビルドを行う. + + $ docker compose -f docker-compose.prod.yml build --no-cache + $ docker compose -f docker-compose.prod.yml up -d --force-recreate + +4-2. +モジュールが見つからない (MODULE_NOT_FOUND) + 本番起動時に `ws` 等が見つからないエラーが出る場合,`Dockerfile` の + COPY記述を確認する.pnpm のシンボリックリンク構造に対応するため, + 以下が記述されている必要がある. + + COPY --from=builder /app/apps/server/node_modules ./apps/server/node_modules + +4-3. +再起動ループ (Restarting) + `docker ps` でステータスが `Restarting` になる場合,サーバープロセスが + クラッシュまたは終了している. + 1. ログを確認する: + $ docker compose -f docker-compose.prod.yml logs --tail=50 + 2. コード修正後,4-1 の手順で再デプロイする. \ No newline at end of file