11ARG PYTHON_VERSION=3.12
22
3- # Build stage - includes all build tools and dependencies
4- FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} AS builder
3+ # Stage 1: Build dependencies
4+
5+ # Download the OpenTelemetry Layer with AppSignals Support:
6+ FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} as otel-builder
7+ RUN dnf install -y unzip wget && \
8+ wget https://github.com/aws-observability/aws-otel-python-instrumentation/releases/latest/download/layer.zip -O /tmp/layer.zip && \
9+ mkdir -p /opt-builder && \
10+ unzip /tmp/layer.zip -d /opt-builder/
511
6- # Copy uv for faster dependency management
12+ # install python dependencies
13+ FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} AS builder
714COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
815
9- # Install system dependencies needed for compilation
1016RUN dnf install -y gcc-c++ && dnf clean all
1117
12- # Set working directory for build
1318WORKDIR /build
1419
15- # Copy dependency files first for better caching
1620COPY README.md uv.lock .python-version pyproject.toml ./
1721COPY src/titiler/ ./src/titiler/
1822
23+ COPY infrastructure/aws/lambda/otel-requirements.txt ./
24+
1925# Install dependencies to temporary directory with Lambda-specific optimizations
26+ # Install OTEL packages to /opt/python (where otel-instrument wrapper expects them)
27+ RUN uv pip install \
28+ --target /opt-python \
29+ --no-cache-dir \
30+ --disable-pip-version-check \
31+ -r otel-requirements.txt
32+
33+ # Install app packages (excluding OTEL packages since they're already installed)
2034RUN uv export --locked --no-editable --no-dev --extra lambda --format requirements.txt -o requirements.txt && \
2135 uv pip install \
2236 --compile-bytecode \
@@ -26,7 +40,9 @@ RUN uv export --locked --no-editable --no-dev --extra lambda --format requiremen
2640 --disable-pip-version-check \
2741 -r requirements.txt
2842
43+
2944# Aggressive cleanup to minimize size and optimize for Lambda container
45+ # Clean up app dependencies in /deps
3046WORKDIR /deps
3147SHELL ["/bin/bash" , "-o" , "pipefail" , "-c" ]
3248RUN <<EOF
@@ -50,30 +66,53 @@ find . -type f -name '*.so*' -not -path "*/numpy.libs/*" -exec strip --strip-unn
5066du -sh . > /tmp/package_size.txt
5167EOF
5268
53- # Final runtime stage - minimal Lambda image optimized for container runtime
69+ # Clean up OTEL dependencies in /opt-python (lighter cleanup to preserve CLI tools)
70+ WORKDIR /opt-python
71+ RUN <<EOF
72+ # Remove test files and docs
73+ find . -type d -a -name 'tests' -print0 | xargs -0 rm -rf
74+ find . -type d -a -name 'test' -print0 | xargs -0 rm -rf
75+ # Keep bin/ directory for opentelemetry-instrument CLI
76+ find . -name '*.mo' -delete
77+ find . -name '*.po' -delete
78+ find . -name 'LICENSE*' -delete
79+ find . -name 'README*' -delete
80+ find . -name '*.md' -delete
81+ EOF
82+
83+ # Stage 3: Final runtime stage - minimal Lambda image optimized for container runtime
5484FROM public.ecr.aws/lambda/python:${PYTHON_VERSION}
5585
5686# 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
87+ # PYTHONPATH includes both /opt/python (OTEL packages) and LAMBDA_RUNTIME_DIR (app packages)
88+ ENV PYTHONUNBUFFERED=1 \
89+ PYTHONDONTWRITEBYTECODE=1
90+
91+ # Copy OTEL code
92+ COPY --from=otel-builder /opt-builder/ /opt/
93+ COPY infrastructure/aws/lambda/collector-config.yaml /opt/collector-config/config.yaml
94+
95+ # Copy dependencies from builder stage
96+ # OTEL packages to /opt/python (includes opentelemetry-instrument CLI)
97+ COPY --from=builder /opt-python /opt/python
98+
99+ # App packages to LAMBDA_RUNTIME_DIR
100+ COPY --from=builder /deps ${LAMBDA_RUNTIME_DIR}/
61101
62- # Copy only the cleaned dependencies from builder stage
63102# Copy required system library
64- COPY --from=builder /deps / usr/lib64/libexpat.so.1 ${LAMBDA_RUNTIME_DIR}/
103+ COPY --from=builder /usr/lib64/libexpat.so.1 ${LAMBDA_RUNTIME_DIR}/
65104
66105# Copy application handler and OpenTelemetry configuration
67- COPY infrastructure/aws/lambda/handler.py infrastructure/aws/lambda/otel_config.py ${LAMBDA_RUNTIME_DIR}/
106+ COPY infrastructure/aws/lambda/handler.py ${LAMBDA_RUNTIME_DIR}/
68107
69108# Ensure handler is executable and optimize permissions
70109RUN <<EOF
71110chmod 644 "${LAMBDA_RUNTIME_DIR}" /handler.py
111+ chmod -R 755 /opt/
72112# Pre-compile the handler for faster cold starts
73113python -c "import py_compile; py_compile.compile('${LAMBDA_RUNTIME_DIR}/handler.py', doraise=True)"
74114# Create cache directories with proper permissions
75115mkdir -p /tmp/.cache && chmod 777 /tmp/.cache
76116EOF
77117
78- # Set the Lambda handler
79118CMD ["handler.lambda_handler" ]
0 commit comments