たくさんの自由帳

Amazon S3 と Lambda で画像を小さくして配信する

投稿日 : | 0 日前

文字数(だいたい) : 12629

どうもこんにちは、飲み会した。
今回の記事で作ったAmazon S3+Lambda+CloudFront画像変換&配信システムのお陰で、ちゃんとUltraHDRの画像が貼れているはず。

おさけ

おさけ

おさけ

飯もあります。
飯テロするか~~~w

ごはん

ごはん

そういえば言われた。
わたし、更に痩せたらしい。のでいっぱい食べてきた。

本題

UltraHDRをブログに貼りたい。が、世の中のサービスはUltraHDR無視されてJPEGになってしまうので、UltraHDRのまま配信出来る何かを探す必要があった。
あと、ブログ用に画像をGIMPで小さくしてるけど手間だし自動でやってほしいし、そもそもUltraHDRは無理だからそれもなんとかしたい。

Lambda でリサイズからの S3 + CloudFront で配信

これだ。よくあるAWSサーバーレス入門みたいなやつ。
S3バケットにブログに貼りたい画像をアップロードすると、Lambdaが起動して、ImageMagickを使って半分くらいのサイズにしたあと、
リサイズ保存用S3バケットに放り込まれるようにし、このバケットをCloudFrontで配信する。完璧じゃん。

作戦

S3に画像を放り込んだらAWS Lambdaが起動して、ImageMagickで変換する。
できる限りそのままの画像をアップする/originalと、ブログに乗せる用に小さくした/resizeへそれぞれ画像を配置する。

変換過程ですが、画像をアップロードするとUUIDが払い出され、できる限りそのままの画像と、配信用に半分くらいにした画像が保存されます。
おなじUUIDになる。

  • /original/{UUID}.{拡張子}
    • 投稿した動画をできる限りそのままの画質で保存します
    • 基本的には小さくした画像を使うので、使いません、、
  • /resize/{UUID}.{拡張子}
    • ziyuutyou ブログに貼る用

構成図

CloudFrontの部分はAWS S3+CloudFrontで静的サイトの記事で触ったので、あんまり触れません、、
今回の記事はAWS Lambdaで画像をリサイズしたいので。

Imgur

つくる

  • AWS Lambdaで動くUltraHDR付きImageMagickを作る(一番大変)
  • S3の受け付け用、配信用バケットを作る
  • Lambdaで動かすためのコードを書く
  • S3をトリガーに起動するようにする
  • (任意) CloudFrontで配信する

Lambda で動く UltraHDR 付き ImageMagick をビルドする

画像を小さくするためのImageMagickLambdaで動くようにビルドします

Lambda で ImageMagick を動かすためには

いまNode.jsで画像のリサイズをしたいならsharpってのが良いらしいんですが、
UltraHDRに対応していないので今回はImageMagickにします。

ImageMagickのビルドだけならそんなに難しくない。
https://takusan.negitoro.dev/posts/imagemagick_build_add_ultra_hdr/

ただ、それはお使いのマシンに既にインストールされている(もしくはインストールした)libjpeg-devlib-pngに依存しているからで、
パッケージを新たに入れることが出来ない(yum install 出来ない)AWS Lambdaでは、少し考える必要があります。

LambdaにはLambda Layerと呼ばれる機能があり、Lambdaが動くマシンに依存関係を配置させる事ができます。
この機能を使い、必要なバイナリをすべて同梱して、Lambda Layer機能を使い、LambdaのマシンにImageMagickのバイナリや必要なライブラリを配置させます。

と、いうわけで、今回はLambdaで動くImageMagick (ライブラリ同梱済み)を作ろうと思います。

ライブラリ同梱の詳細

先述の通りAWS Lambda環境下では、apt install等でインストールする事がが出来ないため、
libjpeg-dev相当のライブラリもImageMagickと一緒に同梱する必要がある。そのせいでビルドが結構面倒なことになってる。

今回は必要なライブラリをすべて/optにインストールすることにします。(/opt/bin/opt/libみたいになる)
なぜかと言うと、これで/optをすべてzipに固めてLambda Layerに登録すれば、パスが通った状態になるんですよね。
Lambda Layer/binにパスが通った状態になるそう)。

ビルド準備

Amazon Linux 2023WSLで起動する方法があるそうなのでこれでいきます。

が、公式のものじゃないらしいので、どうしても気になる人はEC2借りるなりLightsailAmazon Linux 2023のマシンを用意しても良いかもしれません。
スペックは多少高いものを選ばないとダメそう(Lightsailの一番下を選んだら固まってしまった...)

