アプリをDocker化してデプロイしたお
なぜこのようにアプリをDocker化することにしたのか、
それは、現在はLinux mint OS上で開発しているため、
ローカルでビルド->本番環境に(Ubuntu)デプロイ-> 公開
が可能であったが、Windows, Mac 環境でも通用するかといえば、そういうわけではない。
そのため、汎用的に適応できるために、このようなコンテナ化を実施することにしました!
あと、他にもアプリケーションが色々とあるので、全てコンテナ化してdocker composeや、k8sで管理できるようにしたい!
そのための第一歩としてNext.jsアプリケーションをコンテナ化してデプロイしたいと思いました!
Docker化・GHCRデプロイ振り返り
① Bun + node:sqlite が動作しない
Point
Bun環境では node:sqlite は使えなかった
Reason
node:sqlite は Node.js の組み込みモジュールであり、Bunは完全互換ではないため解決できない
Example
ビルド時に module が見つからないエラーが発生
Point
Node環境に変更する必要があると判断
② better-sqlite3 導入時の型エラー
Point
TypeScriptの型不足でビルドが失敗した
Reason
better-sqlite3 は型定義が別パッケージとして提供されているため
Example
型定義が見つからないというエラーが発生
Point
型パッケージを追加して解決
③ better-sqlite3 のネイティブエラー
Point
Bunではネイティブモジュールが動かなかった
Reason
better-sqlite3 はC++ネイティブであり、Bunではビルド・実行が不安定
Example
バイナリが見つからないエラーが発生
Point
Node環境へ完全移行することで解決
④ node:sqlite の残存によるビルド失敗
Point
古いコードが残っていた
Reason
一部ファイルで node:sqlite のimportが残っていた
Example
ビルド時に該当モジュールが見つからないエラー
Point
プロジェクト全体を検索し完全削除
⑤ server.js 起動エラー
Point
起動方法が間違っていた
Reason
Next.jsは node server.js ではなく next start で起動する
Example
server.js が見つからないエラー
Point
npm run start に修正して解決
⑥ Docker image が巨大化
Point
イメージサイズが異常に大きかった
Reason
単一ステージビルドにより依存や不要ファイルが全て含まれていた
Example
数百MBのレイヤーが生成された
Point
マルチステージビルドや軽量化の必要性を理解
⑦ GHCR push時の権限エラー
Point
push時に permission_denied が発生
Reason
トークン権限不足またはnamespaceの誤り
Example
create_package エラー
Point
PATの権限とユーザー名の確認で解決
⑧ GHCRのユーザー名問題
Point
Dockerでは大文字ユーザー名が使えなかった
Reason
Docker repository名は小文字のみ許可される
Example
invalid reference format エラー
Point
ユーザー名を小文字に統一して解決
⑨ GHCR pull時の unauthorized エラー
Point
本番サーバでpullできなかった
Reason
パッケージがPrivateのため認証が必要だった
Example
unauthorized エラー
Point
Publicに変更することで解決
⑩ Docker Compose が使えない
Point
docker compose コマンドが存在しなかった
Reason
Ubuntu標準の docker.io には compose plugin が含まれていなかった
Example
unknown command エラー
Point
docker-compose-v2 をインストールして解決
⑪ systemd から Docker へ移行
Point
従来の起動方法を廃止した
Reason
コンテナ運用へ統一するため
Example
systemdサービスを停止しDockerに置き換え
Point
docker compose による運用へ移行完了
最終まとめ
今回の本質は「実行環境の整理と統一」である
- BunではなくNodeを選択することで安定性を確保
- ネイティブモジュールの特性を理解
- Dockerによる実行環境の標準化
- GHCRを用いた配布とデプロイの簡略化
- systemdからコンテナ運用への移行
結果として
ローカル開発 → Docker build → GHCR push → 本番pull → 起動
という一貫したデプロイフローを構築できた
これは実務でも通用する構成であり、インフラとアプリの責務分離ができた状態である
Discussion