【ITニュース解説】Build your own Posthog - PART 2

2025年09月04日に「Dev.to」が公開したITニュース「Build your own Posthog - PART 2」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

Posthog風分析システム構築の第2回。今回はインフラ設定、Docker、API Gatewayの実装を解説する。API Gatewayはクライアントとバックエンド間の一元的な入り口として、CORS管理やログ記録を担う。Docker ComposeでDBやメッセージキューを設定し、TypeScript/ExpressでAPI Gatewayを構築、Dockerコンテナ化した。

出典: Build your own Posthog - PART 2 | Dev.to公開日:

ITニュース解説

この解説では、分析システム「SmolHog」のインフラ構築、Dockerを使ったコンテナ化、そしてAPI Gatewayの実装に焦点を当てる。システムエンジニアを目指す初心者でも理解できるよう、各要素の役割と具体的な設定方法を詳しく説明する。

まず、API Gatewayという重要なコンポーネントについて説明する。API Gatewayは、クライアントアプリケーションとバックエンドサービスの間で、リクエストの「交通整理役」として機能するサーバーだ。例えるなら、家の「玄関」のようなもので、クライアント(スマートフォンアプリやウェブアプリケーションなど)からのすべてのリクエストが最初にここに届き、適切なバックエンドサービスへと振り分けられる。

なぜAPI Gatewayが必要なのかというと、SmolHogのようなシステムでは、複数のバックエンドサービスが連携して動作することがよくある。API Gatewayがない場合、クライアントは各サービスのエンドポイント(URL)を個別に知っておく必要があり、非常に複雑になる。API Gatewayがあれば、クライアントはただ一つの入り口(API Gateway)にリクエストを送るだけでよくなる。また、異なるドメインからのリクエストを許可するCORS(Cross-Origin Resource Sharing)の設定や、すべてのリクエストとレスポンスのログ記録といった共通の処理を、一箇所でまとめて管理できる利点もある。これにより、システム全体のセキュリティや監視が容易になる。

次に、SmolHogプロジェクトの構造を見てみよう。このプロジェクトは「モノレポ」と呼ばれる形式で構成されている。これは、複数のプロジェクトやサービスが単一のリポジトリ(コードを管理する場所)で管理される形式で、開発ワークフローを効率化できる。プロジェクトの主要なディレクトリには、Docker関連の設定をまとめたdocker-compose.ymlファイル、ビルドコマンドなどを定義するMakefile、インフラ関連のコードを格納するinfraディレクトリ、データベースのスキーマ変更履歴を管理するmigrationsディレクトリ、そしてFlutterアプリケーションのコードが含まれるsmolhog_flutterディレクトリなどがある。infraディレクトリの中には、backend(API Gatewayやイベントプロセッサなど)とfrontend(ウェブアプリケーションなど)がさらに分けられている。

SmolHogの構築には、データベースとしてPostgreSQL、メッセージキューとしてRabbitMQといった様々なツールが利用される。これらのツールをプロジェクトに組み込むために、Dockerという技術を活用する。Dockerを使うと、これらのツールをそれぞれ独立した「コンテナ」として動作させることができ、環境構築の手間を大幅に削減できる。コンテナは、アプリケーションとその実行に必要なすべてのものをパッケージ化したもので、どんな環境でも同じように動作することを保証する。

docker-compose.ymlファイルは、これらのDockerコンテナをまとめて管理し、連携させるための設定ファイルだ。このファイルの中で、PostgreSQLとRabbitMQのサービスを定義する。PostgreSQLサービスでは、postgres:latestという最新のPostgreSQLイメージを使用し、データベース名、ユーザー名、パスワードを設定する。ポート5432を開放して外部からアクセスできるようにし、postgres_dataというDocker管理のボリュームを使ってデータベースのデータを永続化する。これにより、コンテナが停止したり削除されたりしてもデータは失われない。また、./migrationsディレクトリにあるSQLスクリプトを、コンテナが初めて起動する際に自動で実行するように設定し、初期のデータベーススキーマ(テーブルの構造など)を簡単にセットアップできるようにしている。RabbitMQサービスでは、rabbitmq:4.0-managementイメージを使用し、メッセージング用のポート5672と、管理UI用のポート15672を開放する。PostgreSQLとRabbitMQの両方のサービスは、smolhog-networkという専用のネットワークに参加する。このネットワークは、SmolHogの各サービスが互いにサービス名を使って通信できる、隔離された環境を提供する。

