push → edge
GitOps Deployment Pipeline

コードを push する。
数十秒後、世界に出る。

GitHub と Cloudflare Workers をつなぐ初期設定ガイド。一度組めば、あとは git push するだけで、自動ビルド・デプロイが走り、独自ドメインには常に最新版が映ります。

Deploy pipeline
STAGE 01
LOCAL
コード編集
STAGE 02
GITHUB
git push
STAGE 03
CLOUDFLARE
build & deploy
STAGE 04
DOMAIN
独自ドメインで公開

What you get

この構成でできること

接続方式は2通りありますが、設定が最も簡単な Workers Builds(Cloudflare 純正の Git 連携) を推奨構成として解説します。API トークンの管理が不要で、ダッシュボード操作だけで完結します。

01

push が唯一のトリガー

本番ブランチへの push を検知して自動でビルド・デプロイ。手動のデプロイ作業がなくなります。

02

独自ドメインに自動反映

ドメインは常に最新の本番デプロイを指すため、ビルド完了後そのまま反映されます。

03

GitHub で状態確認

デプロイの成否はコミット横のチェックに表示。画面を離れずに監視できます。

Architecture

構成図

開発から公開、そしてユーザーのリクエスト処理までの全体像です。更新は上から下へ(push → 自動ビルド → Worker → 公開)流れ、ユーザーのアクセスは独自ドメイン経由で Worker が処理し、D1 を読み書きします。

開発者 ローカル または GitHub Web UI git push GitHub リポジトリ ソースコードを保管 自動ビルド(Workers Builds) CLOUDFLARE(エッジ) Worker リクエストを処理し D1 等へアクセス binding D1 データベース Secrets 秘密値 静的アセット HTML / CSS / JS 独自ドメインで公開 独自ドメイン 常に最新を公開 ブラウザでアクセス ユーザー リクエストは Worker が処理
更新(push) 自動ビルド 公開・アクセス バインディング(D1 / Secrets / Assets)

Prerequisites

前提条件

項目内容
GitHub アカウントリポジトリを作成できること
Cloudflare アカウント無料プランで可
独自ドメインCloudflare の DNS(ゾーン)配下にあること。 ネームサーバーを Cloudflare に向けて移管済みである必要があります
Node.jsLTS 版を推奨。node -v で確認
Gitgit --version で確認
*.workers.dev のサブドメインだけで試す場合、独自ドメインの前提は不要です。

Language & Runtime

開発言語・ランタイム

Worker は Node.js サーバーではなく、Cloudflare 独自の V8 ベースのエッジランタイム(workerd) 上で動きます。書く言語は JavaScript / TypeScript が標準で、C3 の雛形も既定で TypeScript を選べます。前提条件の Node.js は、ローカルでのビルドやツール(npm・wrangler)実行のためのものであって、本番でコードを動かす実行環境ではありません。

標準 · JS / TS

JavaScript / TypeScript

最も情報が多く、まず選ぶ言語。src/index.ts にリクエストハンドラを書く。型の付く TypeScript を推奨。

ベータ · PY

Python

Workers の Python 対応。src/entry.py を起点に、Python で Worker を記述できる(機能は発展途上)。

WASM · RS

Rust / WebAssembly

workers-rs 経由の Rust など、WebAssembly にコンパイルできる言語も動かせる。

Node.js 互換:多くの npm パッケージや一部の Node.js API は、wrangler.jsonccompatibility_flagsnodejs_compat を加えると利用できます。ただし Node.js の全 API が使えるわけではない点に注意してください。

Setup · 6 steps

構築手順

上から順に進めれば、push するだけで本番反映される状態が完成します。

