🐏

KTX-SoftwareをLambdaで実行してみた

に公開

背景

KTX-Softwareを用いて画像をKTX2に圧縮する必要があがりました。
要件を聞くと

  • 圧縮対象の画像は非常に小さい(512x512以下)
  • 圧縮にかかる時間は長くなってもよい

ということだったので、既にシステムで使用しているLambdaで賄えないか、ということで表題の件を実施するに至りました。

方針

KTX-Software(詳細にはKTX Tools)はLinuxアプリケーションとしては配布されていますが、PythonやNodeから呼び出せるライブラリとしては配布されていません。

というわけで、今回はKTX ToolsをインストールしたDockerイメージ上でLambdaを起動して、PythonからsubprocessでKTX Toolsを実行する方針にしました。

参考
コンテナイメージを使用した Lambda 関数の作成
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html

コンテナイメージの作成

ベースイメージの選択

ベースイメージは以下の3パターンがあります。

  • Lambda の AWS ベースイメージを使用する
  • AWS の OS 専用ベースイメージを使用する
  • 非 AWS ベースイメージを使用する

今回インストールするKTX ToolsにはGnuパッケージが必要です。AWSが用意するベースイメージにはこのGnuパッケージが含まれなかったため非 AWS ベースイメージを使用することにしました。

Pythonファイルの作成

Lambdaで実行するPythonファイルを作成します。
今回はローカルで動作確認するため、Docker上の/tmp/sample.jpgをKTX Toolsで変換します。

ファイル名はapp.pyとします。

$ touch app.py
app.py
import subprocess

def handler(event, context): 
    command = [
        "ktx", "create", 
        "--format", "R8G8B8A8_UNORM",
        "/tmp/sample.jpg",
        "/tmp/sample.ktx2"
    ]
    result = subprocess.run(command)
    return f'ktx execute. returncode = {result.returncode}'

Dockerfileの作成

Dockerfileを作成します

$ touch Dockerfile

ローカルで動作確認を行うため、ローカル上のsample.jpgをDocker上へコピーしています。

Dockerfile
FROM ubuntu:22.04

# install python
RUN apt-get update
RUN apt-get install -y python3-pip

# install python libraries
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

# install awslambdaric
RUN mkdir /function && \
  pip install --target /function awslambdaric
COPY ./app.py /function/

# 変換対象のファイルをコピー
COPY ./sample.jpg /tmp/

# install KTX-Software
RUN apt-get install -y curl
RUN mkdir /install && \
  curl -L -o /install/KTX-Software-4.3.2-Linux-x86_64.deb https://github.com/KhronosGroup/KTX-Software/releases/download/v4.3.2/KTX-Software-4.3.2-Linux-x86_64.deb
RUN apt install /install/KTX-Software-4.3.2-Linux-x86_64.deb

WORKDIR /function

ENTRYPOINT [ "/usr/bin/python3", "-m", "awslambdaric" ]

CMD [ "app.handler" ]

動作確認

イメージをローカルでテストする方法は下記で解説されています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-image.html#python-image-clients

Docker ビルド

$ docker build -t docker-image:test .

エミュレーターをインストール

$ mkdir -p ~/.aws-lambda-rie && \
    curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
    chmod +x ~/.aws-lambda-rie/aws-lambda-rie

Docker イメージを起動

$ docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
    --entrypoint /aws-lambda/aws-lambda-rie \
    docker-image:test \
        /usr/bin/python3 -m awslambdaric app.handler

Dockerにログインし、/tmpフォルダの内容を確認します

$ docker exec -it <コンテナID> /bin/bash
$ ls /tmp
sample.jpg
$ exit

エミュレータのLambdaイベントを起動

$ curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

"ktx execute. returncode = 0"と表示されれば正常です。

再びDockerにログインし、/tmpフォルダの内容を確認します。

$ docker exec -it <コンテナID> /bin/bash
$ ls /tmp
sample.jpg  sample.ktx2
$ exit

sample.ktx2が生成されていることが確認できました。

起動したDokerを停止

$ docker kill <コンテナID>

Lambda関数の作成

作成したDockerイメージを使用してLambda関数を作成する方法は、下記を参考にしました。
https://zenn.dev/kou_pg_0131/articles/lambda-container-image

Discussion