くりにっき

フルスタックキュアエンジニアです

なるべくお金をかけずに個人アプリを運用したい

前々からこの手のことを書きたいとは思ってたけど id:k0kubun さんの下記エントリに触発されて書きました。

k0kubun.hatenablog.com

tl;dr;

  • HerokuやFirebaseを駆使すれば割と無料でいける
  • 若干お金を払えばもっと選択肢は増える

個人アプリ開発

  • 2001~2002年あたりから個人HPでアプリを公開。後にVectorにも公開
    • アカウントは残ってるのでいまだにVectorからのレポートメールが毎月届いてます
  • 2009年くらいから色々ウェブアプリを開発

前提

Heroku

jp.heroku.com

メリット

  • レコード数が少なければPostgreSQLが無料で使える
    • 執筆時点で1万レコードまで無料 *1
  • アドオンが充実しててRedisやMemcachedも小規模なら無料で使える
    • 無料で使えるがクレジットカードの登録は必要
  • git pushだけでデプロイできるお手軽さ
  • Herokuのコンソールから機微情報を環境変数としてセットできる
    • 個人アプリをOSSとして公開する時に地味に助かるやつ
  • Deploy to Herokuボタン があるのでgemみたいに個人アプリを他の人に気軽に配布できる
    • 今だとDockerイメージで固めてDocker Hubとかで配布ってのもできるけど実行環境含めて配布できるのは強い

デメリット

  • コールドスタートがあるのでRailsみたいに起動に時間のかかるアプリは不向き
  • 東京リージョンはEnterpriseでしか使えないので日本国内からアクセスするようなウェブアプリの場合レイテンシの関係で不利。(Enterpriseじゃない普通のHerokuだとusかeuのみ)

特にPostgreSQL, Redis, Memcachedが無料で使えるので、業務でサーバサイドアプリを作っていてその延長で個人アプリも作ってみたいという場合にはとっつきやすいんじゃないでしょうか。

色々思うところはあるんだけどHeroku便利なんすよね、、、

GCP

Google App Engine

cloud.google.com

  • Herokuと同じくらいにできたPaaS老舗
  • 国内外問わず他のPaaSも色々できたんだけどことごとくサービス終了したのでHerokuとAppEngineしか勝たんって思ってる

メリット

  • オートスケールがあるのでアクセス数に応じてインスタンスが自動で増減する
    • ただしインスタンスが増えるとその分費用も発生する
    • 追記:一応HerokuにもDynoのオートスケーリングはあるんだけど、Performanceプラン以上(1 Dyno辺り最低月250ドル)じゃないと使えないので個人アプリだと厳しいのではと思います。(FreeプランかStandardプランだとコンソールから手動でのDyno数変更のみ)
  • 静的ファイルはサーバサイドアプリとは別のフロントエンドサーバから配信する設定にできる

デメリット

  • Heroku同様コールドスリープがある
  • GCPだと無料のRDBが使えないので別のSaaSを併用する必要がある
    • Cloud SQLは個人アプリだと高くて使いづらい(最低スペックでも月12ドルかかる)し、AppEngine使ってるのにDB用にGCEインスタンスを作るのもかなり微妙
    • 完全無料で済ませるならDatastoreやFirestoreのようなGCPのKVSを使う必要があるが、RDBと全然違うのでそれなりに学習コストはかかる

AWSでやろうとするとApp Runnerなんだけど完全無料でやるのは難しいんじゃないかなあ、、、

Cloud Run

  • DockerイメージをCIでビルドする手間を惜しまなければ全然あり
  • Cloud Runの無料枠も潤沢にあるので個人アプリ開発で使うには十分なんだけど、ビルドしたDockerイメージを置くContainer Registryの費用が発生するので若干の費用は発生すると思います

Firebase

  • https://primap.web.app/ をFirebase Hostingで動かしてるんだけど爆速でいい
    • 以前Fastlyが世界的な障害になった時にプリマップも落ちていたのでFirebase HostingのバックエンドはFastlyだと思います。どおりで速いわけだ
  • その他Cloud FunctionsやFirestore辺りも使ってます

プリマップのアーキテクチャについては下記エントリに詳しく書いてます。

