Roll With IT

tamakiのIT日記

自作サービスの反響と改善

AI生成画像

はじめに

このエントリーは、フィヨルドブートキャンプ Part 1 Advent Calendar 2023 の 15 日目の記事になります。

adventar.org

Part2cassy0220さんの記事はこちらです!

昨日のエントリーは、

でした!

私からは、前日リリースした自作サービスの反響結果のまとめと、ユーザーからのフィードバックを生かしてアプリを改善した内容について書きたいと思います。

やったこと

まず先にリリースする上でやったことをご紹介したいと思います。

多くの方に見ていただきたいと思い事前に計画と準備をしました。

SEO対策

事前にできるSEO対策を行いました。

  • titleタグ
  • favicon
  • meta description
  • OGP(Open Graph Protocol)
  • canonical
  • LazyLoad
  • レスポンシブデザイン
  • インデックス登録

対策した結果、上位に表示することができました!(キーワード:アウトドア般若心経

リリース日を検討

まずリリース日です。10 月 6 日(金)にした理由ですが、主に以下 2 つの理由からこの日を採用することにしました。

  • 当アプリは外出を前提としているため、外出の可能性が高い連休前日(10/7(土)〜10/9(月祝))にリリースすることがベストだと判断

  • 週末にみうらじゅん FES が開催されており、SNS 等でもみうらじゅん氏関連の露出が増えてることを予想

これは予想が当たり、多くの反響をいただけました。詳細は後ほど。

前日の告知

前日にリリース予告をポストし告知しました。またフィヨルドブートキャンプ限定の日報、Discord にも同様の告知を行いました。

リリース日当日

リリースブログを公開

旅ログを公開

Twitter(現 X)で告知

AM 9:00 に告知を開始しました。

同様の内容をアプリの専用アカウントからもポストしました。

関連情報は素早くアクセス出来るようにスレッドに紐付けておきました。

Image from Gyazo

Discord で告知

Image from Gyazo

反響結果

Twitter(現 X )

Image from Gyazo

はてなブックマーク

はてブのホットエントリにランクインしました。この後一気に反響が増えました。はてブハンパない...

テクノロジー

ブックマーク数:153 件

[B! アプリ] アウトドア般若心経が楽しめるWebアプリをリリースしました - Roll With IT

Image from Gyazo

暮らし

ブックマーク数:166 件

[B! 写真] アウトドア般若心経

Image from Gyazo

2023 年 10 月第 1 週ランキング入り

第 9 位にランクインしました 🎉

今週のはてなブログランキング〔2023年10月第1週〕 - 週刊はてなブログ

Image from Gyazo

はてなブログ アクセス数

日付 アクセス数
10 月 6 日(金) 604
10 月 7 日(土) 1625
10 月 8 日(日) 184
10 月 9 日(月) 88
合計 2501

ユーザー登録者数

日付 ユーザー登録者数
10 月 6 日(金) 38
10 月 7 日(土) 189
10 月 8 日(日) 36
10 月 9 日(月) 13
合計 276

12 月 15 日現在の登録者数は、353 人!🎉

改善

フィードバックをアプリに反映

ユーザーから頂いたフィードバックを Issue に登録し開発に生かしました。

Image from Gyazo

特に面白かったのは、みうらじゅんファンにはおなじみの「Since」について。みうらじゅんファンの方から直接コメントをいただき、デザインとして取り入れることにしました。また質問や疑問が多かった内容についてはFAQ ページを作成し対応しました。

事前にやっておけばよかったこと

リリースしてから一週間後に知りましたが、Google Analytics4 という解析ツールがあり、事前に導入すればよかったと思いました。

アプリへ訪問したユーザーの行動を分析するアクセス解析ツール になりますが、リリース直後から集計を取りたい方は、事前に導入されることをおすすめします。

support.google.com

さいごに

予想以上に多くの反響をいただきとても驚きました。実際に使っている様子を Twitter(現 X)で共有いただいたり、ファボやリポスト、そしてコメントもたくさんいただきました。本当に嬉しかったです。

はてブでは、辛辣なコメントもありましたが、的を得ているご指摘もありとても勉強になりました。

リリースすることで、改めてインターネットの面白さ、Web 開発の楽しさを実感できました。

最後は Twitter(現 X)で共有いただいた素敵な写真をご紹介して終わりにしたいと思います 📸

最後までお読みいただきありがとうございました。それでは!ハッピークリスマス 🎄🎅

OSS Gate に入門しキュアエンジニアに認定された話

はじめに

先日OSS Gate × フィヨルドブートキャンプ 」のコラボ企画イベントに参加しました!

prtimes.jp

OSS Gate とは

OSS 開発に参加する人を増やす取り組みです。OSS Gate は「OSS 開発経験者」が「OSS 開発未経験者」を支援するOSS Gate ワークショップを開催しています。

OSS Gateへようこそ!

フィヨルドブートキャンプとは

プログラマーとして就職を目指せるだけのスキルを身につけることを目標としたオンラインプログラミングスクールです。

FJORD BOOT CAMP(フィヨルドブートキャンプ)

OSS Gate についてより詳しく知りたい

今回の私のブログは感想が主な内容になるため、当日の雰囲気や流れなどが気になる方はぜひこちらをご覧ください。

イベントにご一緒させて頂いた id:hiranovm4 さんのブログにとても分かりやすくまとまっています。

hirano-vm4.hatenablog.com

本もあります。

nextpublishing.jp

参加の経緯

以前から OSS Gate の存在やワークショップの開催が行われていることは知ってましたが、興味はあったものの 未だ Gate をくぐれずにいました。しかし今回フィヨルドブートキャンプとのコラボ企画ということで背中を押していただき、初めてビギナーとして参加させてもらいました。

OSS 活動の経験

OSS 活動の経験(経験と言えるのかは疑問ですが...)といえば、ドキュメントにタイポを見つけて Issue を立てたり...

The content of the h1 tag in the Japanese document contains a typo. · Issue #5586 · axios/axios · GitHub

またこれは受け手側の話しですが、自分で作った gem に Pull Request をもらった経験ぐらいしかありませんでした。

gem install時にtty-promptも一緒に入ってほしい by yancya · Pull Request #8 · shirotamaki/kakutaniquiz · GitHub

講演「今日から参加できる!OSS 開発」

すごくないよ、ふつうだよ

冒頭の講演では、OSS 活動に対して多くの方が以下のような印象を抱えているのでは?という話がありました。

OSS 活動をしている人たちのイメージ

  • 自分たちには程遠い世界の人たち
  • 非常に高い技術力を持つ上級者
  • 聖人のように利他の精神を持つ人たち

確かに、OSS 活動は「すごい人」しか参加できないイメージがすごくありました。敷居の高い活動で、自分にはまだ手が出せないと思っていました。

しかし講演でいろいろなお話を伺う中で、「OSS はすごい人しかできない」という自分の中での勝手なイメージが崩れていき、「自分にもできるかも?」という考えに変わっていきました。

すごいかは関係ない

普通のユーザーの視点が大事

簡単なライブラリもありますし、誰も触りたがらないツギハギだらけのスパゲッティコードOSS もあります。すごい有名な OSS ばかりに目が行きがちですが、世界中にいろんな OSS が存在していることを考えると、普通のユーザーの視点を持つ自分にもなにか出来るのではないか?と思えてきました。

世界を変えられる。今すぐに!

確実に何かが良くなる

なんだか自分にもなにかできそうな気がしてワクワクしました。

ちなみに、この時点ではまだワークショップは始まっていませんが(まだ冒頭の講演 30 分のお話し)、冒頭の講演を聞くだけでも、OSS に対して価値観が変わる内容でした。

ワークショップ

いよいよ、ワークショップ開始です。

詳しい内容は省略しますが(詳細は以下 Issue と Pull Request をご覧ください)、サポーターさんの親切丁寧なサポートのおかげで、何の心配もせずに進めることができました。

github.com

rubicure

今回、私が選んだ OSSrubicureです。

FBC の先輩から教えてもらった OSS です。その時は rubicure の中身の話しではなく、プリキュアの話しで盛り上がってしまったのですが ...。rubicure のことが印象に残っていて、今回ぜひ取り上げたいと思い選択することにしました。

初プルリクをマージしてもらう

サポーターさんや、作者ご本人より直接コメントいただきサポートしてもらいました。プルリクを提出し、無事にマージしてもらうことができました!

初プルリク、初マージ、とても嬉しかったです。

サポーターのみなさん、そして作者の@sue445さん、ありがとうございました。

github.com

キュアエンジニア認定

なんと!rubicure への貢献が評価され、名誉ある「キュアエンジニア」に認定いただきました。

これからも「私たちにとって大切なものを奪おうとする怪物を追い払うため」に、OSS活動に挑戦し続けたいと思います。

最後までお読みいただきありがとうございました!

アウトドア般若心経が楽しめるWebアプリをリリースしました

はじめに

2023 年 10 月 6 日に Web アプリ「アウトドア般若心経」をリリースしました!!

この記事では Web アプリの概要や使い方、技術スタックやこだわった点、また開発過程での苦労や学んだこと、さらには今後の展望まで、詳しく解説します。

サービス URL

https://www.outdoor-heart-sutra.com

GitHub リポジトリ

https://github.com/shirotamaki/outdoor-heart-sutra

対象読者

自己紹介

こんにちは。tamaki と申します。

FJOROD BOOT CAMPフィヨルドブートキャンプ)(以下 FBC)を先日無事に卒業し、現在は転職活動中です。

