5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

今年はレガシーな構成で長く運用してきた Webサイト/LPサイト基盤を大きく見直し、新しい構成への移行を行いました。
コーポレートサイトや多くのLPをホストしている環境であり、これまでEC2上の Nginx + PHP(FastCGI)環境 に対して手作業でvhost設定を追加し、コンテンツ更新時にはFTP(FileZilla等)でファイルを作成・更新する、という運用が数年間続いていました。

本稿では、そのレガシー環境を Kamal2 + FrankenPHP + Caddy を用いたコンテナ基盤へ刷新した際の内容を紹介します。

※本稿は Qiita Advent Calendar「レガシーを保守/刷新した経験共有」7日目の記事です。

Before:レガシーな構成と課題

スクリーンショット 2025-11-29 2.01.44.png

まず、従来の構成は次のようなものでした。

  • EC2インスタンス上で Nginx + PHP(FastCGI) が稼働
  • サイト/LP 毎に VirtualHost(vhost) を追加(すべて手動)
  • 更新作業は FTP(FileZilla等)でファイルを直接アップロード・更新
  • Gitリポジトリは存在するものの、実際の運用とは乖離
    • FTPでコンテンツ更新するのは非エンジニアなため、Git操作はしてくれない
    • EC2上で日々変更された状態を、エンジニアが不定期でコミットしてpushしてコード保全していた(が、面倒であまりやっていなかった)
  • EC2にいつでもSSHできるようにしておく必要があるため、SSHポートが常時解放されていた

この環境では以下の点が大きな課題でした。

  • vhostの追加・変更が属人化し、設定全体の把握が困難
  • ロールバック手段がなく、変更に対する心理的負荷が高い
  • テスト環境もないため、ごく一部で使用しているPHP部分を安全にテストできない
  • EC2のOS/ミドルウェア管理やPHP等の保守が難しい
  • FTPによる直接更新に起因するセキュリティリスク

LPの数が増えるにつれ、手作業による運用では維持が難しくなっていました。

刷新を決めた理由

刷新の背景には、次のような要因がありました。

  1. LPの増加により手作業運用が限界に近づいていたこと
  2. セキュリティや更新性におけるリスクが増加していたこと
  3. EC2で使用しているOSイメージ(amazonlinux2)のサポートが終了したこと
  4. Kamal2・FrankenPHP・Caddy など、適した技術スタックが揃ったこと
  5. Route 53・WAF・CloudFront・ALB・IdentityCenter・InstanceConnect 周りでも、レガシーな構成を見直すべきアップデートがたくさん揃ってきていたこと

ネガティブな事情ももちろん多いですが、技術スタックが揃ってきたというポジティブな事情もあったため、いい機会かと思いました。

After:刷新後の構成

刷新後の構成は以下の通りです。

EC2・コンテナ

スクリーンショット 2025-11-29 2.19.01.png

  • サイト群はコンテナ化してデプロイ
  • デプロイには Kamal2
    • Kamal Proxyにより安全にローリングデプロイ
  • PHP ランタイムには FrankenPHP
  • Web サーバーには Caddy
  • メールのリレー用に msmtp
  • GitHub Actions を利用した Git ベースの CI/CD に統一
  • サイト更新にはAIを活用できるような構成

インフラ

スクリーンショット 2025-11-29 2.16.27.png

  • Route 53 -> CloudFront/WAF -> VPC Origins -> EC2 -> Kamal Proxy -> Caddy
    • オリジンを隠蔽できるモダンな構成
    • ALBを廃止し料金も節約
  • エッジ証明書(CloudFront)とオリジン証明書(Kamal Proxy)
  • IdentityCenterのログインと多要素認証による安全なEC2への接続
    • SSHのポートは開けていない
  • ひととおり手作業で作ってからCloudFormationに取り込んでIaC化

採用ツールと選定理由

Kamal2(デプロイツール)

Kamalは、Dockerベースのアプリケーションを「シンプルに、安全に、本番環境へデプロイ」するためのツールです。
Ver.2で kamal-proxy と統合されたことにより、よりシンプルに安全に扱えるようになっています。

  • SSH経由でコンテナのデプロイ/ロールバックを行える
  • 設定が少なく、構成が明確で理解しやすい
  • サイト管理に必要な操作がすべてkamalコマンドから行える
  • 小〜中規模の複数サービス運用に向いている

今回のように、「大量の静的PHPサイトを、統一された方法で更新したい」というケースに特に適していました。

FrankenPHP(PHP ランタイム)

FrankenPHPは、Caddy Webサーバーをベースにした、モダンなPHPアプリケーションサーバーです。
従来の Nginx + PHP(FastCGI) の組み合わせを置き換え、PHPアプリケーションの高速化を実現している とのことです。

  • Caddyが同梱されており、設定が簡潔
  • コンテナ環境で扱いやすい設計
  • PHPのバージョン管理も不要(FrankenPHPのDocker Imageを更新するだけ)

静的な PHP サイトが中心の環境にとって、扱いやすく効率的でした。

Caddy(Web サーバー)

Caddyは、自動HTTPSとシンプルな設定を最大の特徴とする、モダンで高性能なオープンソースWebサーバーです。デフォルトで安全な設定が提供されるため、Webサイトやアプリケーションのデプロイを簡素化できます。

  • シンプルな設定 (Caddyfile)
    • Nginxのconfと似ているところも多いため、移行が簡単だった
  • 設定のテンプレート化や動的管理がしやすい
  • Let’s Encrypt の更新は完全自動
    • ※今回は使っていませんが

Before/After の変化

項目 Before After
デプロイ FTP による手作業 Git push → CI/CD による自動反映
ロールバック 不可能に近い kamal rollback により即時
vhost 管理 手作業で追加 Git管理されたCaddyfile
テスト できない ローカルで安全にテスト可能
変更履歴 担当者次第 Gitで全履歴を管理
セキュリティ FTP・直接編集 CI/CD 経由の統制された更新
拡張性 設定増加で複雑化 コンテナ分離により保守性向上
コスト ALB $18 + EC2 $80 ALBなし + EC2 $15

運用コストとリスクを大幅に下げることができ、継続的な改善が行いやすい体制になりました。

また、コスト面でも、高価なALBがなくなったことと、Graviton化により20%ほどOFFしたこと、CDNキャッシュが効くことによりオリジンへのアクセス減少が見込めるためインスタンスタイプを小さくすることができたことにより、節約になりました。

苦労した点

  • Caddyfileの文法に慣れるまでに一定の試行錯誤があった
  • LPの中に一部例外的な挙動が必要なサイトがあり、多少工夫が必要だった
  • Gitベース運用への移行に際し、従来の手法からの意識調整に時間を要した

試行錯誤はかなりありましたが、一度作ってしまえばもう触らなくてよいところも多いので、やっておけば楽になると信じてがんばりました。

まとめ

長年運用してきた EC2 + FTP を中心とした基盤を、コンテナと CI/CD を前提とした構成に刷新しました。

  • レガシーな環境は長く支えてきた「資産」であり、その価値を認めつつ、将来に向けて更新していく必要がある
  • Kamal2 + FrankenPHP + Caddy は、静的な PHP サイト群のホスティングに適している
  • Gitベースの運用に統一することで、透明性・安全性・保守性が改善した

同様に、LP を多数ホストしている環境での刷新を検討している方にとって、何らかの参考になれば幸いです。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?