sue445.hatenablog.com

sue445.hatenablog.com

Cloud Functions

  • 画面が不要だとFaaSでもいいですね
  • 個人Slackで運用してる雑ボット類は数年前まではVPSで動かしてたんですが、サーバの管理するのが面倒になって今は全部Cloud Functionsで動かしてます
  • 無料枠が潤沢なので個人アプリで使うには十分
  • AWSだとLambdaに相当し、Lambdaも無料枠が潤沢にある
  • Secret Managerにある機微情報をFunctionに設定することができるんだけど、Functionの呼び出し毎にSecret Managerの読み取り費用が発生するためそこだけ注意
    • 無料枠を超えたら1万回アクセス毎に月0.03ドル *2
  • 実はCloud FunctionsのデプロイでもバックエンドでContainer Registryが使われている関係でGCSの費用が発生します
    • 規模にもよるけど自分が運用してるアプリだと月0.01~0.05ドルくらい

Cloud Functionsで思い出したけど先日Ruby 3.0サポートがGAになってますね

cloud.google.com

GitHub Pages

  • 静的ファイルしか使わないんであればGitHub Pages最強
  • GitHubにコミットされたファイルしかGitHub Pagesで公開できないので、mainブランチが更新された時にGitHub Actionsでビルドしてgh-pagesブランチにcommitしてpushするひと手間がある

GitLab Pages

  • GitHub PagesのGitLab版なんだけど、こっちはGitLab CIのartifactをGitLab Pagesで公開するためGitHub Pagesのようなcommit & pushが不要なので嬉しい

2022/5/7 17:00追記:ブコメレス

id:anonruru

とても参考になる。1つだけ、tldrがtrdrになってたのが気になった。

指摘ありがとうございます。typo修正しました

シレン5の原始に続く穴を99F踏破した

原始に続く穴って?

以下「原始」と呼称

立ち回り

詳しい数字は覚えてないけど原始だけで1年前後、100回以上は余裕でプレイしてると思う。(シレン5全体だとプレイ回数950回、プレイ時間700時間くらい)

ちなみにシレン5だと救助システムがあって倒れても他のプレイヤーに助けてもらえるけど、僕は救助システムは使わずにノーミスクリアを目指してました。

wikiの下記ページはむっちゃ見てた。

seesaawiki.jp

seesaawiki.jp

特に50F以降はずっとモンスターテーブル見ながらやってたと思う。

序盤

  • 10Fのマゼルンゾーンだと隕石装備か朱剛石装備だったと思う
  • 28Fでギリギリ身かわし香の壺が出たのでしあわせの札でクロスカートを吹き飛びカートにレベルアップさせて吹き飛ばしの矢を1000本くらい稼いだと思う
    • とはいえ身かわし状態だと札も当たらないので実際に稼いだのは29F。同じフロアのガラ中流魔道士が怖かったけど魔法ダメージの印があったのでゴリ押せた

中盤

  • 金喰い剣+盾。この辺で道具感血の腕輪(まがい物の方)をゲット
  • 白紙の巻物が店売りしてたので所持品を全部売った後にタダの巻物でギタンを荒稼ぎした時の様子が下記

  • 50Fくらいから即降りモードに移行
  • その後ギタンが尽きて死を覚悟したけど道具感血のおかげで埋蔵金部屋を何回か引き当てることができてよかった
  • 通路で矢を打ちまくって安全確保しながら歩いた

終盤

  • この辺で昼の盾を拾ったのでメイン盾に変更
  • ドレッドラビや大物荒らしに遭遇しなかったのは完全に運がよかった...
  • 催眠無効の印がなくてゲンナマゲイズが怖かった以外は安定
  • 火力的には終盤でも普通に殴り合えたんだけど回復アイテムがなかったので吹き飛ばしの矢を打ちまくって撃破することが多かった
  • 94Fで大部屋モンスターハウスが出た時は死を覚悟したけど冷えびえ香の壺でイッテツ戦車を無効化できたのは大きかった
    • とはいえ96F以降のアビスドラゴンゾーンは冷えびえ香の壺や回復アイテムがなかったので生きた心地がしなかった。(炎半減の印があってもきつい)

