導入
開発中のWebアプリケーションで、なぜか消えない表示に悩まされた経験はありませんか?
今回は、`kouchou-ai`というプロジェクトで「AIによるレポート作成中です」という表示が消えなくなり、その原因を徹底的に調査・解決した過程をブログ記事としてまとめました。同じような問題に直面した方の参考になれば幸いです。
事象
`kouchou-ai`の管理画面(`http://localhost:4000`)でレポート作成を開始したところ、「AIによるレポート作成中です。完了までしばらくお待ちください。」という表示が出続け、何度アプリケーションを再起動しても消えませんでした。

初期調査と誤解
まず、問題解決のためにいくつかの一般的なデバッグ手法を試みました。
1. API経由での停止:
バックエンドAPIの DELETE /admin/reports/{slug}
エンドポイントを使ってレポートの停止を試みましたが、「レポートが見つからない」というエラーで失敗しました。
2. Dockerコンテナの再起動:
docker compose down でコンテナを停止し、docker compose up -d
で再起動。しかし、管理画面の表示は消えませんでした。
3. Dockerボリュームの削除:
docker compose down -v
を実行し、Dockerボリュームも削除して再起動。それでも表示は消えませんでした。この時点で「データは完全に消えたはずなのに…」という大きな疑問が生まれました。
4. ブラウザキャッシュとフロントエンドの再ビルド:
ブラウザのキャッシュクリア、シークレットモードでのアクセス、さらにはフロントエンド(client-admin)のDockerイメージ再ビルドまで試しましたが、状況は変わりませんでした。
原因の深掘り
表示が消えない根本原因を探るため、アプリケーションの内部動作を詳細に調査しました。
1. フロントエンドの表示ロジック:
client-admin の app/page.tsx を確認すると、fetch(`${getApiBaseUrl()}/admin/reports`)
というコードでバックエンドからレポート一覧を取得していることが判明しました。しかし、ブラウザの開発者ツール(Networkタブ)にはこのリクエストが見当たりませんでした。これはNext.jsのSSR(Server-SideRendering)やRSC(React ServerComponents)の機能により、サーバーサイドでAPIリクエストが実行され、その結果がHTMLに埋め込まれてクライアントに送られてい*ためでした。
そして、このHTMLコンテンツの中に、status: "processing"
となったレポート情報が埋め込まれていることを発見しました。これが「AIによるレポート作成中です」という表示の直接の原因でした。
2. バックエンドのデータ永続化:
HTMLに埋め込まれた「処理中」のレポート情報がどこから来ているのかを特定するため、バックエンドのデータ永続化の仕組みを調査しました。
* server/src/config.py で、レポートのステータスが settings.DATA_DIR / "report_status.json"
というファイルに保存されることが判明。
* settings.DATA_DIR はホスト側の ./server/data ディレクトリを指していました。
* compose.yaml を確認すると、api サービスはホスト側の ./server ディレクトリをコンテナ内の
/app にバインドマウントしていました。
核心的な原因
docker compose down -v コマンドは、Dockerの名前付きボリュームは削除しますが、
ホスト側のディレクトリをコンテナにマウントしている「バインドマウント」は削除しません。
したがって、report_status.json ファイルはホスト側の ./server/data/report_status.json
に保存されており、docker compose down -v を実行しても削除されずに残っていたのです。
api サービスは起動時にこの残っていた report_status.json を読み込み、その中に含まれる processing 状態のレポート情報を再度メモリにロードしていました。そして、client-admin はサーバーサイドでこの情報を取得し、HTMLに埋め込んでクライアントに送っていたため、何度再起動しても表示が消えなかった、というわけです。
解決策
原因が特定できたため、解決策はシンプルでした。
1. 現在起動中のコンテナを停止:
docker compose down
. ホスト側の `report_status.json` ファイルを直接削除:
rm ./server/data/report_status.json
(注意: このコマンドは、kouchou-ai プロジェクトのルートディレクトリで実行してください。)
. コンテナを再起動:
docker compose up -d
4. ブラウザのキャッシュを再度クリアし、http://localhost:4000 にアクセス。
この手順を実行したところ、無事に「AIによるレポート作成中です。」という表示が消え、管理画面が正常な状態に戻りました!
教訓と学び
今回のデバッグを通じて、以下の重要な教訓を得ました。
* Dockerのボリュームとバインドマウントの違い: docker compose down -v
が削除するのは名前付きボリュームのみであり、バインドマウントされたホスト側のデータは削除されないことを再認識しました。アプリケーションのデータ永続化の仕組みを正確に理解することが重要です。
* アプリケーションのデータ保存パスの確認:
問題発生時には、アプリケーションがどこにデータを保存しているのか(特に設定ファイルやステータスファイル)をまず確認することが解決への近道です。
* フロントエンドとバックエンドの連携:
Next.jsのSSR/RSC環境では、ブラウザのNetworkタブに表示されないサーバーサイドのAPIリクエストが存在するため、デバッグ時にはその挙動を考慮に入れる必要があります。HTMLコンテンツに埋め込まれたデータも重要なヒントになります。
まとめ
一見すると単純な表示の問題でしたが、その裏にはDockerの仕組み、アプリケーションのデータ永続化、そしてNext.jsのレンダリングメカニズムが複雑に絡み合っていました。今回の経験が、同様の問題に直面した開発者の方々の一助となれば幸いです。



