👌

【assets-syncer】個人開発で使える最強の画像サーバを作りたい話

2022/02/20に公開

【assets-syncer】個人開発で使える最強の画像サーバを作りたい話

個人的にいい感じの画像サーバを作ったのでブログとして書き留めておく。

2022/03 追記) 今回は楽しくなって Ruby + Docker で実装したが、macOS なら fswatch を使ってファイル監視時の処理を作っていく方が多分良い。(gulp とか使うのもあり?)

作ったもの

trim D9D9155D-3004-4BF2-9E2D-1481599842FE 2
https://images.igsr5.com/l/profile.png で公開

モチベーション

自分でサービスを作る際の画像に関する仕組みを整えたい

普段プライベートでサービスを作る際に「画像をどこから配信しよう」と考えることが多く、それを考えなくていいような仕組みを作りたかった。最近だとポートフォリオ制作の際にプロフィール画像や制作実績の画像をどこから配信するかで少し考えた。

具体的には

  • 各制作物ごとに画像配信元がバラバラ
    • 毎回ドメインやキャッシュのことを考えるのが面倒
  • 開発時にローカルリポジトリに画像ファイルを置いて開発するのが面倒
    • 気軽に画像を差し替えたい

などの悩みがあった。

デザイン

汎用画像サーバと開発用の便利ツールを作った。

汎用画像サーバ

画像配信は s3 + CloudFront のとてもシンプルな構成になっている。ドメインは images.igsr5.com

画像例 https://images.igsr5.com/l/sample.png

インフラ構成図

Screen Shot 2022-02-20 at 14 50 01

ref. https://carefree-se.hatenablog.com/entry/2019/10/16/094940

ちなみに個人開発で用いる全てのインフラリソースは https://github.com/igsr5/igsr5-terraform で terraform + GitHub Action を用いて管理している。

assets-syncer

開発用に簡単に画像をアップロード、配信できる便利ツール。
https://github.com/igsr5/assets-syncer

trim D9D9155D-3004-4BF2-9E2D-1481599842FE 2
https://images.igsr5.com/l/profile.png で公開

上のように特定のディレクトリにファイルを配置すると s3 バケットの /l/ ネームスペース配下に同期される。(開発用に配信URLのネームスペースを分けている)

設計

aws s3 sync を実行するスクリプトを docker コンテナ内で定期実行している。

/job/sync_s3.rb
# /job/sync_s3.rb 一部抜粋

# ジョブ開始時にs3 オブジェクトをローカルにコピーする。
system('./pull_images.sh')

loop do
  system('./sync_images.sh')

rescue StandardError => e
  logger.error(e)
  break
end
/sync_images.sh
# /sync_images.sh 一部抜粋

#!bin/bash
aws s3 sync ./images $AWS_S3_BUCKET_PATH --delete

(ログ周りの処理は省略)

docker コンテナは restart: always オプションを指定し、常に起動するようにしている。

リポジトリ内の /images 配下が s3 バケットと同期されることになるので、 images ディレクトリを Finder のスライドバーに置いて開きやすいように運用している。

より詳しい設計、実装はGitHubリポジトリを見るとわかる。

作った感想

全体的にとても単純に設計になっているが、assets-syncer はとても便利なものとなった。
具体的にはサービスを作る際、ちゃんとした画像アップロードの仕組みが整うまでの画像配信の仕組みを整えることができた。

また、今回シェルスクリプト等のコマンド処理をローカルで定期実行する仕組みに初めは cron や launched を検討したが、ruby でデーモンを実装し、それを docker コンテナ内に常駐させるという方法をとった。

これは思いつきであったが、リポジトリ内で仕組みを完結させることができたり、ログ管理などを追加する際に柔軟性があったり、とても良かった。

今回は開発用途に特化して画像配信の仕組みを作ったが、本番用途でも使えるように画像加工やs3 クライアントをラップした便利ライプラリなどの仕組みも整えていきたい。

Discussion