Amazon Linux 2023 を用意する

これでビルドします。
なぜかと言うと、AWS Lambdaを実行するためのマシンが使っている、Linux ディストリビューションAmazon Linux 2023だそうで、
OS同じでビルドすれば多分動くでしょって。

Imgur

Imgur

というかUbuntuでビルドしたら何回やってもダメだったから、Lambdaの環境と同じディストリビューションにしてみた、
標準Cライブラリとやらのバージョンが一致してないとかなんとかで。

Error: Command failed: /opt/bin/magick --version",
/opt/bin/magick: /lib64/libc.so.6: version `GLIBC_2.38' not found (required by /opt/lib/libMagickCore-7.Q16HDRI.so.10)
/opt/bin/magick: /lib64/libm.so.6: version `GLIBC_2.38' not found (required by /opt/lib/libMagickCore-7.Q16HDRI.so.10)
/opt/bin/magick: /lib64/libm.so.6: version `GLIBC_2.35' not found (required by /opt/lib/libMagickCore-7.Q16HDRI.so.10)
/opt/bin/magick: /lib64/libm.so.6: version `GLIBC_2.38' not found (required by /opt/lib/libMagickWand-7.Q16HDRI.so.10)
/opt/bin/magick: /lib64/libc.so.6: version `GLIBC_2.38' not found (required by /opt/lib/libMagickWand-7.Q16HDRI.so.10)

必要なパッケージを入れる

update + upgradeのコンボ、あとaptbuild-essentialに当たるDevelopment Toolsを入れます。
wgetも入ってなかった...

yum update
yum upgrade
yum groupinstall "Development tools"
yum install wget

libjpeg

https://www.ijg.org/

ここからダウンロードリンクが探せるので、wgetか何かで落として解凍。gzの方です。

cd ~
wget https://www.ijg.org/files/jpegsrc.v9f.tar.gz
tar xvzf jpegsrc.v9f.tar.gz
cd jpeg-9f

prefixオプションで/optにインストールするように設定して、makeしてinstall
ライブラリ創作先に/optを追加します。

./configure --prefix=/opt CPPFLAGS=-I/opt/include LDFLAGS=-L/opt/lib --disable-dependency-tracking --enable-shared
make
make install

make installすると/optにバイナリが配置されているはずです。
見てみましょう。

ls /opt

Imgur

入ってますね!

zlib

https://www.zlib.net/

libpngがこれを使っているらしいのでこれもビルドします。
同様にホームページからダウンロードリンクを探してwgetで落とします。gzの方です。

cd ~
wget https://www.zlib.net/zlib-1.3.1.tar.gz
tar xvzf zlib-1.3.1.tar.gz
cd zlib-1.3.1
./configure --prefix=/opt
make
make install

libpng

http://www.libpng.org/pub/png/libpng.html

同様にlibpngもダウンロードリンクを探してwgetで落とします。gzの方で。

cd ~
wget http://prdownloads.sourceforge.net/libpng/libpng-1.6.47.tar.gz
tar xvzf libpng-1.6.47.tar.gz
cd libpng-1.6.47
./configure --prefix=/opt CPPFLAGS=-I/opt/include LDFLAGS=-L/opt/lib --disable-dependency-tracking --enable-shared
make
make install

libwebp

https://developers.google.com/speed/webp/docs/compiling?hl=ja

webpの画像を扱う予定があれば。この通りに進めます。
libgifが無くてもビルドは出来た...、GIFが扱えないだけでwebpは使えるのかな

cd ~
wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.5.0.tar.gz
tar xvzf libwebp-1.5.0.tar.gz
cd libwebp-1.5.0
./configure --prefix=/opt CPPFLAGS=-I/opt/include LDFLAGS=-L/opt/lib --disable-dependency-tracking --enable-shared
make
make install

libultrahdr

https://github.com/google/libultrahdr/blob/main/docs/building.md

UltraHDRのビルドです。
これはCMakeなので他とは若干違う。また、libjpegが必要なので、予めビルドして/optにインストールしておいてください。

ビルド手順がDebian系列になっているのでCentOS系列用?に読み替える必要があります。
あといくつかオプションを指定してLambda Layerに入れられるようにします。

まずはビルドに必要なツールを

yum install cmake pkg-config ninja-build

次にソースコードを落として、ビルド用のフォルダを作ります。

cd ~
git clone https://github.com/google/libultrahdr.git
cd libultrahdr
mkdir build_directory
cd build_directory

そしたらビルドします。
オプションですが、

  • gccg++をコンパイラに指定
    • 多分yum groupinstall "Development Tools"で付いてくるはず
  • ライブラリ捜索先は/opt/lib
    • さっきビルドしたlibjpeg/opt/libにあるので、それを使う
  • ライブラリはlibに配置
    • Debian系は/libに配置してくれるが、CentOS系列?lib64に配置しようとする
    • Lambda Layerlibにしかパスが通ってないのでlibに合わせる
  • インストール先は/opt
    • --prefix=/optみたいな
  • ../pwdbuild_directoryで、親にあるものを探すため
cmake -G Ninja -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_PREFIX_PATH=/opt/lib -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_PREFIX=/opt ../
ninja
ninja install

ImageMagick

ソースコードを持ってきます
7.1.1-47は最新リリースに合わせてください→ https://github.com/ImageMagick/ImageMagick/releases

cd ~
git clone --depth 1 --branch 7.1.1-47 https://github.com/ImageMagick/ImageMagick.git ImageMagick-7.1.1
cd ImageMagick-7.1.1

そうしたら、デリゲートライブラリの捜索先に/opt/libを指定します。これでさっきビルドしたlibjpegたちを発見できるはずです。
export ...の1行ですね。

configureは先駆者のママです。何も分からず。。これでAWS Lambdaで動く。
UltraHDRはデフォルト無効なのでyesを付けます。

export PKG_CONFIG_PATH=/opt/lib/pkgconfig
./configure CPPFLAGS=-I/opt/include LDFLAGS=-L/opt/lib --prefix=/opt --disable-docs --without-modules --enable-delegate-build --without-magick-plus-plus --without-perl --without-x --without-dmr --without-heic --without-jbig --without-lcms --without-openjp2 --without-lqr --without-lzma --without-pango --without-raw --with-rsvg --without-tiff --disable-openmp --disable-dependency-tracking --with-uhdr=yes

Imgur

jpegpnguhdryesになっているはず。

Imgur

そしたらmakeしてmake installです。

make
make install

ImageMagick

ソースコードを持ってきます
7.1.1-47は最新リリースに合わせてください→ https://github.com/ImageMagick/ImageMagick/releases

cd ~
git clone --depth 1 --branch 7.1.1-47 https://github.com/ImageMagick/ImageMagick.git ImageMagick-7.1.1
cd ImageMagick-7.1.1

そうしたら、デリゲートライブラリの捜索先に/opt/libを指定します。これでさっきビルドしたlibjpegたちを発見できるはずです。
export ...の1行ですね。

configureは先駆者のママです。何も分からず。。
UltraHDRはデフォルト無効なのでyesを付けます。

export PKG_CONFIG_PATH=/opt/lib/pkgconfig
./configure CPPFLAGS=-I/opt/include LDFLAGS=-L/opt/lib --prefix=/opt --disable-docs --without-modules --enable-delegate-build --without-magick-plus-plus --without-perl --without-x --without-dmr --without-heic --without-jbig --without-lcms --without-openjp2 --without-lqr --without-lzma --without-pango --without-raw --with-rsvg --without-tiff --disable-openmp --disable-dependency-tracking --with-uhdr=yes

Imgur

jpegpnguhdryesになっているはず。

Imgur

そしたらmakeしてmake installです。

make
make install

ビルドした ImageMagick を起動してみる

version返ってくるか確認です!
ちゃんとDelegatesの欄にjpegpnguhdrがあります!

/opt/bin/magick --version

結果。

Version: ImageMagick 7.1.1-47 Q16-HDRI x86_64 c8f4e8cb7:20250329 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI
Delegates (built-in): jng jpeg png uhdr webp zlib zstd
Compiler: gcc (11.3)

zip に固める

問題なく動作したらLambda Layerを作りましょ。
これで/optにインストールしたlibjpegImageMagicklibczipに。WindowsのエクスプローラーからWSL2のドライブ見れるので拾ってください。

cd /opt
zip -r ~/imagemagick-layer.zip .

Lambda Layer として登録

Lambdaレイヤーレイヤーの作成へ進み、適当な名前をつけます。

Imgur

Imgur

さっき作ったzipを放り込んで、アーキテクチャはx86_64、ランタイムはNode.jsで!
これでImageMagickAWS Lambdaから呼び出す準備はおっけーです。

S3 バケットを作る

チュートリアルのそれと同じ

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-tutorial.html

バケットを作ります。画像を受け付けるバケットと、リサイズした画像を置いておくバケットです。
事故が起きるくらいなら入力、出力で2つ作ったほうが良いです。

Imgur

受け付け用バケットに画像をいれる

UltraHDRImageMagickをビルドしたので、UltraHDRの画像で

Imgur

Lambda S3 のアクセス権限のためのポリシーとロール作成

IAMポリシーページを開いて、以下のJSONを貼り付ける。
CloudWatchは使わないので消しました、、(いいのか?)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
        }
    ]
}

そしたら次に進んで、よしなに名前をつけてください。
ポリシーが出来たら、ロールを作ります。Lambdaを先に作成すると対応するロールが作成されているかもしれない、、

IAMロールページを開いて、ロールを作成を押します。
AWS のサービスを選び、その下はLambdaにします。

Imgur

そしたら次に進み、先程作成したポリシーを付けてあげて、次へ進みます。名前間違えてエラーになったのでリロードするなりして合ってるか確認してね。
名前はよしなにつけてください。

Imgur

Lambda Node.js で動かす JavaScript を書く

環境構築

今回はJavaScript (Node.js)にします、Javaも出来るそう、、ですが郷に従え(チュートリアル)というわけで。
別にこの規模ならJavaScriptで良いし。ローカルで適当にnpm initします。

npm init

Imgur

つぎに、必要なライブラリをば。
今回はTypeScriptJavaScriptにしてzipに詰めてアップロードする気でいます。

aws-lambdaの型定義と、esbuildを入れます。
esbuildtsjsにしてLambdaで動かします。Node.js.tsはまだ厳しそう雰囲気(もう少しな気はする)
あとs3クライアント

npm install -D @types/aws-lambda esbuild
npm i @aws-sdk/client-s3

Imgur

次に.jsにするためのコマンドを書きます。package.jsonを開いて、"scripts": { }の部分をこうします。
Windowsでしか動かないと思います。多分delrmに、powershell Compress-Archive ...zipコマンドに置き換えればLinuxでも動くはず?

"scripts": {
    "prebuild": "del /q dist",
    "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
    "postbuild": "cd dist && powershell Compress-Archive -Force -Path index.js* -DestinationPath ../dist.zip"
},

TypeScript

全部張ります。ドーン。
UltraHDRに対応させたので複雑です、、、あとバケット名はLambda環境変数から取り出すようにしました。

import child_process from 'child_process'
import { promisify } from 'util'
import fs from 'fs/promises'
import { randomUUID } from 'crypto'
import path from 'path'
import { S3Event } from 'aws-lambda'
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3'
 
// "GainMap"の文字をバイト配列
const GAINMAP_TEXT_BYTE = Buffer.from('GainMap', 'utf8')
 
// exec() を Promise に
const exec = promisify(child_process.exec)
 
// S3 クライアント
const s3 = new S3Client({ region: 'ap-northeast-1' })
 
// 変換した画像の保存先 S3 バケット名(Lambda 環境変数)
const RESULT_S3_BACKET_NAME = process.env['S3_RESULT_BACKET_NAME']
 
export const handler = async (event: S3Event) => {
    const bucket = event.Records[0].s3.bucket.name
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '))
 
    // 拡張子を取得
    const imageExtension = key.match(/\.([^.]*)$/)?.[0].toLowerCase()
    if (!imageExtension) {
        console.log('拡張子が不明です。')
        return
    }
 
    try {
        // S3 から追加された画像を取り出す
        const response = await s3.send(new GetObjectCommand({
            Bucket: bucket,
            Key: key
        }))
        const inputImageByteArray = await response.Body?.transformToByteArray()
        if (!inputImageByteArray) {
            console.log('S3 からデータが取得できませんでした')
            return
        }
 
        // 作業用フォルダをつくる
        // Lambda はインスタンス再利用されるかもなのでできればランダム
        const tempDirectory = await fs.mkdtemp('/tmp/image')
 
        // ImageMagick に渡すため /tmp に保存
        const inputFilePath = path.join(tempDirectory, `input${imageExtension}`)
        await fs.writeFile(inputFilePath, inputImageByteArray)
 
        // 変換した画像データの保存先
        // できる限りそのままの画像と、リサイズで2つ
        const originalImagePath = path.join(tempDirectory, `original${imageExtension}`)
        const resizeImagePath = path.join(tempDirectory, `resize${imageExtension}`)
 
        // ImageMagick でリサイズ
        // ついでに Exif に回転情報があれば画像自体を回転させて、Exif も消す(スマホの名前とか入ってる)
        if (Buffer.from(inputImageByteArray.buffer).includes(GAINMAP_TEXT_BYTE)) {
            // UltraHDR 画像の場合は uhdr: を付ける必要があるので
            await Promise.all([
                await exec(`magick -define uhdr:output-color-transfer=hlg -define uhdr:hdr-color-transfer=hlg uhdr:${inputFilePath} -auto-orient -strip uhdr:${originalImagePath}`),
                await exec(`magick -define uhdr:output-color-transfer=hlg -define uhdr:hdr-color-transfer=hlg uhdr:${inputFilePath} -auto-orient -strip -resize 50% uhdr:${resizeImagePath}`)
            ])
        } else {
            // UltraHDR じゃない
            await Promise.all([
                await exec(`magick ${inputFilePath} -auto-orient -strip ${originalImagePath}`),
                await exec(`magick ${inputFilePath} -auto-orient -strip -resize 50% ${resizeImagePath}`)
            ])
        }
 
        // 画像を取得
        const [originalByteArray, resizeByteArray] = await Promise.all(
            [originalImagePath, resizeImagePath]
                .map((imagePath) => fs.readFile(imagePath))
        )
 
        // 2つの画像で同じ UUID になるように
        // パスは /original と /resize
        const fileName = `${randomUUID()}${imageExtension}`
        const originalPut = new PutObjectCommand({
            Bucket: RESULT_S3_BACKET_NAME,
            Key: `original/${fileName}`,
            Body: originalByteArray
        })
        const resizePut = new PutObjectCommand({
            Bucket: RESULT_S3_BACKET_NAME,
            Key: `resize/${fileName}`,
            Body: resizeByteArray
        })
 
        // 出力先 S3 にアップロード
        await Promise.all([s3.send(originalPut), s3.send(resizePut)])
    } catch (error) {
        console.log(error)
    }
}

zip にする

index.jsindex.js.mapを一つのzipにしてくれるコマンドをscriptsで定義したので、これを叩けばdist.zipが出来上がるはずです。

npm run build

Imgur

画像が UltraHDR かどうかの判定

そのままImageMagickに入れるとjpegで処理されるため、gainmapが消えちゃう、(uhdr:指定が必要)。
UltraHDRを配信するためにS3+CloudFrontにしているのに、、、

というわけで、exec()の段階でUltraHDR画像かを判定する必要がある。 バイナリエディタを眺めてた結果、GainMapってバイト配列の文字列が入っていたので、このバイト配列があるかで判定すれば良いはず。
あんまり自信ないけど自分しか使わないし!

Imgur

それがこれです。

const GAINMAP_TEXT_BYTE = Buffer.from('GainMap', 'utf8')
const imageByteArray = await fs.readFile('nomikai.jpg') // 画像パス
const hasGainMap = imageByteArray.includes(GAINMAP_TEXT_BYTE) // GainMap があれば UltraHDR

Lambda を作る

Lambdaの作成ページを開いて、適当な名前をつけ、x86_64を選び、ロールはさっき作ったものを選びます。

Imgur

あとは関数を作成を押せばいいです、
できたらアップロード先を押して.zipをアップロードします。

Imgur

Imgur

Lambda 環境変数追加

保存先バケットの名前を環境変数から取り出すようにします。
ここのENVIRONMENT VARIABLES+から以下の名前でバケット名を入れてください。

Imgur

間違えても受け付け用バケットの名前を入れないように!(無限ループする)

LambdaLayer を追加

ここのLayerを押すとスクロールするので、レイヤーの追加からさっきアップロードしたLambdaLayerを選択する。

Imgur

Imgur

メモリ上限とタイムアウトを緩和する

ImageMagickLambdaのデフォルトスペックで動かすと厳しいっぽい?

Error: Task timed out after 3.00 seconds

というわけでメモリ割り当てとタイムアウトを増やします、設定を開きます。
10秒くらいで終わらせるためには2GB (2048MB)欲しいですね。。

Imgur

よく見ると10GBまで使えるらしいですが、私のAWSアカウントだと3GBまでしか使えませんでした!w。 サポートに言えば解禁してくれるらしいです。

テスト

テストを選ぶ。
よしなに名前をつけて、JSONは以下を貼り付けてください。が、一部直して貰う必要があります!!

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "ap-northeast-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "受け付け用バケットの名前",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "受け付け用バケットの arn"
        },
        "object": {
          "key": "受け付け用バケットにアップロードした画像のkey (名前)",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

できたら保存からのテストで。スペックを上げたので10秒くらいで終わるはず。

Imgur

テストうごいた!

保存先バケットを開いてみてください。original/resize/にちゃんと入っているはず!

Imgur

受け付け用バケットに画像が入ったら Lambda が起動するように

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-tutorial.html#with-s3-tutorial-configure-s3-trigger

Lambdaトリガーを追加を押します。

Imgur

そしたらS3を選んで

Imgur

バケットは受け付け用バケットに、すべてのオブジェクト作成イベントになってることを確認して、
一番下にあるチェックマークにチェックを入れて、追加

これでS3がいます!
Imgur

受け付け用バケットに入れてもうごく!

S3の画面にJPEGをどーーん

Imgur

LambdaモニタリングInvocationsを見ると呼び出されてるのが分かるはず。

Imgur

受け付け用バケットは勝手に削除されるように

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html
ライフサイクル機能があります。

今回は受け付け用バケットで、特に保護とかは興味がないので、バージョニングは無効です。
無効にしている場合、上記の URL を見る限りライフサイクルがトリガーされ期限切れになったら、削除になるらしい(バージョニング無効なので)

というわけで追加します。受け付け用バケットでやること。
作成を押します。

Imgur

バケット内のすべてのオブジェクトに適用にして、オブジェクトの現行バージョンを有効期限切れにするにチェックを入れます。
日数はお好みで、まあ1日でも長いんですが

Imgur

ここもよく見ると、バージョニング無効の場合は有効期限切れが削除になるって。
これでオブジェクトをアップロードしてみると、削除日時が表示されます。

Imgur

完成

あとは保存先バケットをCloudFrontで公開するなりすれば画像を配信する超簡易的サーバーの完成。
S3+CloudFrontは前に記事にしたのでそれで!!!

おまけ CloudFront で公開する手順

詳しくは前書いたS3 + CloudFrontで静的サイトの記事で。CloudFront Functionsは不要です。
https://takusan.negitoro.dev/posts/aws_sitatic_site_hosting/

  • CloudFrontのディストリビューションを作る
    • オリジンをリサイズ後の画像が保存されるS3バケット
    • S3は公開しないのでOACを選ぶ
  • ディストリビューションができたら、バケットポリシーの JSON がコピーできるので、保存先S3のバケットポリシーに貼り付ける
    • Imgur
    • Imgur
  • デプロイされるまで待つ(最終変更日が表示される)
  • ディストリビューションドメイン名 + S3の画像のキー をくっつけた URL でアクセス、画像が返ってくること。
    • ディストリビューションドメイン名をコピーする
    • S3にある画像を選んでキーをコピーする
  • ドメインを割り当てる場合は最初にディストリビューションの設定を開き、Custom SSL certificate - optionalRequest certificateを押す
    • パブリックを選び、完全修飾ドメイン名を埋めて、DNS 検証にして、リクエスト
    • CNAME 名CNAME 値が表示されるので、自分のドメイン管理画面(私はCloudflare)を開きDNS レコードを追加する。
      • CNAMEを選んで、名前と値はAWSに指示されたものを
        • Imgur
    • これはAWSがドメインを所持しているかの確認のためで、自分のドメインでCloudFrontを使うためには別の作業がいる
  • 自分のドメインでCloudFrontにアクセスできるようにするため、再度DNS レコードを追加する
    • CNAMEを選び、サブドメインなら名前欄に入れる、値はCloudFront ディストリビューションディストリビューションドメイン名を入れる
      • Imgur
  • DNSでの確認が終わって、AWSSSL 証明書が使えるようになったら、CloudFront ディストリビューションの管理画面を開き、Custom SSL certificate - optionalではさっき作った証明書を、Alternative domain name (CNAMEs) - optionalで使いたいドメインを入れます。
    • 代替ドメイン名カスタム SSL 証明書が表示されてるはず
    • Imgur
  • 自分のドメインでもアクセスできるようになったはず

おわりに

AWS Lambdaで使ったソースコードです、npm iからのnpm run buildzipが出来るので、説明通りデプロイして環境変数をセットすれば良いはず。

https://github.com/takusan23/oekakityou-lambda

おわりに2

ちなみに、自分ひとりしか使わないのでバリデーションとか一切していません。
不特定多数に使わせる場合はちゃんと整備したほうが良いと思います。

おわりに3

S3のコンソールにアクセスしないと画像わからんし、アップロードのためにコンソールログインするのもあれなので、次回はそれを解決します。
超簡易的画像配信サーバーのクライアント編。