twitter.com

アウトドア般若心経とは

まず Web サービスの紹介前にアウトドア般若心経とは何かについて説明したいと思います。アウトドア般若心経とは、イラストレーターのみうらじゅん氏が提唱した「般若心経」の新しい写経方法です。

みうらじゅんは「般若心経」278 文字を、家を出て(これを「出家」と称す)、経文の文字のある市街の看板等の文字を写真に撮り(これを「写経」と称す)、経文の完成を目指すことを「アウトドア般若心経」と定義した。

出典: フリー百科事典『ウィキペディア(Wikipedia)』

ポケモンGO の般若心経バージョン

Xでアプリを告知した際に、秀逸な例えをリプライで頂いたためご紹介。オブレゴニアさん、ありがとうございます!

サービス開発のきっかけ

世の中には二種類の人間が存在します。

アウトドア般若心経」をする人と「アウトドア般若心経」をしない人です。

もちろん私は前者でありますが、街に出て写経を行っている時「どの文字が写経済みか?」また「どの文字が新たに写経必要か?」と、戸惑うときがあります。写経済みの文字を覚えていないことが原因ですが、その都度スマートフォンの中に保存している写真データから撮影済みの文字を確認したりと、写経中とても煩わしく感じていました。

そこで「アウトドア般若心経をもっと手軽に楽しむためのアプリがあれば」と考え、「ないなら自分で作るしかない!」と個人でサービスを開発することにしました。

サービスの概要

アウトドア般若心経は、街の看板や標識から集めた般若心経 278 文字の写真の管理が面倒な問題を解決することができる、 アウトドア般若心経ユーザー向けの写経(写真経)アプリです。

ユーザーは、般若心経 278 文字を写真に収め管理することができ、文字の収集状況を経文の並び順で視覚的に確認することができます。また撮影場所の位置情報の取得、写経場所の Google Maps へのピン止め、それからメモを記録する機能も備えています。

Google アカウントをお持ちの場合、無料でご利用いただけます。

※ 経文は玄奘訳を基本としながらも一部が違う「流布本」を採用しています。本文 266 文字に首題 12 文字を含む合計 278 文字となります。

使い方

1. Google アカウントでログイン

Google アカウントをお持ちの方はすぐに始めることができます。

2. 般若心経の全文を一覧で管理

般若心経 278 文字の写経状況を一覧で管理することができます。

3. 写経した写真を取り込む

写経したい文字を選択すると画面が切り替わります。

HEIC、JPEGPNG 形式の写真を登録することができます。またカメラ付きのデバイスの場合は、写真を撮影しそのまま取り込むことも可能です。

4. 取り込んだ写真をトリミング

5. 写真の登録

トリミング後、切り取った画像がプレビューできます。「保存」をクリックするとアプリに保存できます。

6. 保存した内容の確認

写真を保存後、ページが切り替わります。写真と併せて地図が表示され、 位置情報は自動で登録されます。またトリミングした写真は地図にピン止めされます。(GPS 機能をオンにしてください)

7. メモの登録

メモは 最大 140 文字まで登録が可能です。

8. 全体地図の確認

メニューから「地図」を選択すると、写経済みの全ての文字の位置情報を Google Maps 上で確認することができます。写真をクリックすると詳細ページに遷移できます。

9. マイページ

出家日(サービスを開始した日)と写経済みの文字の総数を確認することができます。退会の手続きもこちらから簡単に行うことができます。

技術スタック

バックエンド

フロントエンド

認証

リンター/フォーマッター

テスト

データベース

インフラ

CI/CD

外部サービス

技術選定の理由

技術選定にあたり、技術的なテーマを 4 つ設定しました。

  1. Rails を使ったバックエンド開発
  2. React と TypeScript を使ったフロントエンド開発
  3. Google サービスとの連携
  4. インフラ、テストツールは、バグを踏みハマらないためにもサポート体制やドキュメントの充実度などを考慮しできるだけ最新のものを採用する

1 つ目は Rails を使ったバックエンド開発です。これはマストでした。日頃から多くの周りの Rubyist の諸先輩方に刺激を受け、そして助けていただいたことで今の自分があり、個人開発を通してさらに Ruby についての知識を深めたいと思い採用を決めました。

2 つ目の React と TypeScript を使ったフロントエンド開発は、FBC で学習している内容ではなかったのですが(現在の FBC のプラクティスでは Vue.js に代わり React が採用されています)、新しい技術であり、かつ Vue.js との比較で React を推す身近なエンジニアが多くいたため採用しました。また以下アーキテクチャの項でも書いていますが、Next.js入門からの影響も大きな理由のひとつです。TypeScript も同様に使ったことはなく不安でしたが、React を使うならほとんどのケースで採用されている組み合わせのため、今回挑戦する価値があると考え採用しました。

3 つ目は、Google が提供するサービスとの連携です。普段から利用している Web サービスの多くが、何かしらの Google が提供するサービスが使われていることが多いのですが、自分の開発する自作サービスでも採用したいと常日頃思っていました。開発したサービスのコアな機能でもある「地図、位置情報」ですが、Google 以外にも存在はしますが、今回のテーマに従い Google MapsGoogle GeoCoding を採用しました。また Google 認証ログインにおいては、NextAuth.js を採用し、ログイン認証機能を実装しました。

4 つ目は、インフラとテストに関する部分です。私はデプロイ未経験、かつテストについても十分な経験がありませんでした。そのため不安要素が多く存在しました。 バグのリスクを減少させるため、そして発生したバグを自力で解決できるように、サポート体制やドキュメントの充実度を考慮しました。結果として、できるだけ信頼性が高く最新の技術を採用する選択をしました。 具体的な技術選定については、E2E テスト・ツールでは当初 Cypress を採用していましたが、後に Playwright に変更しました。また外部ストレージに関しては、Fly.io の Volumes から Amazon S3 に移行しました(詳細は後述します)。

アーキテクチャ

Rails と Next.js を使ったアーキテクチャの構成を検討する上で参考にした記事です。

RailsエンジニアのためのNext.js入門 by Kazuhito Hokamura - Kaigi on Rails 2021

当時、Kaigi on Rails の発表を配信 Live で観ていたのですが、その時は難しく理解ができませんでした。それから時が経ち、今回自分がやりたいことと一致していることが理解でき、ようやく点と点が繋がった感じです。

ディレクトリ構成

フロントのディレクトリ構成は、bulletproof-react を参考にしました。bulletproof-reactはプロジェクト自体が大きいので細かく分けてありますが、当サービスはそこまで切り分ける必要がないので、極力シンプルに最低限の構成にしました。

以下は参考にした記事になります。

本気で考えるReactのベストプラクティス!bulletproof-react2022

Reactベストプラクティスの宝庫!「bulletproof-react」が勉強になりすぎる件

開発方針とこだわり

Getting Real

大本の方針して、開発前に熟考した Getting Real に従うことを意識しました。

自作サービス開発の醍醐味は、サービスの企画段階から、実際の Web サービスとしてのリリースまで、全ての工程を一人で経験できることです。

  • 開発者
  • デザイナー
  • プロダクトオーナー
  • ユーザー

これらの役割を一人で担当することは、規模が小さくても非常に貴重な経験だと思います。

しかし、初めての経験ばかりで「何をどう進めるのか?」の指針がなく、戸惑いも多くありました。そんな時、 Getting Real が私の道しるべとなりました。開発中に不安や迷いが生じた時、原点に立ち返り、Getting Real の教えを思い返していました。

正直、わからないことだらけで何をやっても上手くいかなかったりと、開発が進まず立ち止まることも多く、苦しい時期もありました。幸いなことに、個人開発であるが故ビジネスとしての制約はないため、自分のペースで進める自由がありました。日々コツコツ積み重ねるように開発を続けました。

結果としては、「短いリリーススケジュール」は完全にアウトしていたりと、まだまだ完全な Getting Real 的なサービスとはいえませんが、少なからず「楽しく作って楽しく売る(サービスをリリースする)」ことはできたと思っています。

そんな Getting Realから好きな一節をご紹介。DIY でパンクなアティチュードを体現している イアン・マッケイ だからこそ深く響くものがあります。

パン屋さん

今のアメリカのビジネスは正に、アイディアを広げ、それを金儲けにつなげ、それが金になって、ビジネス展開できる間は売る、と集約されます。全てを吸い上げてしまう発想です。私のアイディアはこうです。パンを楽しく焼きましょう。パンを売りましょう。人々がそれを気に入ってくれたら、もっと売りましょう。あなたがよい食べ物を作って、人々が幸せになる。そんなベーカリーを続けていきましょう。

—イアン・マッケイ、「Fugazi」メンバー、「Dischord Records」共同経営者 ("Salon.com People | Ian MacKaye"より)

出典:Getting Real より意訳

UI / UX

シンプルな機能故デザインには力を入れました。Tailwind CSS を学び、デザインをあてました。

デザインはアウトドア般若心経の世界観を壊さないように、仏教の凛とした佇まいを意識しつつ、ポップな要素を融合させました。

またドッグフーディングを通してユーザー視点に立ち、ボタンの配置や文字の大きさなど、細部にもこだわりました。

アウトドア般若心経 ユーザー 以外には、アプリの内容や本質が理解しにくい問題が存在していました。その解決策として4コマ漫画を作成しました。これにより、ユーザーがアプリの使い方を直感的に理解できるようになり、UXが向上しました。

ダ鳥獣戯画 – 鳥獣戯画を拡張。イラスト素材のベクターデータ配布サイト。新しい戯画もあり

レスポンシブデザイン

さまざまなデバイスでの使用を想定し、レスポンシブデザインに対応しました。

パフォーマンス

開発当初はアプリの動作が非常に重くストレスフルでしたが、パフォーマンスチューニングを行いパフォーマンスの改善に努めました。

ロゴ

ロゴはプロのデザイナーに依頼し製作をしました。

メイン・ロゴ_A

メイン・ロゴ_B

スクエア・ロゴ

ファビコン_A

ファビコン_B

機能面

機能面もシンプルな構成故、いろいろとやりたくなりましたが、上述した Getting Real に従い「より少ない」を意識しました。

コスト面

昨今、無料で利用できる選択肢も多いのですが、プログラミングもアウトドア般若心経も趣味のひとつとして捉えているので、自分の理想に近づけるためにコストはかけました。ロゴの外注、独自ドメインの取得、外部ストレージ(Amazon S3)、Google サービス、デプロイ(Fly.io のメモリ増設)と、サービスを運用する上で必要なものは有料でも採用しました。

プロモーション

オリジナルグッズ製作

オリジナルグッズを SUZURI を利用し製作してみました。

FBCの先輩方が自作サービスに関連したオリジナルグッズを手にしているのを見て、当時から自分もぜひ製作したいと思っていました。実際にグッズを製作することで、自分のサービスへの愛着が深まりとても良かったです。

suzuri.jp

アカウントを開設

サービスのお知らせや告知用でアカウントを開設しました。

twitter.com

ドッグフーディング

開発中、頻繁にアプリを手に街に繰り出し、ドッグフーディングを繰り返しました。実際に使うことでアプリの改善点が見え、その後の開発に生かすことができました。

旅ログ

ドッグフーディングの経験をプロモーションにも生かせれば思い、旅ログとして文章にまとめました。

技術的な要素は排除し、ユーザーにアプリの楽しみ方をイメージしてもらうために書きました。スマホ片手に街を行脚した旅の記録を思いのまま綴っています。

shirotamaki.hatenablog.com

shirotamaki.hatenablog.com

開発中に苦労したこと

Google ログイン認証

まず最初に躓いたのが Google ログイン認証機能とユーザー情報を DB に保存する機能の実装です。「なにがわからないか、わからない」の連続で苦労しました。

当初はomniauth-google-oauth2を使って Google 認証を行う予定でしたが、Next.js を使う場合、NextAuth.js の選択肢があることを知り、途中から切り替えて実装しました。

バックエンドでのユーザー管理や認証のロジックを一元化したい場合はomniauth-google-oauth2 がおすすめのようですが、特にその予定はなかったのと、今回はフロントエンドでの Google 認証フローを経験してみたかったので NextAuth.js を選択しました。

詳細は別記事にまとめています。

shirotamaki.hatenablog.com

shirotamaki.hatenablog.com

外部ストレージサービスの設定

ActiveStorage を利用し、写経した写真をクラウドストレージサービスに保存する機能を実装しています。

元々は、Fly.io の Volumes を採用していましたが、AmazonS3 に変更することにしました。当初は Volumes の設定もうまくいき問題ないと思っていましたが、実際に本番環境で写真の登録動作を繰り返し確認する上で、写真の登録ができないバグが頻繁に発生していました。

原因を調べていく中で「Volumes の選択は適当ではない」との結論に達しました。公式には「Volumes ダメ!ゼッタイ!」と明示されているわけではありません。これはあくまで私の開発環境に基づく結果です。今回は、Fly.io のRails Specialist より頂いた「Rails では Amazon S3、GCS、Microsoft Azure を推奨している」とのアドバイスが決め手となり、Volumes の導入は断念することにしました。

詳細は別記事にまとめています。

shirotamaki.hatenablog.com

shirotamaki.hatenablog.com

E2E テスト

フロントエンドの E2E テストの実装に苦労しました。

当初は、Cypressの最新バージョン 12.17.2 を利用していましたが、自分の開発環境との相性が悪く、Google 認証ログインのテストが実行できない状態が続きました。その後、Cypress に拘るのをやめフラットに考え直し、E2E テストツールを再検討した結果、Playwright を採用することにしました。

詳細は別記事にまとめています。

shirotamaki.hatenablog.com

E2E テストの CI 環境構築

Google 側の bot 対策」が原因でしたが、原因の特定に至るまでに苦労しました。

こちらも詳細は別記事にまとめています。

shirotamaki.hatenablog.com

開発中にやってよかったこと

全て Issue に残す

Issue は小さく分解し細かく分けて立てました。些細なことも Issue にしました。また過去の振り返りでも利用できるように作業メモとしての役割も持たせました。

Scrapbox にアウトプットする

自作サービス開発の前から使っていますが、Scrapbox を使い、学んだことを記録として残しました。自作サービスを完成させることだけが目的ではないので、開発過程で学んださまざまことを Scrapbox に記録しました。Scprabox の良いところは雑に記録ができるところです。綺麗にまとめようとは考えず、とにかくアウトプットしました。Twitter や Discord でも細切れのアウトプットを試みたことはありましたが、私には Scrapbox が一番性に合っていました。

日報を書き進捗を報告する

先ほどの Scrapbox からの流れですが、Scrapbox で雑にまとめた内容が、後に整理されまとめられ日報として形になります。

日報を書くことで、自分の開発の進捗状況を把握することができ、また開発中にハマったことや、解決したことなどを記録することで、後から見返すことができ(復習大事)、自分の成長を実感することができました。また日報はメンターさんに見てもらえるので、開発進捗の報告としても役立ちました。

質問にステップを設ける

質問の段階も以下ステップを踏みいきなりステップ 4 に行くことはないように意識しました。もちろん実際の現場では状況に応じて判断すべきかと思いますが、自作サービス開発は何よりも自分の開発能力向上のためにやっているので、安易な方法に走るのではなく、時間はかかりますがしっかりとステップを踏んで質問の段階を上げていくことを意識しました。

  1. とにかく調べまくる
  2. 公式コミュニティ、フォーラムに質問する
  3. FBC 内でテキストで質問する
  4. FBC 内でペアプロで質問する

その結果、今まではステップ 4 に頼ることも多かったのですが、ステップ 1、2 で解決できることが増えたことを実感しています。特にステップ 2 で、英語圏の公式コミュニティ、フォーラムに対しての抵抗感が減り、そこから得れる情報の有益さに気づけたことは大きな収穫でした。

これからやりたいこと

元々の出発地点が自分が欲しかった 自作サービスの開発であるため、「これしたい、あれしたい」と、これからもやりたいことがいろいろあります。

  • ツイート機能
    • X(旧 Twitter)にボタンひとつでツイートができる機能
    • ツイート内容は、写経した写真、地図、メモ
  • パブリックユーザーとプライベートユーザーの選択
    • パブリックとプライベートを選択できるようにする
  • SNS 機能
    • パブリックユーザーの写経状況がタイムラインに流れる
    • いいねボタン
  • ランキング機能
    • パブリックユーザー限定。写経した文字数に応じてユーザーのランキングを表示する機能
  • ネイティブアプリ化

などなど、アイデアは尽きません。

やりたいことはいろいろありますが、まずは現状のサービスを継続して運用できるようにパフォーマンスチューニングを中心に改善に努めたいと思います。

焦らずマイペースに今後も少しつづ大事に育て、自分の手でサービスを成長させていきたいです。

おわりに

個人開発を通じて得た自身の最大の変化は「自走力」が身についたことです。なにかわからないことがあっても「なんとかなる」という自信が、開発前と比べて圧倒的に変化したことを実感しています。もちろん、全てを一人で完結できるわけではありませんが「時間はかかっても、解決不可能な問題はない」と自信を持てたことは、大きな収穫です。

プログラミングを始める前は、世界中どこからでもどんな人でもアクセスができるWebアプリを、自分がゼロから開発することができるとはまったく想像ができませんでした。企画から開発を経て初めてデプロイを行い、自身が開発したサービスが動いている様子を目にしたときは、本当に嬉しく感動しました。その後コツコツと開発を続け、サービスを完成させこの度リリースまでやり切ったことは、大きな自信になったと同時にとても大きな達成感を得ることができました。

大変なこと、苦しいこともありましたが、最初から最後まで本当に楽しい開発でした。

今後もこの経験を糧に学びを深め、さらにスキルを高めていきたいと思います。

最後までお読みいただきありがとうございました!

謝辞

長い期間、FBC で学習を続けてきました。その間多くの方に支えられ、助けられ、勇気づけられ、学び続けることができました。自分ひとりではここまでたどり着くことはできなかったと思います。

メンター、アドバイザーのみなさん、そして卒業生、在校生のみなさん、関わった全ての方に心より感謝申し上げます。

そして何より、アウトドア般若心経という新しい写経方法を提唱してくださったみうらじゅん氏に 深く感謝申し上げます。

本当にありがとうございました。

アウトドア般若心経の旅 〜沖縄ゆいレール編(後編)〜

はじめに

アウトドア般若心経とは

アウトドア般若心経とは、イラストレーターのみうらじゅん氏(以下「師」と称する)が提唱した「般若心経」の新しい写経方法です。

みうらじゅんは「般若心経」278 文字を、家を出て(これを「出家」と称す)、経文の文字のある市街の看板等の文字を写真に撮り(これを「写経」と称す)、経文の完成を目指すことを「アウトドア般若心経」と定義した。

出典:フリー百科事典『ウィキペディア(Wikipedia)

アウトドア般若心経が楽しめる Web アプリ

パソコン、スマホで使える Web アプリを開発しました。

無料でご利用いただけます。

今回のブログは、以下 Web アプリを手に街を行脚した旅の記録になります。

www.outdoor-heart-sutra.com

写経の旅

今回の記事は後編になります。

前編はこちら

美栄橋駅

「軽食の店 ルビー 」が定休日により途方に暮れてしまった前編

さすがの暑さにバテてしまい、近くの公園の木陰に逃げ込みました。そこで一息つき、冷静になって考えてみると、今自分が食べたいのは A や B や C のアルファベットの頭文字を冠したデカ盛りランチではなく、さっぱりあっさりした普通の沖縄そばであることに気づきました。

www.orionbeer.co.jp

次は「普通の沖縄そば」を探す旅に出ることにしました。

しかし沖縄そばといえど、県内には800店舗以上の沖縄そば屋があると言われおり、どこに行こうか悩みました。

照見五蘊皆空

五蘊」とは、「色(体)・受(感覚)・想(イメージ)・行(深層意識)・識(判断)」を意味します。仏教では、自分という主体を構成する基本要素というような意味合いで使います。これら五蘊が自分を自分たらしめていることを理解し、これら五蘊を見極めなさいと説きます。そして「皆空」。次にそれらは空であると見極めなさいとの教えです。観自在菩薩は、たんに自己の主体性を否定するのではなく、自己に対する正しい見方を持つようにと教えてくれます。

ここでも般若心経の教えが役に立ちました。

目を閉じ自分自身に問いかけました。今求めている沖縄そばとは?

パッと、漢字3 文字が浮かび上がりました。

「道頓堀」

次の目的地が決まった瞬間です。

牧志駅

「一」

「道頓堀」の真相は後にし、まずは次の駅「牧志駅」に向かいます。

奇跡の 1 マイルと言われた国際通りと言えばこの駅です。今や観光客が一番訪れる駅とも言えるかもしれません。

そんな牧志駅から向かうのは、これまた沖縄観光の定番スポット「那覇市第一牧志公設市場」です。

「道」

那覇市第一牧志公設市場」の 2 階には飲食店が連なっており、そこに「道頓堀」というお店があります。

このお店には、「道」の字(2 回目)を写経しに来ただけではなく、来ようと思った理由があります。

実はこのお店、筆者が高校生の頃に初めてアルバイトをしたお店なのです。

那覇市第一牧志公設市場は、2023 年 3 月に建て替わったばかりでとても綺麗になっており、特に吹き抜けの影響でだいぶ変わっていましたが、当時を思い出させる雰囲気はまだ残っていました。

10 代の多感な時期に、まかないとして頻繁に食していたここの沖縄そば

食べたかった「普通の沖縄そば」がここには変わらず残っていました。

Image from Gyazo

今や様々な沖縄そばがあり、麺は手打ちで、スープの出汁は ◯◯ からなどなど、こだわりのそば屋が乱列していますが、なんだかんだ食べたいのは、こんなシンプルな普通の沖縄そばなんですよね。

道頓堀に限らず、観光スポットである公設市場のお店はどこも金額設定は高めですが「那覇市第一牧志公設市場」で普通の沖縄そばを食べたいならオススメしたい良店です。

www.dotonbori-naha.jp

「舍」

お腹も満たしたことでだいぶ回復した体力。次の目的地に向かいます。

次は旭橋駅です。

旭橋駅へ向かう道中、桜坂や平和通りで目に付いた文字を写経しました。

素敵な映画館です。

わかりずらいですが、左側のシーサーに「舍」があります。かわいい。

「不」

すごいネーミング ...。

旭橋駅

旭橋駅に着きました。

波といえば「波之上」でしょう。ということで、これまた結構な距離ですが、波之上に向かうことにしました。

波上宮(神社)も久しぶりです。

「波」

本家のマイルールを踏襲し、なるべく神社仏閣にあるものからは写経しないことにしていますので、境内から出て探してみました。

いたるところに「波」が溢れています。

「自」

ついでに波上宮の真横にある我が母校、波之上自動車学校からも写経させてもらいました。

赤嶺駅

さあ、いよいよ次が最後の目的地となります。

最終地点は、瀬長島にある瀬長島ホテルを目指そうと思います。

バスで移動ができないか確認したところ、ちょうど瀬長島行きのバスが出る時間でした。赤嶺駅からバスで向かいたいと思います。

www.umikajiterrace.com

瀬長島

瀬長島那覇空港から車で 15 分ほどにある陸路で繋がっている島になります。

沖縄のサントリーニ島?と誰が言ったか言わないか、海と夕日とそして飛行機が間近に楽しめる観光スポットです。

島内には猫さんたちも多く見かけます。海風が気持ちよく、ゆったりとした時間が流れる素敵な島です。

「神」

バスを降りるとすぐ目の前に瀬長島ホテルがあります。

そこで最後の文字「神」を写経です!

これで今日予定していたすべての写経ポイントを周り終えることができました。

いや〜大変だった。しかし無事にやり終えることができとても爽快な気持ちです。足は棒のようですがそれすら心地よいです。

琉球温泉 龍宮の湯

最後は、瀬長島ホテル内にある温泉施設に伺い、身も心も整えて一日を終わりにしたいと思います。

www.resorts.co.jp

こちらの温泉施設は宿泊客はもちろんのこと、日帰り利用も可能になっておりオススメです。特に夕方の時間帯に訪問してもらいたいスポットです。理由は西海岸に沈む夕日。本当に綺麗です。また飛行機の発着を目の前で楽しめるので飛行機好きにはたまりません。

イマジン

サウナ内に設置されているテレビには、国と国との争い事がニュース映像として映され、その映像の BGM にはジョン・レノンの「イマジン」が流れていました。


師は「イマジン」について、般若心経から影響を受けていると説きます。

ジョン・レノンは、

天国なんてない。地獄もない。国境もない。所有しているものもない。

と歌っています。

是諸法空相 不生不滅 不垢不浄 不増不減

これもない。あれもない。ないない尽くし。このすべてを否定していくパワーが、般若心経のひとつの特徴で「イマジン」と類似しています。

まるで、ジョン・レノンの「イマジン」ではないか!すべてのことを打ち消して夢想する歌詞が般若心経に似ていることに気づきました。

出典:みうらじゅん 著 /『アウトドア般若心経』 /幻冬舎 /2007 年

湾岸戦争、9.11 同時多発テロ時など、この曲は放送禁止の措置が取られた過去が幾度としてありました。天国や宗教の存在の否定や、共有を強調する歌詞が共産主義的だというのが理由のようですが、国と国との争いに平和の象徴とも言えるこの曲が不都合であったことは誰が見ても明らかです。

ふと気を抜くと、これらのニュースは日常のように目の前を通り過ぎていきます。慣れ、無感覚、非日常が日常に溶け込み、受け入れてしまう恐ろしさ。

イマジン、そして般若心経から、否定することの大切さを学べます。

あとがき

終わってみると、想像以上の距離を歩いていました。

歩数 39,000 歩超、総歩行距離 30km 超の写経の旅となりました。

なぜこんな猛暑の中、誰に言われるでもなく、多くの人から見れば意味不明な苦行ともいえる行為を行ったのか? もちろん、自身で開発した Web アプリのドッグフーディングも兼ねていました。しかし、それだけではありません。ここ数ヶ月、やらなければいけないことに圧倒され、心身ともに疲れていました。焦りや不安、プレッシャーから逃れたいとの思いから、1 日だけでもアウトドア般若心経だけのことを考え夢中になれば、他のことを考えずに済むのではないかという不純な動機もありました。

悩みの中にいると、一生ここから抜け出せないような気になって、さらに悩みを深めます。どこかで断ち切りたいと思うのですが、それがどこなのかが分かりません。

出典:みうらじゅん 著 /『アウトドア般若心経』 /幻冬舎 /2007 年

炎天下の中、朦朧としながら歩いていると、

「こんなことして何の意味があるのか?僕は一体何をやっているんだろうか?」何度、自問自答したことでしょう。

しかし、不思議と歩き続けアウトドア般若心経に夢中になっていると、過去と未来に縛られることの無意味さ、自己への執着が「苦」を生み出していること、悩みの小さに気づきます。仏教でいうところの「無我」、つまり自分探しではなく、自分なくしの方が大事だよと般若心経は説きます。「無我夢中」になって写経に取り組むことで、般若心経の真髄にほんの少しだけ触れられた気がしました。

いくら考えても答えが出ないのは、そんなものは初めっからないからなんだよ。 ただ歩こうよ!意味を求めずに今を生きよう。

出典:みうらじゅん 著 /『アウトドア般若心経』 /幻冬舎 /2007 年

アウトドア般若心経(Web アプリ)は、企画から開発まで 8 ヶ月の歳月を要しました。長い長い開発の旅を終え、この度無事にリリースできたことを嬉しく思います。

今後もインターネットの世界でこのアプリが旅を続けられるように、これからも改善を続け、できるだけ長く運用を続けていければと思っています。ひとりでも多くのみなさんに楽しんでもらえると幸いです。

最後までお読みいただきありがとうございました!

2023 年 9 月吉日

お知らせ

Webアプリ開発についての技術記事も公開しています。個人開発に興味がありましたらぜひご覧ください。

shirotamaki.hatenablog.com

アウトドア般若心経の旅 〜沖縄ゆいレール編(前編)〜

はじめに

アウトドア般若心経とは

アウトドア般若心経とは、イラストレーターのみうらじゅん氏(以下「師」と称する)が提唱した「般若心経」の新しい写経方法です。

みうらじゅんは「般若心経」278 文字を、家を出て(これを「出家」と称す)、経文の文字のある市街の看板等の文字を写真に撮り(これを「写経」と称す)、経文の完成を目指すことを「アウトドア般若心経」と定義した。

出典:フリー百科事典『ウィキペディア(Wikipedia)

アウトドア般若心経が楽しめる Web アプリ

パソコン、スマホで使える Web アプリを開発しました。

無料でご利用いただけます。

今回のブログは、以下 Web アプリを手に街を行脚した旅の記録になります。

www.outdoor-heart-sutra.com

出発準備

持ち物

最低限スマホだけで十分ですが、今回は師の経典も持参することにしました。

マイウェア

先日届いたアウトドア般若心経T シャツと、強い日差しに備えサングラスを着用しました。

suzuri.jp

マイルール

徒歩以外の移動手段は、公共交通機関(モノレール、バス)のみ利用可とします。

沖縄の交通情報

モノレールは 1 日フリー乗車券があり「おとな / 800 円」で利用できます。注意したいのはバスです。沖縄のバスは、PASMOSUICA などの交通系 IC カードは使えません。IC カードを利用したい方は、沖縄専用の OKICA(オキカ)を購入しましょう。

出典:ゆいレール | 乗車券・運賃 / OKICA(ICカード

マイルート

ゆいレールの駅を起点に徒歩圏内で行ける場所を目的地としてマイルートを計画しました。

出典:ゆいレール | 路線図

写経の旅

9 月某日。天気は晴れ。8 月のピーク時と比べればだいぶ気温は下がってきたとはいえ、本日も最高気温 34 度と真夏日の予報。

果たして、今回の旅を通して何か気づきを得ることができるのか?そして無事に帰って来ることができるのか?

アウトドア般若心経の旅 〜沖縄ゆいレール編(前編)〜 始めます!

後編はこちら

スタート地点

ゆいレールの始発駅である那覇空港駅からスタートです。

那覇空港駅

「空」

まずは「空」を写経です!

そもそも始まりは街の駐車場の入り口に、「空アリ」の文字を見つけたのがきっかけでした。

出典:みうらじゅん 著 /『アウトドア般若心経』 /幻冬舎 /2007 年

師はアウトドア般若心経の始まりを、「空アリ」の駐車場の看板を見つけたのがきっかけであったと仰せでした。違いはあれど、般若心経の真髄である「空」の教えを学ぶ始まりとしては申し分ないでしょう。

もちろん、那覇「空」港ですので、見渡す限り「空」ばかりです。「空」は何もない状態を表していますが、「空」がこれだけいたるところに存在すると、なんだか「空」があるように思えてきます。

色即是空 空即是色

あるものがない。ないものがある。

長い長い旅の始まりです...

首里駅

今回の旅の目的はアウトドア般若心経を通して街の魅力にも触れることです。

筆者の出身地は那覇市ではありますが、人生の半分は県外で過ごしていたため、特に最近の市街はそんなに詳しくないのが正直なところ。首里駅に降りてはみたもののどうしたものか...。 降りる駅以外は何も決まっておらず、行き当たりばったりのノープラン旅です。

とにかく、まずは首里城を目指して歩いてみることにしました。

「識」

首里城に向かって歩いていると、幸先よく早速文字を見つけました!

識名酒造の看板から「識」を写経です。

識名酒造は、最古の古酒があることで有名な酒造です。

昔の沖縄には 100 年、200 年といった古酒が存在しましたが、第二次世界大戦の戦禍によりそのほとんどが失われてしまいました。現在沖縄で公表されている最も古いといわれている泡盛は、識名酒造の約 150 年ものの古酒といわれています。

www.shikinashuzo.com

「時」

沖縄の皆さんには馴染みのあるレトロな看板。

識名酒造さんの看板メニュー「時雨(しぐれ)」のラベルにも使われていますが、そこから「時」の文字を写経しました。

「時雨」という泡盛の名前の由来は、秋の末から冬の初めにかけて、ぱらぱら通り雨のように降る雨のように、さわやかな飲み口の泡盛をとの思いを込めて「時雨(しぐれ)」と名付けられたそうです。

出典:識名酒造

「道」

首里の「道」と言えばこれでしょう。

金城町石畳道(きんじょうちょういしだたみみち)です。琉球石灰岩が敷かれた石畳道で首里城まで道が続いています。数年前に来た時はもう少し看板の文字がハッキリと確認できたのですが、だいぶ薄くなっていました。

まさに「諸行無常」、文字が薄れていく様子からも般若心経の教えを学ぶことができます。

「真」

午前中の早い時間とはいえこの日も猛暑でとにかく暑い...。

金城町石畳道を登った途中にある茶屋で休憩でもと思い立ち寄ることにしました。

しかし残念ながら開店前でオープンしていません。

度一切苦厄

ここでいう「苦」は「苦しい」ではなく、「思いのままにならないこと」を表しています。「四苦八苦」も仏教用語ですが、「四苦」は、生・老・病・死の四つの苦しみ。「八苦」は、この四苦に愛別離苦(愛するものと別れる苦しみ)・怨憎会苦(憎むものと出会う苦しみ)・求不得苦(求めても得られない苦しみ)・五陰盛苦(心身の苦痛)を加えたものです。「四苦八苦」で、ありとあらゆる苦しみのことを表現しています。そして「度」は「解き放たれる」という意味ですが、思いのままにならないことをどうやって受け入れるのか? 般若心経では説かれます。

とはいえ、まだまだ煩悩にまみれている筆者には「苦」の開放は 1 ミリとも訪れず、逆にあまりの暑さから「憤」すら感じていました。

しかしそんな暑さと憤りが沸点に到達したとき、茶屋の看板に「真」の文字を発見したのです!

ここでもまたひとつ般若心経の教えから学ぶことができました。

首里城

その後、目的地の首里城へ。

2019 年の火災以来の訪問です。首里城が過去の大戦で焼失したことは広く知られていますが、実は過去に 5 度もあったことはあまり知られていません(1453 年、1660 年、1709 年、1945 年、2019 年)。2019年の火災では、正殿をはじめとする 9 施設が焼失してしまいましたが、その後の復興の様子を見ることができとても感慨深かったです。

仏教の根本思想でもある「 諸行無常」、人も、物ごとも、永遠のものは存在しないということを改めて痛感しました。

「空」

首里城を後にし次の目的地へと向かう途中、ローソンがあったのでさんぴん茶でも買おうと思って立ち寄りました。

外観が首里城仕様になっていて面白いと思いパシャリ...

... ?(違和感)

外観とマッチしすぎていて気づきませんでしたが、よく見ると「空」の文字が!!

自治体の景観条例によるものかと思いますが、街に馴染み素敵です。

これらタイプの看板は、京都や鎌倉など観光地でよく見かけますが、ここにも「空」の思想が見え隠れします。

是故空中 無色

「青、緑、赤...。 色はいらない。こだわりを捨てなさい」と。

シンプルな看板が教えてくれます。

栄町駅

探しものは何ですか?

次の目的地の「栄町市場」に向かいます。

カオスな街の様子から何かあるのでは?と感じさせる「栄町市場」です。

時間帯的にお昼前だったのもあり、どこかでお昼ごはんでもと思い写経ついでにお店も探してみることにしました。

しかしこれまた早すぎた時間が仇となり、精肉店など市場のお店はやっていましたが、飲食店はほとんど開いていません。また看板も多数ありますが、なかなか般若心経の文字を見つけることができませんでした。

半ば諦め場所を移動しようと思ったとき、井上陽水風の男性から声をかけられました。

筆者が観光客に見えたのか?道に迷っていると思われたらしく「どこに行きたいんですかぁ?」と声をかけられました。

アウトドア般若心経やっているんですよ」と伝えたところで不審者がられるだけなので、栄町駅までの道を聞いたところ、丁寧に教えてくれました。

聞いてもいないのですがなぜか「飲み屋は早い時間帯はほとんどやっていないさ〜。夕方ごろにまた来た方がいいさ〜」とアドバイスをいただき、「そこでお店やっているから次来た時は飲みに来たらいいさ〜」と誘われました。完全に市場に迷い込んだ観光客だと思われているようでした。

ちょっと強面で掛けているグラサンやファンキーな風貌もあってか、最初は身構えてしまいましたが、話してみるととてもいい人で、自由な空気を身にまとったその男性からは微かにココナッツの甘い香りがしました。その瞬間、ふと頭にこの曲が流れました。


師はこの曲をとても仏教的だと言います。

“探し物はなんですか?見つけにくいものですか?”から始まって、“それより僕と踊りませんか?”ってね。そこから見方を変えたんです。必死で探すから見つからないんだって悟ったんですよ。そして無心になって街を歩き回り、最終的に全文字揃えたってわけです。 つまり真理は、『それより僕と踊りませんか?』でね。探したところにはないんですよ、欲しいものは。目的を決めないで行ったときに、たまたま見つかる。狙って行く方が、すごく無駄だってことでしたね。

出典:IMA プロジェクト『みうらじゅんインタヴュー「“ない”写真の作り方」

男性に礼を言い、次は夕方に再訪し飲み踊り明かそうと誓い、栄町市場を後にしました。

美栄橋駅

軽食の店 ルビー

次に降り立った駅は「美栄橋」

栄町市場でお昼を逃したため、急遽予定変更です。食を求めやってきました。

当 Web アプリはバックエンドでRubyプログラミング言語)を使っています。そんな Ruby に敬意を表し、Rubyist 御用達?のお店に向かうことにしました。

駅から徒歩で向かうには結構な距離です(往復 30 分ぐらいかかります)。普段は車で行くような距離感のお店ですが、覚悟を決め歩みを始めました。炎天下の中ひたすらルート 58 を北上すると左手におなじみのあの看板が見えてきます。

オレンジの看板が眩しい!

軽食の店 ルビー 泊店 - 美栄橋/食堂 | 食べログ

看板に軽食とは書いていますが、全然軽食じゃないです。むしろ重い。そんなボリューミーかつ豊富なメニュー数を誇る地元民からも愛される名店です。

ランチは A にしようか?B にしようか?それともCか?と悩みつつ、店内に向かうと...

「?」

何かがおかしい。もう 12 時前だというのに人の気配がまったくしない。

それもそのはず、今日(水曜日)はまさかの定休日。完全に火曜日が定休日だと思い込んでいました。

Ruby Tuesday ...。大好きな The Rolling Stones が一瞬嫌いになりそうでした。

