テックブログを作りました。フルスクラッチで。

みなさん、こんにちは。株式会社Condisenseです。

本日より弊社のテックブログを開設しました。このテックブログは外部のブログサービスを借りずに自社で構築しています。 せっかくなので、自社で作ることにした理由や、技術構成などを、大まかに紹介したいと思います。

なぜブログをフルスクラッチで?いまどき?

手間を省いて悩みが増える

当ブログは、弊社がフルスクラッチで構築しています。

「なぜいまどき?」と疑問に思う方も多いでしょう。 ZennやNote、はてなブログなど、優秀な外部サービスは数多く存在します。WordPressのような実績あるソフトウェアもあります。わざわざ車輪の再発明をする理由はどこにあるのでしょうか?

私自身、これまで個人ブログ運営や会社のテックブログ立ち上げなどで、様々なブログプラットフォームに触れてきました。 多くの場合、既存サービスを利用するのは合理的です。ブログシステムの維持運営は本質的な価値ではなく、そこに手間をかけるのは避けたいからです。

しかし、手間を省くはずの外部サービスに大きく振り回された経験が1度や2度では済まず、なかなか苦労してきました……。 突然の料金体系変更、意図しないUIの改変、過剰なログイン誘導、あるいは「最新の直感的エディタ」の導入といった"改善"。プラットフォーム自体の求心力が低下することもあります。

対照的に、私が以前できるだけ外部依存を減らして構築した個人ブログは、4年ほど放置していても、今なお問題なく動き続けています(dependabotからの通知を除けば)。

タイムマシンで過去の自分に伝えても信じないでしょうが、外部サービスに依存したブログ運営は、稚拙な技術選択で固めた車輪の再発明より脆い場合があります。

自分の足で立つ

ではセルフホストすることで万事うまく行くかというと、現実はそうでもありません。 私が社会人になったばかりの頃、朝の通勤途中に、自分のVPSからのアラートメールがひっきりなしに飛んできて、スマホのSSHアプリを使って必死に問題を修正したことがあります。

しかし、何かしら意図しない現象に巻き込まれても全て自分たちのせいでしかないので、納得感もありますし、対処法もいくらでも思いつきます。 外部要因へ適宜対処するよりも、ずっと満足感が高いでしょう。

ポジティブなメリットとしては、小規模な運用を経験することでノウハウが蓄積しやすいという点があります。 規模が小さいかつミッションクリティカルではなく、片手間で維持できるようなシステムは昨今では珍しくなってしまっています。 多少の失敗では損害にならないような小さなシステムを自分たちで維持していくことで、基礎力も身についてゆきます。

「サービスが高度化して、経験を積ませるための仕事がなくなってきている」という嘆きも、特にインフラ系ではよく聞きます。 そういった時代だからこそ、自分たちでできることはわざわざ自分たちでやってしまうという考え方も、時には取り入れていく必要になるでしょう。

技術構成

ブログを構築するにあたって、以下の点を重視しました。

  • シンプルであること
  • 運用が楽であること

ブログ程度でわざわざ明示的に意識するほどでもないのでは?という疑問を持つ方もおられると思います。 しかし世の中のブログをいろいろ見て回っていると気づきますが、読者側は使わない大量の機能がサイドバーなどに押し込められていることが、よくあります。 昨今ではシンプルなものも増えましたが、なんとなくで作っていると簡単に肥大化します。

技術的な面でも同様に、あれは必要かも?と付け加えていると簡単に複雑化していくので、意識してシンプルに保つ努力が重要になってきます。

全体像

ウェブサーバーはCloud Runにデプロイし、その前段にCDNを有効化したCloud Load Balancingを配置するという、標準的な構成を採用しています。 Cloud Runは明示的なLBを介さず直接的に外部に公開することも多いですが、今回はCDNを用いたいという理由で、LBの後ろにいます。

近年ではチュートリアルでもなかなか見かけないような、貧相なアーキテクチャとなりました。ここから更に削るなら、LB/CDNを削除しても十分に動作します。