ローカル環境が無くても進められます。 ビルドは Cloudflare 側(Workers Builds)で走るため、端末に Node.js は必須ではありません。
ローカルがある場合:下の手順01から C3 で雛形を作るのが最短です。
ローカルが無い場合:手順01〜02を飛ばし、GitHub の Web UI でリポジトリとファイルを作成→ 手順03でダッシュボード接続、という流れでブラウザだけで完結できます。ただし静的サイトと Worker で wrangler.jsonc が少し違い、ここを外すとデプロイが失敗します——すぐ下の「ローカル無しの2つの型」を必ず確認してください。
⚠ ローカル無しでハマる定番エラー:
✘ [ERROR] The entry-point file at "src/index.ts" was not found.
原因: wrangler.jsonc"main": "src/index.ts" があるのに、その src/index.ts が存在しないため。C3(手順01)ならこのファイルは自動生成されますが、GitHub の Web UI で手動作成した場合は、自分で用意しない限り存在しませんnpx wrangler deploy は「入口(エントリーポイント)」を探して失敗します。用途に応じて次の A / B のどちらかで解決します。
型A:静的サイトだけを配信する(Worker コード不要/このライブラリもこの形)
wrangler.jsonc から main の行を削除し、assets だけにします。エントリーポイントが要求されず、静的アセット配信としてそのままデプロイできます。HTML/CSS/JS を置くだけのサイト(当ドキュメントライブラリなど)はこれで十分。
wrangler.jsonc(静的サイト用・main なし)
{
  "name": "your-app",
  "compatibility_date": "YYYY-MM-DD",
  "assets": { "directory": "./public" }  // 静的ファイルの置き場所(ビルドで生成するなら dist 等)
}
型Aのビルド設定:Deploy command は npx wrangler deploy のままでOK(main が無いのでアセットのみ配信)。Build command は、ビルドで静的ファイルを生成するなら設定(例 node build.mjs/出力先を assets.directory に合わせる)。ビルド不要でリポジトリに直接 HTML を置くなら空欄でも可(その場合 assets.directory をその置き場所=例 ./public に向ける)。
型B:Worker コードが必要(D1 などバックエンド処理あり)
main は残し、GitHub の Web UI で src/index.ts も必ず作成します(Add file → Create new file で、ファイル名に src/index.ts と入力するとフォルダごと作れます)。中身は後述の「D1 サンプル」の src/index.ts をそのまま使えます。この型では「wrangler.jsonc の main」と「実在する src/index.ts」がセットで必要——片方だけだと今回のエラーになります。
01

ローカルで Worker プロジェクトを作成

Cloudflare 公式のスキャフォールドツール(C3)で雛形を生成します。対話プロンプトでテンプレートと TypeScript の利用有無を選ぶと、設定ファイル wrangler.jsonc を含むプロジェクトが作られます。

bash
npm create cloudflare@latest your-app
cd your-app

静的ファイル(HTML/CSS/JS)も配信する場合は、アセット用ディレクトリを指定します。

wrangler.jsonc
{
  "name": "your-app",
  "main": "src/index.ts",  // Workerコードの入口。静的サイトのみなら main 行は不要(上の型A参照)
  "compatibility_date": "YYYY-MM-DD",  // 作成日を入れる
  "assets": { "directory": "./public" }
}

ローカル確認は npx wrangler dev で行えます。

02

Git を初期化し、GitHub へ push

GitHub 側で空のリポジトリを1つ作成しておきます。

bash
git init
git add -A
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-account/your-repo.git
git push -u origin main
重要: 機密値(API キー・パスワード等)や .env / .dev.vars をコミットしないこと。.gitignore.dev.vars*.env* を追加しておきます。
03

Cloudflare と GitHub を連携する

Cloudflare ダッシュボードで Workers & PagesCreate applicationImport a repository の順に進み、Git アカウントを選択します。初回は GitHub アプリ「Cloudflare Workers and Pages」の認可を求められます。続いてデプロイ対象のリポジトリを選択します。

セキュリティ: 認可時は「Only select repositories」を選び、ビルド対象のリポジトリだけにアクセスを限定します。全リポジトリへの許可は避けてください。

設定ファイルが無いリポジトリを接続した場合、Cloudflare がフレームワークを自動検出し、設定を追加する Pull Request を自動作成します。C3 で雛形を作っていれば設定済みのため不要です。

