Python
AWS
docker
lambda

requirements.txtを動的に作成して、lambda用のZIPを作成する

課題

lambda(python)用のZIPファイルを作成するときに、pythonパッケージも一緒にZIPに固める必要がある。
コードの改修やfunctionを作成するたびに、requirements.txtを修正するのは大変。

対処

lambda functionを一つのディレクトリにまとめて、pipreqsでrequirements.txtを動的に作成する。
amazonlinuxのDockerイメージを使い、requirements.txtからPythonパッケージを作成しZIPにする。

詳細

ディレクトリ構成.
# `function/`にlambda function用のディレクトリをそれぞれ作成
.
├── Dockerfile
├── function
│   ├── lambdaFunction1
│   │   └── function1.py
│   └── lambdaFunction2
│       └── function2.py
└── deploy.sh
Dockerfile.
# For install library for python of lambda
FROM amazonlinux:2017.03
RUN yum install -y python36 python36-pip zip
COPY requirements.txt /tmp/
RUN python36 -m pip install -r /tmp/requirements.txt -t /tmp/library
RUN cd /tmp/library && zip -r /tmp/library.zip *

deploy.sh
PROJECT_ROOT_DIR=$(cd $(dirname $0); pwd)
DEPLOY_WORK_DIR="${PROJECT_ROOT_DIR}/.deploy"
DOCKERFILE_DIR="${PROJECT_ROOT_DIR}"

if [ -e ${DEPLOY_WORK_DIR} ] ; then
    rm -rf ${DEPLOY_WORK_DIR}
fi
mkdir ${DEPLOY_WORK_DIR}

download_python_library() {
    cd ${DOCKERFILE_DIR}
    # requirements.txtはpipreqsを使って動的に作成します
    pip install pipreqs
    pipreqs --force ${FUNCTION_CODE_DIR}
    # lambdaでインストールせずに使えるパッケージは除外します
    sed -i '' -e "/boto3/d" ${FUNCTION_CODE_DIR}/requirements.txt
    mv ${FUNCTION_CODE_DIR}/requirements.txt .
    docker build . -t amazonlinux
    docker run --name amazon amazonlinux /bin/true
    docker cp amazon:/tmp/library.zip ${DEPLOY_WORK_DIR}/${FUNCTION}.zip
    docker stop amazon
    docker rm amazon
    rm requirements.txt
}

create_zip() {
    cd ${DEPLOY_WORK_DIR}
    echo $'Zip \e[33m'$(ls ${FUNCTION_CODE_DIR})$'\e[0m into '${FUNCTION}'.zip'
    zip -j ${FUNCTION}.zip ${FUNCTION_CODE_DIR}/*
}

zip_function() {
    download_python_library
    create_zip
}

# Create ZIP with python package
FUNCTIONS=($(ls ${FUNCTION_DIR}))
for _FUNCTIONS in "${FUNCTIONS[@]}"; do
    FUNCTION=${_FUNCTIONS}
    FUNCTION_CODE_DIR="${FUNCTION_DIR}/${FUNCTION}"
    echo $'Zip \e[33m'${_FUNCTIONS}$'\e[0m'
    zip_function
done