Skip to content

Instantly share code, notes, and snippets.

@rdkls
Last active March 31, 2021 15:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rdkls/d52906d8e108988de4961d5c8c7a2b9f to your computer and use it in GitHub Desktop.
Save rdkls/d52906d8e108988de4961d5c8c7a2b9f to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# Compiles a Python package into a zip deployable on AWS Lambda
#
# - Builds Python dependencies into the package, using a Docker image to correctly build native extensions
# - Strip shared object files for smaller size ca. 20% reduction
# - Remove .py and use .pyc's = faster lambda and ca. 20% reduction
# - Remove tests, info (minor reduction, but why not)
# - Remove packages that will be available in AWS lambda env anyway (boto et al) ca. 50mb (uncompressed) reduction
# - Able to be used with the terraform-aws-lambda module
#
# Based on Raymond Butcher's build script for the terraform-aws-lambda module:
# https://github.com/claranet/terraform-aws-lambda/blob/master/tests/build-command/lambda/build.sh
#
# Incorporating ideas from Vincent Sarago @ mapbox
# https://blog.mapbox.com/aws-lambda-python-magic-e0f6a407ffc6
#
# There's a Terraform module that wraps this method (and other stuff re: lambda deployment) here:
# https://github.com/intelematics/terraform-aws-lambda
#
# Usage:
#
# $ ./build.sh <output-zip-filename> <runtime> <source-path>
set -euo pipefail
# Read variables from command line arguments
FILENAME=$1
RUNTIME=$2
SOURCE_PATH=$3
# Convert to absolute paths
SOURCE_DIR=$(cd "$SOURCE_PATH" && pwd)
ZIP_DIR=$(cd "$(dirname "$FILENAME")" && pwd)
ZIP_NAME=$(basename "$FILENAME")
docker run --rm -t -v "$SOURCE_DIR:/src" -v "$ZIP_DIR:/out" lambci/lambda:build-$RUNTIME bash -c "
cp -r /src /build &&
cd /build &&
pip install --progress-bar off -r requirements.txt -t . &&
find . -name \\*\\.pyc -exec mv {} . \\; &&
find . -name \\*\\.so -exec strip {} \\; &&
find . -type d -name \\*-info -prune -exec rm -rdf {} \\; &&
find . -type d -name tests -prune -exec rm -rdf {} \\; &&
find . -type d -name boto3 -prune -exec rm -rdf {} \\; &&
find . -type d -name botocore -prune -exec rm -rdf {} \\; &&
find . -type d -name docutils -prune -exec rm -rdf {} \\; &&
find . -type d -name dateutil -prune -exec rm -rdf {} \\; &&
find . -type d -name jmespath -prune -exec rm -rdf {} \\; &&
find . -type d -name s3transfer -prune -exec rm -rdf {} \\; &&
find . -type d -name doc -prune -exec rm -rdf {} \\; &&
chmod -R 755 . &&
zip -r /out/$ZIP_NAME . &&
chown \$(stat -c '%u:%g' /out) /out/$ZIP_NAME
"
echo "Created $FILENAME from $SOURCE_PATH"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment