きゃんブロ

きゃんなブログ

【Fly.io×Active Storage】画像が表示されたりされなかったりする現象はなぜ起こるのか

fly.ioでボリュームを作成し、マシンに接続。 無事に本番にもデプロイして画像の保存を永続化できた...!

...けれどなぜか画像が正常に表示されない😭表示されたりされなかったりする😭😭😭

このような自体になっていませんか?

今回はこの現象はなぜ起こるのか?を説明します。

fly.ioでは2つのマシンを持つことを推奨

fly.ioでは、マシンを2つ持つことが推奨されています。 これはなにを意味するかというと、ボリュームも2つ持たなくてはならないということです。

マシンに対し、接続できるボリュームはひとつだけです。 マシンを2つ持つのであれば、ボリュームも2つにしなければいけないのです。

そして、マシンはお互いに独立し、ボリュームもお互いに独立します。 ボリューム同士は同じデータを共有することはありませんし、1つのマシンで2つのボリュームの面倒を見ることはできません。

まずはこれをご理解いただければと思います。

マシンとボリュームを2つずつ持つことによる弊害

マシンとボリュームは1対1で接続されるとお話しました。 これを2つ持っている状態を絵に表すと、こうなります。

1つのアプリの中に2つのマシンを持っている様子
1つのアプリの中に2つのマシンを持っている状態

ここでは仮にマシンAがボリュームAに接続されており、マシンBがボリュームBに接続されているとします。

この状態で、あなたのアプリ上でユーザーが画像を登録したとします。 すると、現在アプリを動かしているマシンに接続されている方のボリュームに入ります。

ボリュームAに画像が保存されている様子
ボリュームAに画像が保存されたとする

ボリューム間でデータが共有されることはないので、どちらかのボリュームにデータが入ることになります。 ここまでくれば、なんとなく察しはついたのではないでしょうか。

そうです。ボリュームAに保存された画像を再び引っ張ってくるためには、マシンAに接続する必要があります。 なぜなら、マシンAに接続されているのはボリュームAのみで、マシンBからボリュームAを見に行くことはできないからです。

そのため、リロードをすると画像が表示されたりされなかったりという現象が起こるわけです。 これは、アプリがマシンAとマシンBを持っていて、リロードする度にマシンAでアプリを起動したり、マシンBでアプリを起動したりするからです。

ボリュームBを見に行っても保存した画像データがない様子
ボリュームBを見に行っても保存した画像データはない

これを解決するには?

これを解決するには、他の方法でボリューム間のデータを共有するようにする必要があります。残念ながら、fly.ioの力だけで解決する手段は現時点では存在しないようです。

もしどうしてもfly.ioとActive Storageを利用したい場合は、マシン1つで稼働しなければいけません。しかし、これは公式が推奨する2台のVMで稼働するというものに反するものなのでおすすめしません。(小規模なアプリであれば大丈夫かもしれないですが、自己責任でお願い致します。)

アプリ上でユーザーが登録した画像を永続的に見せたい場合は、他の手段を探してみましょう。

参考