開発環境ではIAP(Identity-Aware Proxy)を用いて社内のアカウントのみがアクセスできるよう構成していますが、ここでは省略します。

DBを用いない構成については、後ほど説明します。

サーバーの技術選択

ウェブサーバーはTypeScriptで記述し、bun + honoを使用しています。

今回のウェブサーバーは、記事に対するGETリクエストを処理するのみであるため、シンプルで軽量なものを採用しました。 npmbun といったJSランタイムはエンジンのフットプリントやそれに伴うベースイメージが大きくなりがちです。 私個人としてはコンテナ環境下ではJSランタイムの使用を避けて、GoやRustで構築することが多いです。

ですが今回はシンプルなブログであるのに加えて、頻繁にデプロイすることもないため、フロントエンドと親和性の高いTypeScriptで記述できたほうが楽という事情もあり、bunを選びました。

サーバーとしてはSSR(Server-Side Rendering)したコンテンツを配信するのみで、キャッシュはCDNに任せています。

DBの技術選択

DBは独立して用意せず、コンテナビルド時にMarkdownの記事データを読み込んでSQLiteファイルを生成し、コンテナに内蔵しています。実行時には、このSQLiteファイルを読み取る仕組みです。

Markdownで管理するためディレクトリベースのルーティングも可能だったのですが、ディレクトリベースの管理では広いクエリ(検索、並び替えなど)が煩雑になります。 かといって本格的なRDBやHeadless CMSが絡むと、管理が煩雑になります。

ユーザー操作によって頻繁にデータの書き込みが発生する一般的なウェブサービスと異なり、ブログでは記事を追加・編集しなければ書き込みは発生しません。 そのためRead-Onlyなデータとして配置できれば十分であるので、ビルド/デプロイ時にSQLiteファイルを構築する選択肢を選びました。

DuckDBなどを併用することも考えましたが、規模が小さいことと、SQLiteのみでひとまず十分に動作しているので、一旦は保留としました。

運用を楽にするための取り組み

どれだけシンプルなシステムにしても、運用の手間からは逃れられません。システムの構築と同時に、運用を楽にするための仕組みも用意しました。

Terraform

インフラ管理にはTerraformを使用しています。もしかするとブログ程度にIaCは少し大げさに感じるかもしれません。 ですが、ブログのような小規模システムでは、インフラの変更頻度が低いからこそ、構成を忘れてしまうことがあります。 tfファイルに構成が残っていることで、あとあと救われるかもしれません。

また、PR作成時に terraform plan の内容をコメントするGitHub Actionsも用意しました。 どのような差分が適用されるかわかりやすいため、安心してマージできます。

AIレビュー

記事執筆時の悩み事のひとつがレビューです。エンジニアにとって、自分が書いた記事は大丈夫なのだろうか?という不安はコードを書いた時のそれより大きいと思います。 しかし、記事レビューを依頼するのは気が引けますし、依頼された側も、読者視点でのレビューには相応の負担が伴います。

そこでAIによる簡易レビューができるようにしました。

現在は各々がcliから実行する形になっていますが、GitHub Actionsを用いてPR作成時にもレビューが自動で書かれるようにする予定です。

以下の画像は、この記事自体をレビューさせてみたものです。 書き終わってからレビューさせたので問題の指摘が少ないですが、書き途中では細かな表現の指摘などもしてくれました。

さいごに

ブログとひとことで言っても、技術的に様々考えなければいけませんし、運用面でもたくさんの課題が発生します。 単に記事を書いて公開するだけにこだわらず、技術練習の場として利用すれば一石二鳥にもなります。

弊社のブログもこれで完成というわけではなく、必要な機能などは適宜追加していくつもりです。 読者のみなさまに有益な情報を提供できるよう、記事の充実化はもちろんのこと、ブログ自体の改善も継続的に行っていきます。

それではまた、機会があればよろしくお願いいたします。