#インフラ#デプロイ#技術解説Cloudflare WorkersGitHub ActionsD1CI/CDDNSNext.js
はじめに -- この記事の目的
toniolab.comを公開した。
「コードを書いて、ネットで見れるようにする」
たったこれだけのことに丸2日かかった。
なぜか。コードを書く と ネットで見れるようにする は、全く別のスキルだから。
プログラミングの解説は無限にある。でも「書いたコードをどうやってインターネットに出すのか」を体系的に解説してる記事は意外と少ない。
この記事は、toniolab.comのデプロイ作業を通じて学んだことを、初心者向けに整理したもの。自分のための勉強ノートでもある。
第1章 -- デプロイとは何か
「ローカル」と「本番」
コードを書いているとき、ブラウザで http://localhost:3000 にアクセスして動作確認する。これはローカル環境。自分のPCの中だけで動いている。
この状態では他の誰もアクセスできない。
デプロイとは、このローカルで動いているアプリケーションを、インターネット上のサーバーに配置して、世界中の誰でもアクセスできるようにすること。
デプロイに必要な3つの要素
- コード -- 動くアプリケーション(Next.js、React等)
- サーバー -- コードを実行する場所(Vercel、Cloudflare、AWS等)
- ドメイン -- アクセスするためのURL(toniolab.com等)
この3つを繋ぐ作業がデプロイ。
第2章 -- サーバーの選択肢
Vercel -- 最も簡単
iwasaki-naisou.comはVercelで動いている。
Vercelの特徴:
- GitHubにプッシュするだけで自動デプロイ
- Next.jsの開発元なので相性が完璧
- 設定ほぼゼロ
- 無料枠が大きい
欠点: Cloudflare D1のようなエッジデータベースとの統合が面倒。
Cloudflare -- 速いが複雑
toniolab.comはCloudflareで動いている。
Cloudflareの特徴:
- 世界300以上のエッジロケーション
- D1データベースがネイティブに使える
- Workerとして動くのでレスポンスが速い
欠点: 設定が多い。Next.jsを動かすのに変換ツールが必要。
重要な違い
Vercelは「そのまま動く」。Cloudflareは「変換して動かす」。
Next.jsはもともとNode.jsサーバーで動くように作られている。Cloudflare Workersは独自のランタイム(V8 isolate)で動く。環境が違う。
だから
@opennextjs/cloudflare という変換ツールが必要。これがNext.jsのコードをCloudflare Workerで動く形に変換する。第3章 -- Cloudflare Workers vs Pages
Cloudflareには2つのデプロイ方式がある。初見では違いがわからない。
Pages -- 静的ファイル配信
HTMLやCSS、JavaScriptの静的ファイルを配信する。SPAやSSG(Static Site Generation)向け。
イメージ: ファイルを置く棚。置いたものがそのまま配られる。
Workers -- サーバーサイド実行
コードがリクエストごとに実行される。SSR(Server-Side Rendering)やAPI処理ができる。
イメージ: 注文を受けて料理を作る厨房。リクエストに応じて動的にレスポンスを生成する。
toniolab.comがWorkersを使う理由
Next.jsはSSRが必要。ページの表示時にサーバーでHTMLを組み立てる処理がある。API(/api/user-phrases等)もサーバーで実行される。
Pagesでは静的ファイルしか配信できないので、SSRやAPIが動かない。
最初はPagesでデプロイしようとして失敗した。 ページは表示されたがAPIが404を返した。WorkersにSSRワーカーがいなかったから。
wrangler.toml -- Workers設定ファイル
name = "toniolab" main = ".open-next/worker.js" compatibility_date = "2024-11-27" compatibility_flags = ["nodejs_compat"] [assets] directory = ".open-next/assets" [[d1_databases]] binding = "DB" database_name = "iwasaki-phrases" database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
各行の意味:
- name: Worker名。Cloudflareダッシュボードに表示される
- main: 実行されるJavaScriptファイル。opennextjsが生成する
- compatibility_flags: Node.jsのAPIを使えるようにするフラグ
- [assets]: 静的ファイル(CSS、画像等)の置き場所
- [[d1_databases]]: D1データベースの接続設定
第4章 -- CI/CD -- 自動デプロイの仕組み
CI/CDとは
CI = Continuous Integration(継続的インテグレーション)
CD = Continuous Deployment(継続的デプロイ)
簡単に言うと: コードをプッシュしたら自動でビルドしてデプロイする仕組み。
手動でやるとこうなる:
- コードを書く
npm run buildでビルド- ビルド結果をサーバーにアップロード
- サーバーを再起動
CI/CDがあると:
- コードを書く
git pushする- 以上。あとは自動。
GitHub Actions
GitHubが提供するCI/CDサービス。リポジトリに
.github/workflows/ ディレクトリを作り、YAMLファイルを置くだけで使える。name: Deploy to Cloudflare on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci - run: npx @opennextjs/cloudflare build - run: npx @opennextjs/cloudflare deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
上から順に読む:
- on: push: branches: [main] -- mainブランチにプッシュされたら実行
- runs-on: ubuntu-latest -- GitHubのLinuxサーバーで実行
- actions/checkout@v4 -- リポジトリのコードをダウンロード
- actions/setup-node@v4 -- Node.js 22をインストール
- npm ci -- パッケージをインストール
- opennextjs/cloudflare build -- Next.jsをCloudflare用にビルド
- opennextjs/cloudflare deploy -- Cloudflareにデプロイ
env にある
secrets.CLOUDFLARE_API_TOKEN は、GitHub Settingsで設定する秘密の値。コードに直接書くとセキュリティリスクになるため。なぜWindowsではなくGitHub Actionsか
opennextjs-cloudflareのビルドツールはLinux前提で作られている。Windowsでは動かない。
GitHub Actionsは
ubuntu-latest(Linux)で動くので、Windowsの開発マシンからでもLinux上でビルド・デプロイできる。これがCI/CDの大きなメリットの一つ: 開発環境とデプロイ環境の違いを吸収できる。
第5章 -- D1データベース
D1とは
CloudflareのエッジSQLデータベース。SQLiteベースで、Workerから直接アクセスできる。
普通のWebアプリ: アプリ → インターネット → データベースサーバー
CloudflareのD1: アプリ(Worker) → 同じエッジロケーションのD1
データベースが物理的に近い場所にあるのでレスポンスが速い。
アクセス方法: バインディング vs REST API
バインディング(直接接続):
WorkerのコードからD1に直接アクセス。最速。ただしWorker内部からしか使えない。
REST API(HTTP経由):
どこからでもHTTPリクエストでD1にアクセス。APIトークンが必要。
toniolab.comはREST APIを使っている。理由: 元々Vercel(iwasaki-naisou.com)からもアクセスする設計だったため。
Worker Secrets -- 秘密情報の管理
データベースにアクセスするにはAPIトークンが必要。これをコードに直接書いてはいけない。GitHubに公開されてしまう。
Worker Secret: Workerの環境変数として安全に保存する仕組み。
echo "YOUR_TOKEN" | npx wrangler secret put CLOUDFLARE_API_TOKEN
コード内では
process.env.CLOUDFLARE_API_TOKEN で参照する。APIトークンの権限
Cloudflare APIトークンには細かい権限設定がある。
今回の失敗: 最初に作ったトークンに Workers の権限しかなく、D1 の権限がなかった。
結果: Workerは動くがデータベースにアクセスできない。APIが「account not authorized」エラーを返す。
教訓: トークン作成時に必要な権限を全て付与する。足りない権限は後から追加できない。新しいトークンを作り直す必要がある。
第6章 -- Workerサイズ制限
無料プランの壁: 3 MiB
Cloudflare Workersの無料プランでは、Workerの圧縮後サイズが 3 MiB(約3.07 MB) に制限されている。
有料プラン($5/月)では 10 MiB まで。
なぜサイズが大きくなるのか
Next.jsアプリをWorkerにすると、全ページのSSRコードが1つの
handler.mjs ファイルにバンドルされる。ページが多い = バンドルが大きい = 制限に引っかかる。
最初のデプロイ: gzip 3,471 KiB → 制限超え
不要ファイル削除後: gzip 3,160 KiB → まだ超え
さらに削除後: gzip 2,966 KiB → 制限内
何を削ったか
- 世界地図ページ6個: 大きなTopoJSONデータ(739KB)を含む
- 業務用コンポーネント170個: 請求書、工程表、顧客管理等。英語学習に不要
- 未使用データファイル40個: 料理日記、健康ジャーナル等
- プロトタイプページ13個: 古いダッシュボード、レビュー機能等
削除の判断基準: ページから import されていないコンポーネント・データは全てバンドルから除外できる。grepで依存関係を確認してから削除する。
重要な教訓
サイズ制限は無料プランの宿命。対策:
- 不要なコードを入れない: 使わないページ・コンポーネントは削除
- 大きなデータファイルに注意: JSONの地図データ等は特に重い
- 有料プランの検討: $5/月で10 MiBまで。3 MiBがきつい場合は現実的
- バンドル分析: どのファイルが大きいかを確認してから最適化する
第7章 -- DNS とカスタムドメイン
ドメインとは
toniolab.com はドメイン名。人間が覚えやすいWebサイトの住所。
実際のサーバーはIPアドレス(例: 104.21.23.45)で特定される。ドメイン名をIPアドレスに変換するのが DNS(Domain Name System)。
ドメインの設定手順
- ドメイン購入: Cloudflare Registrar等で取得(年$10程度)
- DNSレコード設定: ドメインがどのサーバーを指すか設定
- Workers側の設定: このドメインのリクエストを受け付けるよう設定
Cloudflareでは、Workers設定画面の「Custom Domains」からドメインを追加する。DNS設定が自動で行われる。
作業の流れ
toniolab.comの場合:
- Cloudflare Registrarでドメイン取得済み
- Workers設定 → Routes → Custom Domains → toniolab.com を追加
- SSL証明書が自動発行
- https://toniolab.com でアクセス可能に
第8章 -- トラブルシューティング実録
今回実際に踏んだエラーとその解決策。
エラー1: Pages デプロイで404
症状: ページは表示されるがAPIが404
原因: PagesモードではSSRワーカーがデプロイされない
解決: PagesからWorkersに切り替え
エラー2: GitHub push が拒否される
症状:
.github/workflows/ を含むプッシュが rejected
原因: GitHubのPersonal Access Tokenに workflow スコープがない
解決: GitHubの Settings → Developer settings → Personal access tokens で workflow スコープを追加エラー3: D1が空のデータを返す
症状: APIは200を返すがフレーズ数が0
原因: Worker SecretにCLOUDFLARE_API_TOKENが設定されていない
解決:
wrangler secret put で設定エラー4: D1アクセスが「account not authorized」
症状: APIが認証エラー
原因: APIトークンにD1の権限がない(Workersの権限のみ)
解決: D1 Edit権限付きの新しいトークンを作成
エラー5: Worker サイズ超過
症状: デプロイ時に「exceeded size limit of 3 MiB」
原因: 全ページが1つのバンドルにまとまり、圧縮後3 MiB超え
解決: 不要なページ・コンポーネント・データを削除して2,966 KiBまで圧縮
エラー6: TypeScript型エラーでビルド失敗
症状:
declare global の Window 拡張が conflict
原因: 複数ファイルで同じプロパティのoptional修飾子が不一致(YG: vs YG?:)
解決: next.config.ts に ignoreBuildErrors: true を追加(iwasaki側と同じ設定)第9章 -- 全体像の整理
デプロイパイプラインの流れ
ローカルでコードを編集
↓
git push origin main
↓
GitHub Actions が起動(ubuntu-latest)
↓
npm ci(パッケージインストール)
↓
opennextjs/cloudflare build(Next.js→Worker変換)
↓
opennextjs/cloudflare deploy(Cloudflareにアップロード)
↓
Worker更新 → toniolab.com に反映
関係する技術の地図
- Next.js: アプリケーションフレームワーク
- opennextjs-cloudflare: Next.js→Cloudflare変換ツール
- Cloudflare Workers: サーバーレス実行環境
- Cloudflare D1: エッジSQLデータベース
- GitHub Actions: CI/CDパイプライン
- GitHub Secrets: 秘密情報の安全な保管
- Worker Secrets: ランタイムの環境変数
- DNS: ドメインとサーバーの紐付け
- wrangler: Cloudflareの管理CLI
覚えておくべき数字
| 項目 | 値 |
|------|-----|
| Worker無料サイズ上限 | 3 MiB(gzip後) |
| Worker有料サイズ上限 | 10 MiB(gzip後) |
| Workers有料プラン | $5/月 |
| GitHub Actions無料枠 | 2,000分/月 |
| D1無料枠 | 5 GB ストレージ |
| ビルド時間(目安) | 約40秒 |
| デプロイ時間(目安) | 約15秒 |
おわりに
Vercelなら
git push だけで済む作業に、Cloudflareでは2日かかった。でも2日で学んだこと:
- Workers/Pagesの違い
- CI/CDの仕組み
- データベースの認証と権限
- バンドルサイズの最適化
- DNSとドメインの設定
Vercelの「何もしなくても動く」は魔法じゃない。裏で同じことが自動化されてるだけ。
自分でやると面倒。でも何が起きてるか全部わかる。
面倒なことを一度やっておくと、次から何が壊れても直せる。
これがインフラを理解するということ。
AI生成コンテンツについて
この記事は、AI(Claude、ChatGPT等)によって生成されたコンテンツです。 経営者とAIの実際の対話を元に作成していますが、技術的な内容には誤りが含まれる可能性があります。
重要な決定をされる際は、専門家にご相談されることをお勧めします。 また、記事の内容について疑問がある場合は、お気軽にお問い合わせください。