PlantUMLで描いた図をGitHubのリポジトリでいい感じに管理したい

tl;dr;

  1. pumlファイル*1を作成
  2. pumlファイルからsvgファイルを作成
  3. リポジトリにはsvgファイルを埋め込む

モチベーション

GitHubでMermaidがサポートされましたが *2、Mermaidで描けないタイプの図があってたまにPlantUMLを使いたくなるので備忘。

ちなみにGitLabやesaやQiita辺りはPlantUMLをサポートしてるのでこの手のハックはしなくていいです。

実際の例

実際の例を見てもらった方がいいと思うので自分のリポジトリを見せます。

他にもうまいやり方は色々やり方はありそうだけど思いついてないです。

pumlファイルを作成

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/_img/overview.puml

Goのリポジトリなのでビルドターゲットから外すために_img/ のようなディレクトリにしましたが、ディレクトリ名は何でもいいと思います。

pumlファイルからsvgファイルを作成

手元でPlantUMLのjarファイルを管理したくないので僕はよく https://hub.docker.com/r/think/plantuml を使ってます。

Makefile に下記のようなタスクを置いておけば make puml2svgsvgが作れる。

.PHONY: puml2svg
puml2svg:
  cat _img/overview.puml | docker run --rm -i think/plantuml -tsvg > _img/overview.svg

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/Makefile#L54-L56

Makefile にしないまでもpumlからsvgを作るコマンドくらいはREADMEに書いてた方が他の人もメンテできるようになって便利。

リポジトリにはsvgファイルを埋め込む

README.md で下記のように書けば表示できます。

![overview](_img/overview.svg)

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/README.md#overview

メリット

余談

なんとなく自分のリポジトリを見ていて「この図はMermaid移行した方がよさそうだなー」と思ったんですが、これを消した後に別のリポジトリでPlantUMLを管理したくなった時に自分が困るので後から調べられるようにしたいというのがこのエントリの本当の目的です。

2022/04/13追記

PlantUMLからMermaidに移行した

github.com

itamae-plugin-recipe-datadogのメンテナになった&itamae-plugins orgのオーナーになった

簡単な経緯

PRを送ったらitamae-plugin-recipe-datadogのメンテナになった

詳しい経緯

経緯は id:takanamito さんのエントリに詳しく書いてます。

takanamito.hateblo.jp

itamae-plugin-recipe-datadogとは

Itamaeでdatadog-agentをインストールするためのプラグインです。

今年のISUCONに向けてずっと素振りをやってるんですが、今年はDatadogを使いたくてitamae-plugin-recipe-datadogを使ってました。

そこで、Itamaeを実行する度に余計にDatadogのインストールスクリプトが実行されて遅くなってたので下記のパッチを投げました。

github.com

そしたらある日突然下記のようなメンションをもらってメンテナになりました。

itamae-plugins orgのオーナーになった経緯

自分がメンテするのは別にいいんですが、Datadogは有名なツールなので個人プロダクトよりは複数人で管理できる https://github.com/itamae-plugins に置くのがいいと考えました。

github.com

orgのオーナーである id:k0kubun さんに相談したところorgのオーナー権限をもらいました。

v0.2.2について

いくつか機能追加したいとは思ってるんですが、CIやテストをセットアップしたり過去バージョンのCHANGELOGを全部書いてたら結構差分が多くなったのでとりあえず最低限の分だけいれてます。

https://github.com/itamae-plugins/itamae-plugin-recipe-datadog/blob/master/CHANGELOG.md#v022

まとめ

takanamitoさんのエントリに

自分は勉強会やイベントでsue445さんの発表を見ており、いくつもgemをリリースされている方なので信頼できると判断してお声がけしました。 (あとになって気付きましたが、itamae本体のメンテナでもありますね)

と書いてあったので日頃の活動ってのは大事だなと実感しました。。。*1

あと、k0kubunさんとは同じItamaeコミッタ仲間だしリアルでも何回かやり取りしたことあるのも良かったと思います。(僕もGitHub orgのオーナー権限をいくつか持ってるので分かるんだけど、普通見ず知らずの人にオーナー権限は渡せない)