04

ビルド / デプロイ設定

接続時の設定画面で以下を指定します。

設定項目値の例備考
Production branchmainこのブランチへの push がトリガー
Build commandnpm run buildビルド不要なら空欄でも可
Deploy commandnpx wrangler deploy既定値のまま使えることが多い

Save and Deploy を選択すると、初回ビルドとデプロイが走ります。

05

初回デプロイを確認

完了すると https://your-app.<your-subdomain>.workers.dev の URL が払い出されます。ブラウザでアクセスして動作を確認します。ビルドログは Deployments タブ最下部の View build history から見られます。

06

独自ドメインを割り当てる

「独自ドメインで即確認」の核心です。対象ドメインが Cloudflare のゾーン配下にあることが前提です。対象の Worker を開き、Settings → Domains & Routes → Add → Custom Domain から使用するホスト名(例:app.example.com)を入力して保存します。

Cloudflare が必要な DNS レコードと TLS 証明書を自動で発行・設定します。以降、このドメインは常に最新の本番デプロイを指すため、push → ビルド完了 → 自動反映のループが完成します。

初回アクセスで DNS エラーが出る場合は、伝播待ち(数分)か、別端末・別回線で再確認してください。

Daily flow

日常の運用フロー

構築後は、これだけで本番が更新されます。デプロイの成否は GitHub のコミット横のチェックから確認できます。

— terminal —
# ローカルでコードを編集
$ git add -A
$ git commit -m "Update layout"
$ git push
# → 数十秒〜数分後、独自ドメインに自動反映

Operate & Recover

ロールバックと観測

「壊れてもすぐ戻せる」「何が起きているか見える」の2つが揃うと、push が怖くなくなります。GitOps 運用の安心材料として最初に押さえておきたい部分です。

壊れたら:即時ロールバック

デプロイは世代管理されており、以前の正常なバージョンへ数秒で切り戻せますgit revert を push してビルド完了を待つより速いので、「まず戻す → 落ち着いて原因調査」が定石です。

bash
npx wrangler rollback
# または:ダッシュボード → 対象 Worker → Deployments
# → 戻したいデプロイの「…」→ Rollback
ロールバックで戻るのはコードだけ。 D1 など、バインディング先のデータは巻き戻りません。スキーマ変更を伴う更新は「列やテーブルの削除を急がない」など、旧コードでも動く後方互換を保っておくと安全に戻せます。

ビルドの失敗は本番を壊さない

Workers Builds では、ビルドが失敗しても本番は「最後に成功したデプロイ」を配信し続けます。エラー画面に変わることはありません。裏を返すと、「push したのに本番が変わらない」ときの最有力容疑者はビルド失敗です。対象 Worker の Deployments → View build history でログを確認してください。

観測:ログとメトリクス

開発中の「本番で何が起きているか分からない」を避けるために、次の2つを用意しておきます。

手段使い方向いている場面
リアルタイムログnpx wrangler tail で本番の console.log や例外をターミナルへストリーム表示いま起きている問題の調査
Workers Logs(保存ログ)wrangler.jsonc"observability": { "enabled": true } を追加すると、ダッシュボードでログの検索・集計が可能に過去にさかのぼる調査・エラー率の把握
メトリクスダッシュボードの Worker 概要(リクエスト数・エラー・CPU 時間)傾向の監視・無料枠の消費確認

Optional

環境変数・Secrets・データベース

Worker に値を渡す3つの方法

種類中身Git に載るか用途
vars(変数)平文の設定値載るAPI ホスト名など、秘密でない設定
Secrets暗号化された秘密文字列載らないパスワード・API キー・外部 DB の接続文字列
BindingsCloudflare リソースへの参照参照情報は載るD1・KV・R2 などへの接続

機密値はコードや設定ファイルに書かず、Secrets として登録します。コードからは環境変数として読めます。ローカル開発用の値は .dev.vars に記述し、必ず Git 管理から除外します。