あ、そんなストーンズですが、10 月 20 日に 18 年振りのスタジオ・アルバムを発売しますね(楽しみ)

rollingstonejapan.com

ストーンズ のように止まらず転がり続けたいところですが、さすがにここまで来ての定休日は凹みます...。まさに徒労。

「タクシーに乗りたい。もうやめたい...」

「一体、僕は何のためにこんなことをしているんだろうか...」

あまりの暑さから朦朧とし、邪念が頭をよぎります。

果たして、この後もアウトドア般若心経の旅を続けることができるのか?

後編に続く...

Fly.io の Volumes から AmazonS3 に乗り換えた

はじめに

Next.js と Rails を使ってオリジナルの Web アプリを開発しています。

github.com

前回の記事で Fly.io の Volumes を外部ストレージに設定しましたが、Amazon S3 に乗り換えることにしました。

shirotamaki.hatenablog.com

今回の記事は、乗り換えた理由と乗り換え後の Amazon S3 の設定手順についてまとめた内容になります。

Fly.io の Volumes の導入を取りやめた理由

当初は Volumes の設定は上手くいき問題ないと思っていましたが、本番環境で写真の保存を繰り返す上で、保存ができないバグが頻繁に発生していました。

原因を調べていく中で「Volumes の選択は適当ではない」との結論に達しました。

公式には「Volumes ダメ!ゼッタイ!」と明示されているわけではありません。これはあくまで私の開発環境に基づく結果です。Fly.io のRails Specialist より頂いた「Rails では Amazon S3、GCS、Microsoft Azure を推奨している」とのアドバイスが決め手となり、Volumes の導入は断念することにしました。

正しい Volumes の構成

まず、Volumes の理解が正しいのか確かめました。

Volumes の構成図 になります。

I would diagram it like this:

fly.io_volumes.png

ここでのポイントは、App1 というひとつの App の枠の中に、VM(Machine) が 2 台存在し、VM は 1 台の Volumes に紐づいているということです。この場合 Volume1,2 と存在しますが、Volues1,2 間は連携されていなく、Volume1 に保存された外部データは Volume2 には存在しません。そのため、App が特定の VM を利用する時、例えば VM1 は Voluse1 に保存したデータしか取り扱うことができません。各々に保存されたデータを取り扱うには、Volume 間で連携できるように別途手配が必要とのことです。

対応策として、mirrorのようなツールを利用し連携を行うことも可能のようですが、Fly.io で試した人はいないとのことです。

Amazon S3 を選択する

バグの原因がわかったところで代替案として、Rails が推奨する方法から選択することにしました。

Active Storage は、Amazon S3Google Cloud Storage、Microsoft Azure Storage などのクラウドストレージサービスへのファイルのアップロードや、ファイルを Active Record オブジェクトにアタッチする機能を提供します。 development 環境と test 環境向けのローカルディスクベースのサービスを利用できるようになっており、ファイルを下位のサービスにミラーリングしてバックアップや移行に用いることも可能です。 Active Storage は、アプリケーションにアップロードした画像の変形や、PDF や動画などの画像以外のアップロードファイルの内容を代表する画像の生成、任意のファイルからのメタデータ抽出にも利用できます

Active Storage の概要 - Rails ガイド

Don't use Disk service unless you put the data on a Volume and are prepared to sync the data between machines If you want to have your active storage data hosted on fly.io, consider using the postgres adapter or MinIO. Of course, you are welcome to use Amazon S3, Microsoft Azure, or Google Cloud Services.

Existing Rails Apps · Fly Docs

データを Volume に保存し VM 間でデータを同期させない場合は、利用はしないようにと書いてあります。代わりに Amazon S3, Microsoft Azure, or Google Cloud Services を選択しましょう。ということです。

決め手となったRails Specialistからのコメントです。

Rails clearly recommends Amazon S3, GCS, and Microsoft Azure for this purpose.

以下、Fly.ioの公式フォーラムでのやり取りです。

community.fly.io

参考

Amazon S3 を設定する

外部ストレージとして選択した Amazon S3 を設定します。

  1. アカウントを新しく作成する

    • 一度解約したアカウントに紐づけているメールアドレス(当時個人のメインアドレスで開設し解約済み)で新たにアカウントを作り直すことはできない。
    • 新しくメールアドレスを作成し新たにアカウントを開設した。
  2. IAM アカウントを作成する

    • IAM アカウント(IAM ユーザーとも呼ばれる) とは、環境(テナント)内で、IAM を使って払い出しが行われる操作アカウントのこと。
    • 作成しただけでは何も行えず、その操作に即した権限を付与することで、付与された権限に応じた操作を実行することができる。
    • IAM とは、AWS サービスの一つで「Amazon Identity and Access Management」の略名。
  3. バケットを作成する

  4. Gemfile に aws-sdk-s3 gem を追加しインストールする

  5. access_key_id、secret_access_key を取得して Rails に設定する

# backend/config/storage.yml

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: "ap-northeast-1"
  bucket: "outdoor-heart-sutra-backend-storage"
# backend/config/environments/production.rb

config.active_storage.service = :amazon

Fly.io の Volumes を試してみた

はじめに

Next.js と Rails を使ってオリジナルの Web アプリを開発しています。

github.com

当Webアプリには写真保存機能があり、Rails の ActiveStorage を介して外部ストレージに保存する構成にしています。本番環境の外部ストレージをFly.io の Volumes で試してみることにしました。

先に結論から申し上げると、私の開発環境では Fly.io の Volumes は本番環境のストレージとして不向きでした。結果的には外部ストレージは AmazonS3 に乗り換えることになりましたが、Fly.io の Volumes は、まだ日本語の情報も少なく自分と同じくハマる人がいるのではないかと思い、今回試した結果をまとめることにしました。この記事が何らかの形でお役に立てれば幸いです。

以下は、AmazonS3 に乗り換えた記事になります。

shirotamaki.hatenablog.com

Fly.io の Volumes とは

Fly.io が提供している永続的なストレージのことです。

物理サーバー上の NVMe ドライブを分割して提供しているハードウェアで、データベースのファイルを保存したり、設定やセッション、ユーザーデータなどのアプリの状態を保存したり、デプロイや再起動後に持続する必要がある情報を保存したりすることができます。デフォルトのボリュームサイズは 3GB になります。最大サイズは 500GB。分割も可能のようです。

Databases & Storage · Fly Docs

Volumes 利用時に考慮すべき内容

  • Volume は、1 つのアプリに紐付く
  • Volume は、1 つのリージョンしか指定できない。リージョンの複数指定は不可
  • Volume は、1 つの Machine(VM)に紐付ける必要がある。Volume と Machine は 1 対 1 でマッピングが必要
  • Volume は、Volume 内で自動的に複製は作られない
  • Volume は、ホストする NVMe ドライブが故障すると、アプリのインスタンスがダウンする。アプリの Volume を持つ複数の Machine を実行することでハードウェアの障害を軽減することができる
  • Volume は、万が一ドライブが故障した場合はデータが失われてしまう。バックアップ方法は別で検討する必要がある

Volumes · Fly Docs

Volumes 設定時のルール

  • 1 つのアプリにつき少なくとも 2 つの Volume の実行が必要
  • 1 つの Volume は 1 つの Machine にのみ接続が可能
    • そのため、2 つの Volume を準備する場合は、2 つの Machine を用意する必要がある

Volumes · Fly Docs

無料枠

今回は無料枠内で設定を行いました。

  • Up to 3 shared-cpu-1x 256mb VMs
    • VM は Machine のこと
  • 3GB persistent volume storage (total)
    • 今回は 1GB を 3 つ用意する
  • 160GB outbound data transfer
    • outbound data transfer とは、コンピューターネットワークや通信分野において、外部へ転送されるデータ(HTTP 通信)のこと

Fly App Pricing · Fly Docs

Fly.io を初期化する

fly launch済みだったので、途中の設定から進めましたがうまくいかず...。コミュニティに質問を投げたところやり直した方がいいとのことで、初期化してやり直すことにしました。

fly launchは、Fly.io を立ち上げるコマンドになります。Rails アプリをデプロイする前段階の必要な設定を自動で行ってくれます。

