こしあん
2024-12-07

DockerでAWS LambdaのレイヤーのZipファイルを一括生成する


17{icon} {views}

複数のrequirements.txtファイルから、AWS Lambda用のレイヤーZipファイルを自動生成します。Dockerを使用して一括で生成することで、レイヤーファイルの手作業作成や、手順の未記録といった問題を解決できます。

やりたいこと

  • requirements.txtpip installするライブラリのリストが与えられたときに、AWS Lambdaで使うレイヤーのZipファイルを自動生成したい
  • requirements.txtは複数ファイルあり、それぞれに必要なライブラリのリストが記載されている
  • シェルファイル一個実行したらレイヤー用のZipファイルが一括生成されるもの

作るもの

ディレクトリ構造を詳細に書くと以下の通りで、build_layers.shを実行すると、裏でdocker builddocker runが走って、requirementsディレクトリの各テキストファイルを読み取って、outputディレクトリに対応するZipファイル(例:numpy_openai.zip, numpy_opencv.zip)などを生成

/
├── output/
├── requirements/
│   ├── numpy_openai.txt
│   ├── numpy_opencv.txt
│   ├── numpy_pillow.txt
├── build_layers.sh
├── Dockerfile
└── entrypoint.sh

requirementsには、Dockerと同様に以下のように必要なライブラリを記載する。

openai==1.57.0
numpy==2.1.3

ChatGPTに作らせて少し調整したらできてしまったので、メモ用にコードをおいておく。

コード

build_layers.sh

共通のDockerイメージを作って、requirements.txtごとにdocker runを実行。マウントで作ったZipファイルを引き渡す。

#!/bin/bash

set -e

# Path to directories
REQUIREMENTS_DIR="$(pwd)/requirements"
OUTPUT_DIR="$(pwd)/output"

# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"

# Build the Docker image
docker build -t lambda-layer-builder .

# Loop through all .txt files in the requirements directory
for req_file in "$REQUIREMENTS_DIR"/*.txt; do
  base_name=$(basename "$req_file" .txt)
  output_zip="${OUTPUT_DIR}/${base_name}.zip"
  echo "Building layer for $req_file to $output_zip"

  docker run --rm \
    -v "$req_file:/app/requirements.txt" \
    -v "$OUTPUT_DIR:/app/output" \
    -e BASE_NAME="$base_name" \
    lambda-layer-builder
done

Dockerfile

AWS Lambdaの実行環境と合わせるために、Lambda用のDockerイメージを使う。これは本来デプロイに使うのだが、レイヤーを作成するときも使える。ベースのPythonを変えたいときは、最初の行のPullするイメージのバージョンを変える。

# Use Amazon Linux 2 for AWS Lambda as the base image
FROM public.ecr.aws/lambda/python:3.13

# Install required packages
RUN dnf install -y zip

# Set the working directory
WORKDIR /var/task

# Copy the entrypoint script into the container
COPY entrypoint.sh /entrypoint.sh

# Make the entrypoint script executable
RUN chmod +x /entrypoint.sh

# Set the entry point
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

Dockerイメージ内で実行されるコード。入力のテキストファイル、出力のZipファイルを動的にするためにこのようにシェルファイルを実行する形にしている。

#!/bin/bash
set -e

# Check if BASE_NAME is set
if [ -z "$BASE_NAME" ]; then
  echo "Error: BASE_NAME environment variable is not set."
  exit 1
fi

# Get the base name from the environment variable
base_name="$BASE_NAME"

# Install Python packages
pip install --no-cache-dir -r /app/requirements.txt -t python

# Compress the Python directory into a zip file
zip -r /layer.zip python

# Copy the zip file to the output directory using the base name
cp /layer.zip /app/output/${base_name}.zip

所感

Lambdaのレイヤーファイルって手作業で作ったり、作成手順が記録されなかったりでモヤモヤしていたけど、これならどっちも解決できて便利!



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です