AWS

アプリのバッチ処理は書きたくない!S3にアップされた一時画像をライフサイクルで自動削除してみた

はじめに

現在運用しているWebサービスのお問い合わせフォームには、ユーザーが画像を添付できる機能があります。

画像にはユーザーの個人情報や画面のキャプチャなどが含まれるため、S3バケットは当然パブリックアクセスブロック(完全非公開)に設定し、管理画面からは署名付きURL(Pre-signed URL)を発行して表示するセキュアな構成にしています。

ただ、ここで一つ問題が。 「サポート対応が終わったあとの画像、ずっとS3に残り続けるの嫌だな……」

そのまま放置するとストレージ代の無駄ですし、セキュリティ的にも不要なデータはさっさと消したい。でも、わざわざ「30日経過した画像を削除する」みたいなバッチ処理(Cron)をアプリ側で書いて管理するのは面倒くさい……。

S3の「ライフサイクルルール」を使えば、特定のディレクトリ(プレフィックス)だけを狙い撃ちして自動削除できることは知っていたので、今回はこの機能を使ってインフラ側でサクッと解決することにしました。

今回の要件(やりたいこと)

  • 対象バケット: demo-private-2026(完全非公開)
  • 対象ディレクトリ: inquiry-images/ 配下のファイルのみ
  • アクション: アップロードから30日後に自動的に削除する
  • ※同じバケット内にある別のシステム用フォルダのファイルは絶対に消さない!

さっそく設定してみた

AWSマネジメントコンソールからS3の画面を開き、対象のバケットを選択して作業スタートです。

  1. ライフサイクルルールの作成画面へ
    バケットの詳細画面から「管理」タブを開き、少し下にあるライフサイクルルールの「ライフサイクルルールの作成」ボタンをポチッと押します。


  2. ルールの対象(プレフィックス)を絞り込む
    ルールの作成画面が開きました。ここが今回一番緊張するポイントです。設定をミスるとバケット内の全ファイルが消し飛びかねません。
    • ライフサイクルルール名: 自分が後から見て分かるように Delete-Inquiry-Images-30days と命名。
    • ルールのスコープ: 「1つ以上のフィルターを使用してこのルールのスコープを制限する」を選択。
    • フィルタータイプ(プレフィックス): ここに inquiry-images/ と入力!


  3. 何日後に消すかを設定する
    次に「どういうアクションをするか」を設定します。
    今回は「30日後に消去」したいので、以下の通り設定しました。
    • ライフサイクルルールのアクション: 「オブジェクトの現行バージョンの有効期限が切れる」にチェックを入れる。
    • 日数: 出現した入力欄に 30 と入力。



      最後に画面の一番下にある「ルールの作成」ボタンを押せば完了です!

設定完了!しかし削除の「タイミング」に要注意

ライフサイクルルールの一覧画面に戻ると、今作ったルールが表示されていました。設定自体はめちゃくちゃ簡単です。

しかし、テストをしていて「あれ?」と思うことがありました。 アップロードしてからピッタリ30日後の同じ時間になっても、画像が消えていなかったのです。機能自体は知っていましたが、厳密な削除タイミングまでは把握していなかったので、気になって調べてみました。

すると、S3のライフサイクルルールの「日数計算」には少し特殊なクセがあることが分かりました。

削除されるのは「アップロード時刻からきっちり30日後」ではない

S3のライフサイクルルールの時間は、基本的に世界標準時(UTC)の0時、つまり日本時間(JST)の朝9時が基準になります。

AWSの仕様では、アップロードされた時刻に「指定した日数(今回は30日)」を足して、その直後に来る「翌日のUTC0時(日本時間の朝9時)」に有効期限が切れるという計算になるそうです。

具体例で考えてみる(10月15日の14時にアップロードした場合)

  1. 10月15日の14:00に画像をアップロードする。
  2. これに30日を足すと、11月14日の14:00になる。
  3. その直後に来る「翌日の日本時間 朝9時」は、11月15日の09:00。

つまり、10月15日の14時にアップロードした画像がライフサイクルルールによって削除対象になるのは、「11月15日の朝9時」ということになります。(実質30日+19時間かかっていることになりますね)

さらに、朝9時になった瞬間にシュッと消えるわけではなく、そこからS3の裏側の非同期処理で削除が順次実行されるため、実際にバケットから消えるまでにはさらに数時間のタイムラグがあるようです。

厳密に「1秒の狂いもなく30日後に消さなければならない!」という要件だとこの機能は使えませんが、今回のような「サポートが終わった古い画像が、だいたい1ヶ月くらいで勝手にお掃除されていればOK」という要件なら、全く問題ありません。

おわりに

バッチ処理のコードを数行から数十行書いて、定期実行のインフラを用意して、エラーハンドリングをして……という手間を考えたら、AWSコンソールからポチポチ設定するだけで完全自動化できるのは本当に最高でした。

「日数の計算は日本時間の朝9時が基準で、切り上げになる」という点だけ理解しておけば、非常に強力で便利な機能です。

プライベートバケットでも問題なく動くので、ユーザーの一時ファイル(CSVエクスポートの一時保存や、一時的なバックアップなど)を扱う際には、この「特定のプレフィックス+ライフサイクルで自動削除」をどんどん使っていこうと思います。

同じように「S3のゴミ掃除バッチ書きたくないなー」と思っている方の参考になれば幸いです!

天前智矢

天前智矢

企画開発部 マネージャー 愛犬ファーストのエンジニア

関連記事