個人開発で使っているNext.js + Express + React Viteの構成、デプロイまわりがかなり場当たり的になっていたので、GHCRを軸にCI/CDを整理し直すことにした。進捗あれば随時追記していく。
これまでの構成
ローカル環境
Next.jsはnpm run devで直接起動、React Viteも同様に直接起動している。BackendとMySQLだけdocker-composeで動かしていた。つまりローカルではDockerに寄せきれておらず、フロント系は素で動かしている状態。
Lightsail(本番)
/var/www/app/にリポジトリをクローンし、docker-compose.prod.ymlでbackend・Next.js・MySQLをDockerコンテナとして動かしている。React Vite(管理画面)はビルド済みの静的ファイルを/var/www/app/backend/public/に配置し、ホスト側のNginxから配信。Nginxはリバースプロキシとして各サービスの前段に立っている。
何が問題だったか As-Is → To-Be
Next.jsの二重ビルド問題
GitHub Actionsでビルド → scpでファイル転送 → Lightsail上でさらにDocker再ビルド、という流れになっていた。せっかくCIでビルドしているのに、本番側でもう一度ビルドが走る無駄な構成。
またLightsail上でビルドするフローのため、AWSコンソール画面でメトリクスでバーストキャパシティの枯渇を確認しました、、Next.jsのビルド中にメモリ不足で502エラーが発生しており、デプロイが不安定な状態です。
Backend:Lightsailでビルドが走る
Lightsail上でgit pullしてからdocker buildしている。ビルドがサーバー上で走るので、CI/CDとしては中途半端。サーバーのリソースも食うし、ビルドの再現性も担保しにくい。
React Vite:同じくサーバー上でビルド
Lightsail上でgit pull → npm run build。これも本番サーバーでビルドしているので同じ問題。
共通しているのは「ビルドをどこでやるか」が統一されていないこと。GitHub Actionsがあるのに活かしきれていなかった。
3つのリポジトリは別々?それとも1つのモノレポ?
As-Is
親リポジトリはnext-basic/, vite-react-0206/, backend/をgitignoreしていて、それぞれが独立したリポジトリ。
親リポジトリにはdocker-compose.yml, initdb/, db/.envなどの共通設定だけがある。
To-Be 推奨する構成変更
親リポジトリ(express-mysql-docker)は不要にできる。各リポジトリが自分のDockerイメージをGHCRにpushし、Lightsail側にはdocker-compose.prod.ymlとNginx設定だけ置く。
[GitHub]
backend repo → ghcr.io/あなた/backend:latest
next-basic repo → ghcr.io/あなた/nextjs:latest
vite-react repo → ghcr.io/あなた/admin:latest (nginx+静的ファイル)
[Lightsail]
/var/www/app/
docker-compose.prod.yml ← これだけ管理
initdb/ ← 初期化SQL(既存のまま)
db/.env ← MySQL認証情報
backend/.env ← Backend認証情報
Nginx (ホスト側) → 今とほぼ同じ
docker compose pull && docker compose up -d ← デプロイはこれだけGHCRを使った新しい構成
方針はシンプルで、GitHub Actionsでイメージをビルドしてghcr.ioにpush → Lightsailではpullしてdocker compose up -dするだけにする。
GitHub Actions(ビルド & push)
→ ghcr.io/<user>/backend:latest
→ ghcr.io/<user>/nextjs:latest
→ ghcr.io/<user>/admin:latest(nginx + 静的ファイル)
Lightsail(pull & run)
docker compose -f docker-compose.prod.yml up -d
+ Nginx(ホスト側、既存のまま)
これでLightsail上ではビルドが一切走らなくなる。デプロイはdocker compose pull && docker compose up -dだけ。
進める前に確認・決めたいこと
React Vite管理画面のコンテナ化
今はビルド済みファイルをホスト側Nginxから直接配信しているが、nginx + 静的ファイルのDockerコンテナにするのが自然だと思う。コンテナにすれば他と同じくGHCRからpullするだけで済む。
リポジトリ構成
express-mysql-dockerの中に全部入っているモノレポっぽい構成に見えるが、React ViteとNext.jsのGitHub Actionsが別リポジトリのようにも見える。ここの整理が必要。
MySQLのデータ移行
既存のdocker volumeをそのまま使えば問題ないはず。コンテナを差し替えてもvolumeは維持される。
今後の予定
構成が固まり次第、GitHub Actionsのワークフロー作成から着手する。進捗があれば追記予定。
最終更新:2025年2月