|
1 | 1 | ARG PYTHON_VERSION=3.12
|
2 | 2 |
|
3 |
| -FROM --platform=linux/amd64 public.ecr.aws/lambda/python:${PYTHON_VERSION} |
| 3 | +# Build stage - includes all build tools and dependencies |
| 4 | +FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} AS builder |
| 5 | + |
| 6 | +# Copy uv for faster dependency management |
4 | 7 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
5 | 8 |
|
6 |
| -WORKDIR /tmp |
| 9 | +# Install system dependencies needed for compilation |
| 10 | +RUN dnf install -y gcc-c++ && dnf clean all |
7 | 11 |
|
8 |
| -# Install system dependencies to compile (numexpr) |
9 |
| -RUN dnf install -y gcc-c++ |
| 12 | +# Set working directory for build |
| 13 | +WORKDIR /build |
10 | 14 |
|
11 |
| -COPY uv.lock .python-version pyproject.toml LICENSE README.md ./ |
| 15 | +# Copy dependency files first for better caching |
| 16 | +COPY README.md uv.lock .python-version pyproject.toml ./ |
12 | 17 | COPY src/titiler/ ./src/titiler/
|
13 | 18 |
|
| 19 | +# Install dependencies to temporary directory with Lambda-specific optimizations |
14 | 20 | RUN uv export --locked --no-editable --no-dev --extra lambda --format requirements.txt -o requirements.txt && \
|
15 |
| - uv pip install --compile-bytecode --no-binary pydantic --target /asset -r requirements.txt |
| 21 | + uv pip install \ |
| 22 | + --compile-bytecode \ |
| 23 | + --no-binary pydantic \ |
| 24 | + --target /deps \ |
| 25 | + --no-cache-dir \ |
| 26 | + --disable-pip-version-check \ |
| 27 | + -r requirements.txt |
| 28 | + |
| 29 | +# Aggressive cleanup to minimize size and optimize for Lambda container |
| 30 | +WORKDIR /deps |
| 31 | +SHELL ["/bin/bash", "-o", "pipefail", "-c"] |
| 32 | +RUN <<EOF |
| 33 | +# Convert .pyc files and remove source .py files for faster cold starts |
| 34 | +find . -type f -name '*.pyc' | while read -r f; do n="$(echo "$f" | sed 's/__pycache__\///' | sed 's/.cpython-[0-9]*//')"; cp "$f" "$n"; done |
| 35 | +find . -type d -a -name '__pycache__' -print0 | xargs -0 rm -rf |
| 36 | +find . -type f -a -name '*.py' -print0 | xargs -0 rm -f |
| 37 | +# Remove unnecessary files for Lambda runtime |
| 38 | +find . -type d -a -name 'tests' -print0 | xargs -0 rm -rf |
| 39 | +find . -type d -a -name 'test' -print0 | xargs -0 rm -rf |
| 40 | +rm -rf numpy/doc/ bin/ geos_license Misc/ |
| 41 | +# Remove unnecessary locale and documentation files |
| 42 | +find . -name '*.mo' -delete |
| 43 | +find . -name '*.po' -delete |
| 44 | +find . -name 'LICENSE*' -delete |
| 45 | +find . -name 'README*' -delete |
| 46 | +find . -name '*.md' -delete |
| 47 | +# Strip debug symbols from shared libraries (preserve numpy.libs) |
| 48 | +find . -type f -name '*.so*' -not -path "*/numpy.libs/*" -exec strip --strip-unneeded {} \; 2>/dev/null || true |
| 49 | +# Create a manifest file for debugging |
| 50 | +du -sh . > /tmp/package_size.txt |
| 51 | +EOF |
| 52 | + |
| 53 | +# Final runtime stage - minimal Lambda image optimized for container runtime |
| 54 | +FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} |
16 | 55 |
|
17 |
| -# copy libexpat.so.1 into /asset which is included in LD_LIBRARY_PATH |
18 |
| -RUN cp /usr/lib64/libexpat.so.1 /asset/ |
| 56 | +# Set Lambda-specific environment variables for optimal performance |
| 57 | +ENV PYTHONPATH=${LAMBDA_RUNTIME_DIR} \ |
| 58 | + PYTHONUNBUFFERED=1 \ |
| 59 | + PYTHONDONTWRITEBYTECODE=1 \ |
| 60 | + AWS_LWA_ENABLE_COMPRESSION=true |
19 | 61 |
|
20 |
| -# Reduce package size and remove useless files |
21 |
| -RUN cd /asset && find . -type f -name '*.pyc' | while read f; do n=$(echo $f | sed 's/__pycache__\///' | sed 's/.cpython-[0-9]*//'); cp $f $n; done; |
22 |
| -RUN cd /asset && find . -type d -a -name '__pycache__' -print0 | xargs -0 rm -rf |
23 |
| -RUN cd /asset && find . -type f -a -name '*.py' -print0 | xargs -0 rm -f |
24 |
| -RUN find /asset -type d -a -name 'tests' -print0 | xargs -0 rm -rf |
25 |
| -RUN rm -rdf /asset/numpy/doc/ /asset/bin /asset/geos_license /asset/Misc |
26 |
| -RUN rm -rdf /asset/boto3* |
27 |
| -RUN rm -rdf /asset/botocore* |
| 62 | +# Copy only the cleaned dependencies from builder stage |
| 63 | +# Copy required system library |
| 64 | +COPY --from=builder /deps /usr/lib64/libexpat.so.1 ${LAMBDA_RUNTIME_DIR}/ |
28 | 65 |
|
29 |
| -# Strip debug symbols from compiled C/C++ code (except for numpy.libs!) |
30 |
| -RUN cd /asset && \ |
31 |
| - find . -type f -name '*.so*' \ |
32 |
| - -not -path "./numpy.libs/*" \ |
33 |
| - -exec strip --strip-unneeded {} \; |
| 66 | +# Copy application handler |
| 67 | +COPY infrastructure/aws/lambda/handler.py ${LAMBDA_RUNTIME_DIR}/ |
34 | 68 |
|
35 |
| -COPY infrastructure/aws/lambda/handler.py /asset/handler.py |
| 69 | +# Ensure handler is executable and optimize permissions |
| 70 | +RUN <<EOF |
| 71 | +chmod 644 "${LAMBDA_RUNTIME_DIR}"/handler.py |
| 72 | +# Pre-compile the handler for faster cold starts |
| 73 | +python -c "import py_compile; py_compile.compile('${LAMBDA_RUNTIME_DIR}/handler.py', doraise=True)" |
| 74 | +# Create cache directories with proper permissions |
| 75 | +mkdir -p /tmp/.cache && chmod 777 /tmp/.cache |
| 76 | +EOF |
36 | 77 |
|
37 |
| -CMD ["echo", "hello world"] |
| 78 | +# Set the Lambda handler |
| 79 | +CMD ["handler.lambda_handler"] |
0 commit comments