登場人物

  • Machine(VM):3 台
  • Volume:3 台 × 1GB
  • App :Rails API を用意する( App 名:outdoor-heart-sutra-backend)
  • DB: PostgreSQL を用意する(DB 名前:outdoor-heart-sutra-backend-db)

Fly.io を初期化しデプロイをやり直す手順

1 . Fly.io のダッシュボードからアプリと DB を削除する

Dashboard_·_Fly.png

2 . ローカルのDockerfilefly.tomlを削除する

3 . fly launch を実行する。

Image

4 . 新しいDockerfilefly.tomlが生成される。

5 . fly deployをする

6 . もし You hit a Fly API error with request ID: XXXXXX に遭遇しても慌てない。再びfly deployをする。成功するまで何回もやり直す(サーバーが混雑していて一時的に通信できていない可能性が高い)

7 . 上手く行ったらfly open する。

8 . 設定が反映される。

Flyioにデプロイできないときの対処法と、ActiveStorageをfly.ioで動かす方法 by lef237 · Pull Request #54 · lef237/quotelist · GitHub

fly launch 後の状態

fly statusで状態の確認が可能です。

デフォルトで、Machine が 2 台用意されています。fly launch時に指定したリージョンnrt(東京)が設定されていることが確認できます。

❯ fly status
App
  Name     = outdoor-heart-sutra-backend
  Owner    = personal
  Hostname = outdoor-heart-sutra-backend.fly.dev
  Image    = outdoor-heart-sutra-backend:deployment-01H2MXM3JKRRCQNPMEESTRGE4D
  Platform = machines

Machines
PROCESS ID              VERSION REGION  STATE   CHECKS  LAST UPDATED
app     148ed5d5a3d668  5       nrt     started         2023-06-11T11:05:20Z
app     4649xxxxxxxxxxx 5       nrt     started         2023-06-11T11:05:20Z

fly volumes listで Volume の設定状況が確認できます。Volume はまだ設定していないので何も表示されません。

❯ fly volumes list
 ID STATE   NAME    SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM CREATED AT

Volume を作成

Volume を作成します。ストレージ名は、英数字、アンダースコアのみ使用可能です。

❯ fly volumes create <ストレージ名> --region <リージョン名> --size <サイズ>

- ストレージ名:outdoor_heart_sutra_backend_data
- リージョン: nrt(東京)
- サイズ: 1GB

警告が表示されますが無視します。

❯ fly volumes create outdoor_heart_sutra_backend_data --region nrt --size 1
 Warning! Individual volumes are pinned to individual hosts. You should create two or more volumes per application. You will have downtime if you only create one. Learn more at https://fly.io/docs/reference/volumes/
 ? Do you still want to use the volumes feature? Yes
         ID: vol_lgz1vpp7j7kv78m3
       Name: outdoor_heart_sutra_backend_data
        App: outdoor-heart-sutra-backend
     Region: nrt
       Zone: 6082
    Size GB: 1
  Encrypted: true
 Created at: 10 Jun 23 08:12 UTC

Volume が 1 台追加できています。

MachineID 148ed5d5a3d668 と VolumeID vol_lgz1vpp7j7kv78m3マッピングに成功しています。

❯ fly volumes list
ID                      STATE   NAME                                SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM     CREATED AT
vol_lgz1vpp7j7kv78m3    created outdoor_heart_sutra_backend_data    1GB     nrt     e73c    true        148ed5d5a3d668  1 day ago

Add Volume Storage · Fly Docs

Machine と Volume の対を 1 組追加する

Machine を削除する

先に不要になった Machine を削除します。

Machine 対 Volume のマッピングしたセットをもう一組追加したいのですが、クローン 方式で行うことにします。

まず先にマッピングしていない Machine を削除します。

❯ fly machine destroy <削除したいMachineID>
 machine <MachineID> was found and is currently in stopped state, attempting to destroy...
 <MachineID> has been destroyed

Scale the Number of Machines · Fly Docs

クローンする

すでにマッピング済みの MachineID を引数に渡し clone を実行します。

 fly machine clone 148ed5d5a3d668
 Cloning machine 148ed5d5a3d668 into region nrt
 Volume 'outdoor_heart_sutra_backend_data' will start empty
 Provisioning a new machine with image registry.fly.io/outdoor-heart-sutra-backend:deployment-01H2JH5NCPN0X4RV99W0D1WB9N@sha256:c4bb537636be6b041fe026bd04f7bbccc50b2c7c50dd17b08d7c9b7f34d52312...
   Machine 5683d3d0bd40d8 has been created...
   Waiting for machine 5683d3d0bd40d8 to start...
 No health checks found
 Machine has been successfully cloned!

クローン後の結果

Volume2 台のマッピングが成功しています。

❯ fly volumes list
ID                      STATE   NAME                                SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM     CREATED AT
vol_3q80vd3wlwkrgzy6    created outdoor_heart_sutra_backend_data    1GB     nrt     a588    true        5683d3d0bd40d8  1 day ago
vol_lgz1vpp7j7kv78m3    created outdoor_heart_sutra_backend_data    1GB     nrt     e73c    true        148ed5d5a3d668  1 day ago

fly statusで確認ができます。Machine が 1 台追加され合計 2 台になっています。

❯ fly status
App
  Name     = outdoor-heart-sutra-backend
  Owner    = personal
  Hostname = outdoor-heart-sutra-backend.fly.dev
  Image    = outdoor-heart-sutra-backend:deployment-01H2QVEXXPGDS97AXPJQC5Q3PQ
  Platform = machines

Machines
PROCESS ID              VERSION REGION  STATE   CHECKS  LAST UPDATED
app     148ed5d5a3d668  11      nrt     started         2023-06-12T14:32:13Z
app     5683d3d0bd40d8  11      nrt     started         2023-06-12T14:33:35Z

Volume をマウントするために App を設定する

新しい Volume をマウントするために設定が必要です。fly.toml とは、Fly.io アプリケーションの設定ファイルです。Fly.io は、このファイルに従ってデプロイと実行を行います。

Active storage images are not persisting in disk

 # backend/fly.toml

app = "outdoor-heart-sutra-backend"
primary_region = "nrt"
console_command = "/rails/bin/rails console"

[env]
  RAILS_STORAGE = "/mnt/volume/storage"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[statics]]
  guest_path = "/rails/public"
  url_prefix = "/"

[[mounts]]
  source = "outdoor_heart_sutra_backend_data"
  destination = "/mnt/volume"

storage.yml ファイルでは、Active Storage がどのようにファイルを保存するかを設定します。

# backend/config/storage.yml

local:
  service: Disk
  public: true
  root: <%= ENV.fetch('RAILS_STORAGE', Rails.root.join("storage")) %>

デプロイする

❯ fly deploy

PostgreSQL

fly launch時に Postgresql をデータベースに設定したので、

243152027-8749019e-017b-46b4-8788-9353c23194bb_png__2016×2610_.png

以下、自動で生成されます。

名前は App 名の後ろに-dbと付きます。

❯ flyctl status -a outdoor-heart-sutra-backend-db

ID              STATE   ROLE    REGION  CHECKS              IMAGE                               CREATED                 UPDATED
5683d3d3ad1338  started primary nrt     3 total, 3 passing  flyio/postgres-flex:15.3 (v0.0.42)  2023-06-10T11:28:31Z    2023-06-10T11:28:46Z

Free builder とは

Free builder というアプリは、デプロイ用に自動的に作成されます。

デプロイ時に fly CLI は自動的にアプリを作成し、そのアプリを使用してデプロイビルドを実行してくれます。デプロイをやり直す時に削除しても問題ないようです。万が一削除しても、次にデプロイするときに再び作成されます。

Cursor_と_Dashboard_·_Fly.png

Free builder is created by itself. - Questions / Help - Fly.io

おわりに

これで Fly.io の Volumes の設定は完了です。

しかし、冒頭でも案内した通り、結果として今回は Volumes の導入は断念し Amazon S3 に乗り換えることにしました。

詳細は以下記事にまとめています。

shirotamaki.hatenablog.com