Data Clerk へのデプロイ
このアプリは Data Clerk 上で動作します。Data Clerk は、オペレーター(人間、連絡先は PROJECT.md に記載)が運用する小規模なマネージド Kubernetes クラスターです。このリポジトリの所有者は、通常、インフラストラクチャ担当者ではありません。サーバーや Kubernetes、クラウドコンソールに触れる必要は一切ありません。main にプッシュすれば、あとはクラスターがやってくれます。 あなたの仕事は、その状態を維持することです。リポジトリ内で作業し、以下の契約に従い、どうしてもクラスター側の対応が必要な場合は、場当たり的な対応をするのではなく、オペレーターに明確なリクエストを送ってください。
ユーザーには、「サイトは約5分で更新されます」といった平易な言葉で説明し、Kubernetes 用語は使わないでください。
ここから始める
deploy-data-clerk/PROJECT.mdを読んでください。このプロジェクトの値(公開 URL、デプロイフォルダ、イメージ名、ポート、マイグレーションコマンド、制限、オペレーターの連絡先)が記載されています。以下の「PROJECT.md から」という記述はすべてこのファイルを指します。PROJECT.md 内のフォルダ名がdeploy-data-clerk/と異なる場合(古いプロジェクトではdeploy/を使っています)、PROJECT.md の内容に従ってください。PROJECT.mdがない、またはまだ__PLACEHOLDER__のままですか?プロジェクトはまだオンボーディングされていません。references/new-project.mdに従ってください。- Dockerfile の作成や変更、アプリの構成方法の選択、スタックが Node ではない場合?
references/stacks.md(任意の言語、フルスタック vs フロントエンド + API の分離、FastAPI、Go)を読んでください。 - マシンで初めてシークレットタスクを行う前に、ツールが動作することを確認してください:
sops --versionとテスト復号化(sops decrypt <deploy folder>/secrets.env > /dev/null)。どちらかが失敗した場合は、references/setup-tools.mdに従ってください。
変更がライブサイトに反映される仕組み
| 変更内容 | 何が起こるか | ライブ反映までの時間 |
|---|---|---|
コード(main へのプッシュ) | GitHub Actions が Docker イメージをビルドしてプッシュし、クラスターが新しいイメージタグを検出してロールアウトする | 約3~7分(ビルド時間 + 約1分) |
secrets.env(main へのプッシュ) | クラスターが5分ごとにデプロイフォルダを再読み込みし、復号化してアプリの環境変数を更新、アプリを再起動する | 約5分 |
migrations/ 内の新しいファイル | 新しいバージョンが起動する前に自動的に実行される | コードデプロイと同時 |
main 以外の変更 | 何も起こらない。ブランチと PR はデプロイされない | — |
ロールアウトは慎重に行われます。新しいバージョンは古いバージョンの隣で起動し、マイグレーションが最初に実行され、新しいバージョンがヘルスチェックに応答して初めてトラフィックが切り替わります。ビルド、マイグレーション、またはヘルスチェックが失敗した場合、古いバージョンがサービスを続け、サイトはダウンしません。デプロイの失敗は「変更が反映されていない」ことであり、「サイトがダウンしている」ことではありません。
デプロイを確認するには:gh run list --workflow "Deploy to cluster" --limit 3(または GitHub の Actions タブ)を実行し、公開 URL を開いてください。コード変更なしで再デプロイするには:gh workflow run "Deploy to cluster" を実行します。これにより新しいタグがビルドされ、アプリが新しい環境で再起動します。
契約(デプロイを機能させ続けるためのルール)
各ルールは、破ると静かに失敗したりデータが失われたりするために存在します。これらを守り、ユーザーのリクエストがルールを破る場合はその旨を伝えてください。
$PORTでリッスンする(PROJECT.md のポート、クラスターによって設定されます)。0.0.0.0でリッスンし、localhostではリッスンしないでください。- イメージは
<deploy folder>/Dockerfileからlinux/amd64向けにビルドされ、非 root ユーザーで実行されます。root 不可、ポート 1024 未満の使用不可、追加の Linux ケイパビリティは不要です。 - イメージタグは
YYYYMMDDHHMMSS-<shortsha>形式です。 クラスターは最も大きい番号をデプロイし、この形式以外のタグは静かに無視します。.github/workflows/deploy-cluster.ymlのタグ生成ステップは決して変更しないでください。 - コンテナのディスクはデプロイと再起動のたびに消去されます。 ユーザーアップロード、SQLite ファイル、その他貴重なデータはローカルディスクに保存しないでください。データはデータベースに入れてください。ファイル(写真、動画)の場合は、オブジェクトストレージについてオペレーターに依頼してください。
- ヘルスチェック: クラスターは PROJECT.md のヘルスパス(
/healthz推奨)をプローブします。データベース呼び出しやページレンダリングなしで、迅速に 200 を返すようにしてください。データベースが遅いと、クラスターがアプリが停止していると誤認識する可能性があります。 DATABASE_URLはクラスターから提供されます。secrets.envに決して入れないでください(本物の値を上書きしてしまいます)。また、イメージビルド時に設定しないでください。- ランタイム vs ビルド時。
secrets.envはランタイムのみでアプリに到達します。イメージは GitHub Actions でsecrets.envなしでビルドされます。ビルド時にフロントエンドにインライン化されるもの(VITE_*、NEXT_PUBLIC_*、REACT_APP_*)はsecrets.envから取得できません。そのような値はサーバー側でランタイムに読み取り、ページに渡すか、または(シークレットでない場合は)コード内にコミットしてください。 - アプリが自身で生成するシークレット(認証/セッションシークレット、暗号化ソルト、プッシュキーなど)が存在しない場合:
secrets.envに設定してください。そうしないと、再起動のたびに新しいものが生成され、ユーザーがログアウトされたり、プッシュサブスクリプションが壊れたりします。 - マイグレーションは古いバージョンに対しても安全である必要があります。 約1分間、両方のバージョンが新しいスキーマに対して実行されます。カラムとテーブルの追加は自由に行ってください。リネームや削除は2回のデプロイに分けて行ってください。最初に使用をやめ、その後削除します。詳細は
references/database.mdを参照してください。
環境変数とシークレット
すべてのランタイム設定は <deploy folder>/secrets.env にあり、sops で暗号化されてコミットされています。値のみが暗号化され、キー名は読み取り可能のままです。変更するには sops 自体を使用してください。コミットする可能性のあるファイルに復号化しないでください。また、シークレット値をチャットやログに出力しないでください。
sops set deploy-data-clerk/secrets.env '["STRIPE_SECRET_KEY"]' '"sk_live_..."'
sops unset deploy-data-clerk/secrets.env '["OLD_KEY"]'
sops decrypt deploy-data-clerk/secrets.env | cut -d= -f1
その後、コミットして main にプッシュすれば、約5分で反映されます。ユーザーが値を提供する必要がある場合(ダッシュボードからの API キーなど)、ユーザー自身に sops set 行を実行してもらうか、値のみを自分のターミナルに貼り付けてもらってください。完全なガイド(キー、保存場所、ローテーション、注意点)は references/secrets.md にあります。
データベース
Postgres 18、オペレーターによって管理されます。アプリは DATABASE_URL 経由で独自のデータベースとユーザーを取得します。スキーマ変更はデプロイ時に自動的に適用されるマイグレーションファイルです(references/database.md)。
バックアップ: 毎日 03:00 UTC に完全バックアップ、さらにすべての変更の継続的なログが保存され、Google Cloud Storage にオフサイト保存されます。オペレーターはデータベースを過去7日間の任意の時点に復元できます。そのため、データが削除されたり、マイグレーションが失敗したりしても、慌てずに手動で修正しようとしないでください。発生した時刻をメモし、オペレーターに復元を依頼してください(テンプレートは references/troubleshooting.md にあります)。復元はデータベース全体を巻き戻すため、その時点以降の変更は失われます。
コードが必要とするかもしれないネットワーク情報
- トラフィック経路:訪問者 → Cloudflare → Traefik(クラスターイングレス)→ アプリ。HTTPS 証明書は自動です。アプリ自体は
$PORTでプレーン HTTP を話します。X-Forwarded-Proto: httpsは元のリクエストが HTTPS であったことを示します。プロキシヘッダーを信頼し、アプリ内で HTTPS にリダイレクトしないでください(ループします)。 - 実際の訪問者 IP:
CF-Connecting-IPヘッダーを読んでください。X-Forwarded-Forには Cloudflare のアドレスが含まれているため、これでレート制限を行うとすべての訪問者が同じバケットに入ります。 - Traefik は以下のヘッダーを追加します:HSTS(2年、プリロード)、
X-Content-Type-Options: nosniff、X-Frame-Options: SAMEORIGIN(サイトは他のドメインの iframe に埋め込めません)。追加のヘッダー(CSP、SharedArrayBuffer用の COOP/COEP、iframe 許可)は、リクエストに応じてオペレーターが設定します。 - イングレスはレスポンスを圧縮しません。Cloudflare が一般的なテキストタイプを圧縮します。完全に制御するには、アプリ内で圧縮するか、事前圧縮されたアセットを配信してください。
- 長時間接続(SSE、websocket)は問題ありませんが、Cloudflare は約100秒間アイドル状態の接続を切断します。約30秒ごとにハートビートを送り、クライアント側で再接続してください。
- アウトバウンド: アプリは任意のパブリックインターネットエンドポイントに任意のポートでアクセスできます。LLM API、Stripe、メール、S3、マネージドデータベースや Redis(Neon、Supabase、Atlas、Upstash)をパブリックエンドポイント経由で利用できます。プライベートネットワーク(VPC ピアリング、PrivateLink、プライベート IP)やクラスター上の他のプロジェクトにはアクセスできません。インバウンドトラフィックは公開 URL 経由でのみ来ます。
- サードパーティサービス: そのキーと URL を
secrets.envに保存してください。サービスが IP 許可リストを必要とする場合、クラスターには1つの静的アウトバウンド IP があります。オペレーターに問い合わせてください(公開されていません)。また、クラスター上の他のプロジェクトと共有されていることをユーザーに伝えてください。サーバーは米国中部にあります。そのため、外部データベースには米国中部/東部リージョンを推奨します(EU データベースはクエリごとに約 100 ms 追加されます)。外部データベースはユーザー自身のものであり、Data Clerk のバックアップ対象外です。LLM 呼び出しが遅い場合は、レスポンスをストリーミングするか、バックグラウンドジョブとして実行してください。約 100 秒以上待機するブラウザリクエストは切断されます。 - リソースには上限があります(PROJECT.md のメモリ/CPU)。メモリ制限を超えるとアプリが強制終了され、再起動されます。その場合は、コードで対処しようとせず、オペレーターにより多くのリソースを依頼してください。
- アプリのコピーは1つ実行されます(レプリカ1)。デプロイをまたいでインメモリ状態が保持されることを前提にせず、セッションはデータベースまたは署名付き Cookie に保存してください。
オペレーターのみが行えること
ユーザーはクラスターにアクセスできません。これは設計上の意図です。以下のような場合には、簡潔なリクエストをオペレーターに送ってください(テンプレートは references/troubleshooting.md にあります):
新しいドメインまたはサブドメイン · メモリ/CPU 増量 · ファイル/オブジェクトストレージ · データベース復元 · アプログまたはクラッシュ原因 · セキュリティヘッダー変更 · マイグレーションコマンド、開始コマンド、ポート、ヘルスパスの変更 · スケジュールジョブ(cron) · 追加サービス(Redis、キュー) · 同一プロジェクト内の2つ目のアプリ · 新しいリポジトリのオンボーディング。
詳細情報
references/stacks.md:任意の言語向けの普遍的な契約;フルスタック vs SPA + API vs 静的;Node、Python FastAPI、Go およびその他のスタック。references/new-project.md:リポジトリのオンボーディング(追加するファイル、オペレーターに依頼すること、スタックごとの Dockerfile)。references/secrets.md:sops の詳細、キーファイル、ローテーション、ビルド時変数。references/database.md:マイグレーション、接続文字列、バックアップ、データ修正。references/setup-tools.md:macOS、Linux、Windows に sops/git/gh を安全にインストールする手順。scripts/install-tools.shまたはscripts/install-tools.ps1を実行してください。references/troubleshooting.md:「変更が反映されない」「サイトがダウンしている」、よくあるエラー、オペレーターリクエストテンプレート。assets/:Dockerfile テンプレート(Node、Python、Go)、デプロイワークフロー、kustomization.yaml、.sops.yaml、.gitattributes、PROJECT.mdのテンプレート。