2022/4/2 1:10追記

パッチ袋にあった機能を取り込んでv0.3.0をリリースしました。

https://github.com/itamae-plugins/itamae-plugin-recipe-datadog/blob/master/CHANGELOG.md#v030

2022/4/6 14:20追記

Speeeさんの方からもブログがきてました

tech.speee.jp

*1:最近表立った活動をあまりできてないのは内緒

plant_erd v0.4.0をリリースした

github.com

GitHubがmermaidに対応予定 *1 ということでplant_erdもmermaidに対応しました。

https://github.com/sue445/plant_erd/blob/master/CHANGELOG.md#v040

plant_erdって名前でPlantUML以外のフォーマットに対応するのがかなり悩ましかったんですが、GitHubが対応する以上今後これがデファクトになる予感がしたので対応しました。(mermaid用にリポジトリ分けるという案もあったけど いい名前が思いつかなかった メンテナンスコストが上がるのでやめた)

ただしPlantUMLで埋め込めていた情報(index情報とか)がmermaidだと埋め込めなかったので、完全な代替にはならなさそうです。(詳しくはREADMEの図を参照)

gitのログをとにかく全部出したい

git log ではなくgitの内部のログの話です。

最近gitコマンドの通信周りを追っていてログをとにかく全部出して挙動確認してるのでメモ。

  • --verbose :git以外のコマンドにもよくあるオプションなので定番
  • GIT_TRACE, GIT_TRACE_SETUP:git内部のデバッグログ
  • GIT_CURL_VERBOSE:gitがリモートリポジトリに通信する時の詳細なログを表示

ということで、gitのログをとにかく全部出したい時は

GIT_TRACE=true GIT_TRACE_SETUP=true GIT_CURL_VERBOSE=true git fetch --verbose

export GIT_TRACE=true
export GIT_TRACE_SETUP=true
export GIT_CURL_VERBOSE=true
git fetch --verbose

のようにする。

参考URL

git-scm.com

faraday v2対応を行った&faraday-mashifyをリリースした

公式ドキュメント

https://github.com/lostisland/faraday/blob/main/UPGRADING.md

具体的な対応内容

faraday v0系とv1系は共存できたんですが、v2系はプラグイン周りに大きな変更があった関係でそれまでのバージョンと共存できなかったので拙作のAPIクライアントgemに関してもfaraday v2系未満のサポートを切ってメジャーバージョンアップを行いました。

faraday v2系でRuby 2.6系未満のサポートが切られてるので必然的に自分のgemでもRuby 2.6未満のサポートを切っています。

faraday_boolean v1.0.0

pixela v3.0.0, prismdb-ruby v1.0.0, chatwork-ruby v1.0.0

いずれのgemもmashify(普通のHashを ActiveSupport::HashWithIndifferentAccess のようなメソッドアクセスできるいい感じのHashにするやつ)を使ってたのですが、mashifyが組み込まれてる faraday_middleware がfaraday v2系だと非推奨になって対応をどうするちょっと困りました。(gemspecに ~> 1.0 が書かれてるのでv2系と共存もできない *1

v2系だとfaraday_middlewareに組み込まれてたプラグインは各gemに分割される方針になってるようなのでfaraday-mashifyというgemがあるかと思いきやなかったのでIssueで聞いてみました。

github.com

そうしたらfaradayのメンテナから

We welcome people who would like to create and maintain them though, it doesn't have to be us!

という返事をもらったので自分でfaraday-mashifyを作り、自分のgemに組み込んで今回の対応を行いました。

github.com

その他地味にハマったところ

faraday v2対応時にテストコードが軒並みコケて調べたところ、レスポンスヘッダのContent-Typeが正しく設定されていないと response :json が動かなくて *2 地味にハマりました...

普通にWeb APIを叩いたらContent-Typeにjsonが入らないというのはまず無いはずなんですが、自分のテストコードだと webmock で外部通信部分をスタブにしていてスタブ側でContent-Typeを設定してなくてテストコードが軒並みコケていたというオチでした、、、

実際の対応内容 https://github.com/sue445/pixela/pull/91/commits/2adf922689b023fd458f6293f04c7e4b5b5b01fa