bash
npx wrangler secret put SECRET_NAME
# → 値の入力を求められる。値はリポジトリに残らない

データベース(D1)を使う

リレーショナル DB が必要なら、Cloudflare 純正の D1(サーバーレス SQLite)が最も手軽です。DB は Secrets ではなく バインディングで接続するため、パスワード管理は不要です。

bash
npx wrangler d1 create your-db

出力された database_idwrangler.jsonc に追記します(ID は秘密情報ではないため Git に載せて問題ありません)。

wrangler.jsonc
{
  "d1_databases": [
    { "binding": "DB", "database_name": "your-db", "database_id": "..." }
  ]
}
再デプロイで DB の中身は消えません。 push で入れ替わるのは Worker のコードだけで、バインディング先のデータは保持されます。
コストの注意点: D1 は「読み取り行数=スキャンした行数」で課金されます。無料枠(目安:5GB/読み取り500万行・書き込み10万行 per day)の範囲なら小規模アプリは無料ですが、インデックスのないクエリで全件スキャンが多発するとコストが膨らみます。頻出クエリには必ずインデックスを張ってください。

D1 以外の選択肢(バインディング/トリガー早見表)

データの形やアクセスパターンによっては、D1 より適したリソースがあります。いずれも接続方法は同じ「バインディング」方式(+Cron はトリガー設定)で、wrangler.jsonc に書いて push すれば有効になります。

リソース何に使う特徴・向いている場面
D1リレーショナル DB(SQLite)正規化されたデータ・SQL で集計したいとき。まず第一候補
KVキー・バリューストア設定値・キャッシュ・セッション等。読み取りが速く世界中に複製される。書き込み反映は結果整合(数十秒の遅延あり得る)
R2オブジェクトストレージ(S3 互換)画像・動画・大きなファイル。下り転送料(egress)が無料なのが最大の強み
Durable Objects強整合な状態+WebSocketチャット・共同編集・カウンタ等、「1つの実体に順番に処理させたい」場面
Queues非同期ジョブキュー重い処理を後回しにして、リクエストへは即応答したいとき
Cron Triggers定期実行"triggers": { "crons": ["0 3 * * *"] } のように書くと、指定時刻に Worker の scheduled ハンドラが走る。バッチ・定期チェックに

Hands-on · D1 sample

サンプル:D1 で動く最小アプリを公開する

アクセスカウンターを例に、D1 を使う Worker を push だけで公開するところまで通します。テーブル作成もコード内で行うので、ローカル環境が無くてもブラウザ操作だけで完結できます。

結論:D1 を使う場合でも、ローカル環境なし(ブラウザだけ)で完結できます。 全体像はこう:
D1 データベース=ダッシュボードで作成(Storage & Databases → D1 → Create)→ database_id を控える
wrangler.jsonc と src/index.ts=GitHub の Web UI で作成(前章の型Bmain と実在する src/index.ts はセット)
テーブル=コード内の CREATE TABLE IF NOT EXISTS で自動作成、または ダッシュボードの D1 → Console に SQL を貼って実行
デプロイ=push すれば Workers Builds がクラウドでビルド&デプロイwrangler d1 createwrangler deploy を端末で打つ必要はない)
端末に Node.js も wrangler も不要。CLI を使う手順は「ローカルがある人向けの近道」にすぎません。
1

D1 データベースを作る

CLI でもダッシュボードでも作れます。出力(または詳細画面)の database_id を控えます。

bash(ローカルがある場合)
npx wrangler d1 create demo-db
ローカルが無い場合: ダッシュボードの Storage & Databases → D1 → Create から作成できます。
2

2つのファイルをリポジトリに置く

ローカルがあれば作成、無ければ GitHub の Web UI(Add file → Create new file) でそのまま作れます。database_id は手順1の値に置き換えます。