次に、API Gatewayの実装に進む。SmolHogのAPI Gatewayは、TypeScriptとExpress.jsという技術を使って構築される。infra/backend/api-gateway/index.tsファイルにAPI Gatewayの主要なコードを記述する。まず、corsexpresshttp-proxy-middlewareといった必要なモジュールをインポートする。corsミドルウェアは、前述したCORSの管理を行う部分で、ウェブブラウザのセキュリティ制限を緩和し、異なるドメインからのリクエストを許可するための設定を行う。これにより、SmolHogのウェブダッシュボードやFlutterウェブアプリがAPI Gatewayに安全にアクセスできるようになる。

アプリケーションはexpress.json()ミドルウェアを使い、JSON形式のリクエストボディを扱えるように設定する。/パスへのGETリクエストに対するシンプルなウェルカムメッセージも用意されている。 リクエストをバックエンドサービスに転送するための設定は、createProxyOptionsというヘルパー関数で行う。この関数は、転送先のURL(target)、リクエストのオリジン(送信元)を変更するかどうか(changeOrigin)、そしてリクエストパスの書き換えルール(pathRewrite)を定義する。pathRewriteは、例えばAPI Gatewayが/api/eventsで受け取ったリクエストを、バックエンドサービスでは/eventsというパスに転送するといった変換を行うために重要だ。また、プロキシ処理中にエラーが発生した場合の処理(onError)や、プロキシリクエストが送信される直前に行う処理(onProxyReq)も設定し、エラーログの出力やリクエストヘッダーのコピーなどを行う。

リクエストロギングミドルウェアは、API Gatewayを通過するすべてのリクエストとレスポンスを監視するために重要な役割を果たす。このミドルウェアは、リクエストが到着した時刻、HTTPメソッド、URL、ヘッダー、クエリパラメータ、そしてリクエストボディなどの詳細情報をログに出力する。また、レスポンスがクライアントに送り返される際には、処理にかかった時間、HTTPステータスコードを記録し、もしエラーレスポンス(400番台以上のステータスコード)だった場合には、そのエラーの詳細やレスポンスボディも記録する。これにより、問題発生時の原因究明やシステムの監視が容易になる。

ルーティング設定は、API Gatewayがどのようにリクエストをバックエンドサービスに振り分けるかを定義する部分だ。SmolHogのEvent Processorサービスには、/events/analytics/events/analytics/statsという3つのエンドポイントがある。API Gatewayでは、これらのエンドポイントに対して、/api/events/api/analytics/events/api/analytics/statsといった形でマッピングを行う。つまり、クライアントがAPI Gatewayの/api/*というパスにリクエストを送ると、API GatewayはそれをcreateProxyMiddlewarecreateProxyOptionsの設定に基づき、Event Processorの対応するエンドポイントに転送する。最後に、API Gatewayは指定されたポート(デフォルトは3001)でリクエストの待ち受けを開始する。

API Gatewayのコードが完成したら、それをDockerコンテナとして動かすための設定を行う。infra/backend/api-gatewayディレクトリ内にDockerfileを作成する。Dockerfileは、コンテナイメージを構築するための手順を記述したファイルだ。このファイルでは、まずoven/bun:1.2.18-alpineという軽量なイメージをベースとして使用し、作業ディレクトリを設定し、プロジェクトの依存関係(必要なライブラリなど)をインストールする。次に、API Gatewayのソースコードをコンテナ内にコピーし、API Gatewayがリッスンするポート3001を外部に公開する。最後に、bun run devコマンドでアプリケーションを起動するように指示する。

そして、このAPI Gatewayサービスをdocker-compose.ymlファイルに追加する。api-gatewayサービスの設定では、buildセクションでDockerfileの場所を指定し、イメージが自動的に構築されるようにする。ホストマシンのポート3001とコンテナのポート3001をマッピングし、外部からAPI Gatewayにアクセスできるようにする。volumes設定により、開発中にソースコードを変更した際、コンテナを再構築することなく変更が即座に反映されるようにする。environmentセクションでは、EVENT_PROCESSOR_URLという環境変数を設定し、API GatewayがバックエンドのEvent ProcessorサービスにアクセスするためのURLを定義する。このURLは、smolhog-network内でEvent Processorのサービス名(event-processor)とポート番号(8000)を使って指定される。また、depends_on: event-processorという設定により、API Gatewayが起動する前にEvent Processorが起動することを保証する。これにより、すべてのサービスが適切に連携して動作するようになる。

このようにして、API Gatewayの構築とDockerコンテナへの組み込みが完了する。このAPI Gatewayは、次のステップで構築されるEvent Processorサービスに依存しており、システム全体の重要な一要素となる。