はじめに
Docker環境でRails + Next.jsのフルスタックアプリケーションを開発している際に、バックエンドが起動しない問題に遭遇しました。この記事では、問題の原因と解決策の一つとして紹介します。
環境
- OS: macOS
- Docker: Docker Desktop
- バックエンド: Rails 8.0.2.1 + Ruby 3.4
- フロントエンド: Next.js 15.5.2 + TypeScript
- データベース: PostgreSQL 16
- キャッシュ: Redis 7
発生した問題
1. バックエンドコンテナが起動しない
docker compose up
# ログの出力
backend-1 | => Booting Puma
backend-1 | => Rails 8.0.2.1 application starting in development
backend-1 | => Run `bin/rails server --help` for more startup options
backend-1 | A server is already running (pid: 1, file: /app/tmp/pids/server.pid).
backend-1 | Exiting
2. Next.js設定の警告
frontend-1 | ⚠ Invalid next.config.ts options detected:
frontend-1 | ⚠ Unrecognized key(s) in object: 'swcMinify'
問題の原因分析
原因1: server.pidファイルの残存
なぜ起こったのか?
-
異常終了の履歴: 以前のRailsサーバーが正常に終了せず、
server.pidファイルが残存 -
Dockerボリュームマウント:
./backend:/appでホストのファイルシステムをマウントしているため、PIDファイルが永続化 -
Railsの起動チェック: Railsは起動時に
tmp/pids/server.pidをチェックし、既存のPIDがある場合は起動を拒否
技術的な詳細
# docker-compose.yml
volumes:
- ./backend:/app # ホストのファイルシステムをマウント
この設定により、ホストマシン上のbackend/tmp/pids/server.pidがコンテナ内の/app/tmp/pids/server.pidにマウントされ、コンテナを再起動してもファイルが残り続けます。
原因2: Next.js設定の非互換性
なぜ起こったのか?
-
バージョンアップ: Next.js 15では
swcMinifyオプションが削除された - 設定の古い記述: 以前のバージョン用の設定が残っていた
解決策
解決策1: server.pidファイルの削除
手順1: コンテナを停止
$ docker compose down
手順2: PIDファイルを削除
$ rm -f backend/tmp/pids/server.pid
手順3: コンテナを再起動
$ docker compose up -d
解決策2: Next.js設定の修正
修正前(問題のある設定)
frontend/next.config.ts
const nextConfig: NextConfig = {
reactStrictMode: true,
swcMinify: true, // ← Next.js 15では認識されない
// ... その他の設定
};
修正後(正しい設定)
frontend/next.config.ts
const nextConfig: NextConfig = {
reactStrictMode: true,
// swcMinifyを削除
// ... その他の設定
};
根本的な対策
1. Dockerfileの改善
backend/Dockerfile
# 起動スクリプトを追加
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["bin/rails", "server", "-b", "0.0.0.0"]
backend/docker-entrypoint.sh
#!/bin/bash
set -e
# 既存のPIDファイルを削除
rm -f /app/tmp/pids/server.pid
# コマンドを実行
exec "$@"
2. docker-compose.ymlの改善
docker-compose.yml
services:
backend:
# ... 既存の設定
volumes:
- ./backend:/app
- bundle_cache:/usr/local/bundle
# PIDファイルは除外
- /app/tmp/pids
# ヘルスチェックを追加
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
予防策
1. 定期的なクリーンアップ
# 週次で実行するクリーンアップスクリプト
#!/bin/bash
docker-compose down
rm -rf backend/tmp/pids/*
rm -rf frontend/.next
docker-compose up -d
2. ヘルスチェックの実装
backend/app/controllers/health_controller.rb
class HealthController < ApplicationController
def index
render json: { status: 'ok', timestamp: Time.current }
end
end
backend/config/routes.rb
Rails.application.routes.draw do
get '/health', to: 'health#index'
# ... その他のルート
end
3. ログローテーションの設定
docker-compose.yml
services:
backend:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
トラブルシューティングのチェックリスト
バックエンドが起動しない場合
-
server.pidファイルが存在しないか確認 - ポート3000が他のプロセスで使用されていないか確認
- データベース接続が正常か確認
- ログでエラーメッセージを確認
フロントエンドが起動しない場合
- Next.js設定ファイルの構文エラーがないか確認
- 依存関係が正しくインストールされているか確認
- ポート3001が他のプロセスで使用されていないか確認
全体的な問題
-
Dockerコンテナの状態確認:
docker-compose ps -
ログの確認:
docker-compose logs [service-name] -
ボリュームの確認:
docker volume ls
まとめ
今回の問題は、以下の2つの要因が重なって発生しました:
- RailsのPIDファイル管理: 異常終了時のPIDファイル残存
- Next.js設定の非互換性: バージョンアップによる設定オプションの変更
重要なポイント
- Docker環境では、ボリュームマウントによりホストのファイルが永続化される
- アプリケーションの起動前には、古いPIDファイルのクリーンアップが必要
- フレームワークのバージョンアップ時は、設定ファイルの互換性を確認する
これらの対策を実装することで、安定した開発環境を構築できます。