wrangler.jsonc
{
  "name": "d1-counter",
  "main": "src/index.ts",
  "compatibility_date": "2025-01-01",
  "d1_databases": [
    { "binding": "DB", "database_name": "demo-db", "database_id": "<手順1のID>" }
  ]
}
src/index.ts
export default {
  async fetch(request, env) {
    // 初回だけテーブルを用意(無ければ作る)
    await env.DB.prepare(
      "CREATE TABLE IF NOT EXISTS counter (id INTEGER PRIMARY KEY, hits INTEGER NOT NULL)"
    ).run();
    // アクセスのたびに +1(1行目が無ければ作る)
    await env.DB.prepare(
      "INSERT INTO counter (id, hits) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET hits = hits + 1"
    ).run();
    const row = await env.DB.prepare("SELECT hits FROM counter WHERE id = 1").first();
    return new Response(
      `<!doctype html><meta charset=utf-8><h1>訪問数: ${row.hits}</h1>`,
      { headers: { "content-type": "text/html; charset=utf-8" } }
    );
  }
};
"binding": "DB" の名前が、コードの env.DB と一致している必要があります。
3

push してデプロイ

変更をコミットして push します(GitHub Web UI なら「Commit changes」)。接続済みであれば Workers Builds がクラウドでビルドし、自動デプロイされます。端末でのビルドは不要です。

bash
git add -A && git commit -m "Add D1 counter" && git push
4

動作を確認

公開 URL(独自ドメイン、または *.workers.dev)にアクセスするたびに、D1 に保存されたカウントが増えていれば成功です。再デプロイしてもカウントは保持されます。

本番では: この例は手軽さ優先でテーブル作成をコード内に書いています。実運用ではスキーマを schema.sql にまとめ、ローカルがあれば npx wrangler d1 execute demo-db --remote --file=./schema.sqlローカル無しならダッシュボードの D1 → Console に SQL を貼って実行し、コードはクエリだけに集中させるのがおすすめです(どちらでも同じ本番DBに適用されます)。

Pricing

料金の目安

課金されるのは主に Worker(サーバーコード)が実行されたときです。静的アセットの配信や独自ドメイン・DNS・TLS は無料のため、静的サイトや小規模アプリなら ほぼ無料で運用できます。

プラン月額含まれる目安向き
Workers Free$0100,000 リクエスト/日、1 リクエストあたりの CPU 時間に上限個人・検証・小規模
Workers Paid$5〜1,000万リクエスト/月込み(超過は約 $0.30 / 100万)+ CPU 時間の枠本番・規模拡大
無料

静的アセット配信

HTML/CSS/JS など静的ファイルへのリクエストは無料・無制限。サーバーコードを実行しなければ課金対象になりません。

無料

ドメイン・DNS・TLS

Cloudflare ゾーン配下なら、独自ドメインの割り当て・DNS・TLS 証明書はいずれも無料です。

別枠

D1 / KV / R2

データベースやストレージは各サービスごとに無料枠があります(例:D1 は 5GB・読み取り500万行/日)。超過分のみ課金。

注意: 金額・無料枠は変更されることがあります。ここでの数値はあくまで目安です。運用前に必ず Cloudflare の公式料金ページで最新の値を確認してください。

Environments

ステージング環境の分け方

本番に影響を与えずに検証するには、本番(production)とステージング(staging)を分けます。手軽さ重視と分離重視で、代表的な2通りがあります。

方法A:ブランチのプレビューを使う(手軽)

Workers Builds は、本番ブランチ以外への push に対してプレビューデプロイを作成し、専用のプレビュー URL を払い出します。PR やお試しの確認に向き、追加設定はほぼ不要です。

環境ブランチURL用途
本番main独自ドメイン公開版
ステージングstaging などプレビュー URL本番反映前の検証
仕組み:本番ブランチ以外への push では、デプロイの代わりに既定で npx wrangler versions upload が実行され、本番とは別のプレビュー専用 URL が払い出されます(ビルド履歴やコミットのチェックから辿れます)。本番の独自ドメインには一切影響しません

方法B:wrangler の environments で分離(明確)

wrangler.jsonc に環境を定義すると、別名の Worker として独立してデプロイできます。名前・変数・バインディング・ドメイン・Secrets を環境ごとに分けられます。

wrangler.jsonc
{
  "name": "your-app",
  "main": "src/index.ts",

  "env": {
    "staging": {
      "name": "your-app-staging",
      "vars": { "ENVIRONMENT": "staging" }
    }
  }
}

デプロイ時に環境を指定します。

bash
npx wrangler deploy --env staging
# → your-app-staging として独立してデプロイされる
Secrets と DB も環境ごとに分ける: Secrets は npx wrangler secret put NAME --env staging で登録し、D1 などのデータベースも staging 用を別に作成してバインドします。こうすれば、検証で本番データを汚しません

Troubleshooting

動作確認とトラブルシュート

症状確認ポイント
push してもデプロイされないpush 先ブランチが Production branch と一致しているか
push したのに本番が変わらない(エラー画面も出ない)最有力はビルド失敗。失敗時は最後に成功したデプロイを配信し続けるため、見た目では気付けない。Deployments → View build history でログを確認
ビルドが失敗するDeployments → ビルドログでエラー内容を確認。ビルドコマンドが非ゼロ終了(テスト・チェックの失敗含む)していないか
ビルドの npm clean-install が失敗するpackage-lock.json をコミットしているか(Workers Builds はロックファイルを前提に依存を復元する)
ローカルと Node のバージョンが違うビルド設定の環境変数に NODE_VERSION(例:20)を追加するか、.nvmrc を置く
デプロイ成功なのに表示が古いブラウザキャッシュ。ハードリロード(Shift+再読み込み)や別端末で確認
独自ドメインで表示されないドメインが Cloudflare ゾーン配下か/DNS 伝播待ち/ドメインが意図した Worker に紐付いているか
Secrets が読めないwrangler secret put で登録済みか、名前が一致しているか。環境(--env)ごとに別登録が必要な点にも注意

Cheat sheet

wrangler CLI チートシート

日常運用は push だけで回りますが、調査・復旧・初期設定で使う wrangler コマンドをまとめておきます。すべて npx wrangler ... で実行できます(インストール不要)。

コマンド何をするか
npx wrangler devローカルで Worker を起動(http://localhost:8787)。D1 等はローカル用の疑似リソースが使われる
npx wrangler deploy手動で本番デプロイ(通常は push に任せるので出番は少ない)
npx wrangler versions uploadデプロイせずにプレビュー版をアップロードし、プレビュー URL を得る
npx wrangler rollback以前のデプロイへ即時切り戻し
npx wrangler tail本番のログ(console.log・例外)をリアルタイム表示
npx wrangler secret put NAMESecret を登録(--env staging で環境別)
npx wrangler d1 create NAMED1 データベースを作成
npx wrangler d1 execute DB --remote --file=schema.sql本番 D1 に SQL を適用(--remote を忘れるとローカルに当たる)
npx wrangler whoamiどのアカウントにログイン中か確認

Best practices

セキュリティのベストプラクティス

  • GitHub アプリのアクセス範囲は「Only select repositories」で対象リポジトリのみに限定する
  • 機密値(API キー・トークン・DB 認証情報)はソースコードや wrangler.jsonc に絶対に書かずwrangler secret put で登録する
  • .dev.vars / .env.gitignore に追加し、コミットしない
  • 本番・ステージング・開発で別々の値を使う場合は、環境(environments)ごとに Secrets を分離する

Appendix

代替方式:GitHub Actions を使う

CI 内でテストや Lint を挟みたい場合は、Workers Builds の代わりに GitHub Actions + 公式アクションでデプロイできます。この場合は Cloudflare の API トークンを GitHub Secrets に登録する必要があります。

.github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Deploy
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
API トークンはリポジトリに直書きせず、必ず GitHub の Secrets 機能に保存してください。トークンのスコープは、デプロイに必要な権限に限定して発行します。

まずは Workers Builds で運用を始め、CI に独自処理を足したくなった段階で Actions へ移行するのが無理のない流れです。