Comprehensive bundling options for custom Docker images, private repositories, and complex deployment scenarios.
Main configuration interface for customizing the Python bundling process.
/**
* Options for bundling Python Lambda functions and layers
* Extends DockerRunOptions to provide full Docker configuration control
*/
interface BundlingOptions extends DockerRunOptions {
/**
* Whether to export Poetry dependencies with hashes
* Note that this can cause builds to fail if not all dependencies export with a hash
* @default false - Hashes are NOT included in the exported requirements.txt file
*/
readonly poetryIncludeHashes?: boolean;
/**
* Whether to export Poetry dependencies with source repository urls
* @default false - URLs are included in the exported requirements.txt file
*/
readonly poetryWithoutUrls?: boolean;
/**
* List of file patterns to exclude when copying assets from source for bundling
* @default [] - Empty list
*/
readonly assetExcludes?: string[];
/**
* Output path suffix: the suffix for the directory into which the bundled output is written
* @default 'python' for a layer, empty string otherwise
*/
readonly outputPathSuffix?: string;
/**
* Docker image to use for bundling
* If no options are provided, the default bundling image will be used
* @default - Default bundling image based on runtime
*/
readonly image?: DockerImage;
/**
* Optional build arguments to pass to the default container
* This can be used to customize index URLs used for installing dependencies
* This is not used if a custom image is provided
* @default - No build arguments
*/
readonly buildArgs?: { [key: string]: string };
/**
* Determines how asset hash is calculated
* Assets will get rebuild and uploaded only if their hash has changed
* @default AssetHashType.SOURCE - Hash calculated from source directory contents
*/
readonly assetHashType?: AssetHashType;
/**
* Specify a custom hash for this asset
* If assetHashType is set it must be set to AssetHashType.CUSTOM
* @default - Based on assetHashType
*/
readonly assetHash?: string;
/**
* Command hooks to run additional commands before and after bundling
* @default - Do not run additional commands
*/
readonly commandHooks?: ICommandHooks;
/**
* Which option to use to copy source files to the docker container and output files back
* @default BundlingFileAccess.BIND_MOUNT
*/
readonly bundlingFileAccess?: BundlingFileAccess;
}Interface for defining pre and post bundling commands.
/**
* Command hooks for running additional commands during bundling
* These commands will run in the environment in which bundling occurs:
* inside the container for Docker bundling or on the host OS for local bundling
* Commands are chained with &&
*/
interface ICommandHooks {
/**
* Returns commands to run before bundling
* Commands are chained with &&
* @param inputDir - Directory containing the source files
* @param outputDir - Directory where bundled output will be written
* @returns Array of shell commands to execute
*/
beforeBundling(inputDir: string, outputDir: string): string[];
/**
* Returns commands to run after bundling
* Commands are chained with &&
* @param inputDir - Directory containing the source files
* @param outputDir - Directory where bundled output was written
* @returns Array of shell commands to execute
*/
afterBundling(inputDir: string, outputDir: string): string[];
}Configure Poetry-specific bundling options:
import * as python from '@aws-cdk/aws-lambda-python-alpha';
const func = new python.PythonFunction(this, 'PoetryFunction', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
poetryIncludeHashes: true, // Include dependency hashes in requirements.txt
poetryWithoutUrls: false, // Include source repository URLs
},
});Exclude files and directories from the bundling process:
const func = new python.PythonFunction(this, 'ExcludeFiles', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
assetExcludes: [
'*.pyc', // Compiled Python files
'__pycache__/', // Python cache directories
'.git/', // Git repository
'.venv/', # Virtual environment
'tests/', # Test files
'*.log', # Log files
'.DS_Store', # macOS system files
'*.tmp', # Temporary files
'node_modules/', # Node.js modules (if present)
],
},
});Use a custom Docker image for bundling:
import { DockerImage } from 'aws-cdk-lib/core';
// Build custom image from local Dockerfile
const customImage = DockerImage.fromBuild('./docker-build');
const func = new python.PythonFunction(this, 'CustomDockerFunction', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
image: customImage,
},
});Pass build arguments for private repositories or custom configurations:
const func = new python.PythonFunction(this, 'PrivateRepoFunction', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
buildArgs: {
PIP_INDEX_URL: 'https://pypi.org/simple/',
PIP_EXTRA_INDEX_URL: 'https://private.pypi.example.com/simple/',
HTTPS_PROXY: 'https://proxy.example.com:8080',
},
},
});Control how asset hashing is calculated:
import { AssetHashType } from 'aws-cdk-lib/core';
// Hash based on source files (default)
const sourceHashFunc = new python.PythonFunction(this, 'SourceHash', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
assetHashType: AssetHashType.SOURCE,
},
});
// Hash based on output (rebuilds every time due to timestamps)
const outputHashFunc = new python.PythonFunction(this, 'OutputHash', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
assetHashType: AssetHashType.OUTPUT,
},
});
// Custom hash for manual control
const customHashFunc = new python.PythonFunction(this, 'CustomHash', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
assetHashType: AssetHashType.CUSTOM,
assetHash: 'my-custom-hash-v1.2.3',
},
});Run additional commands before and after bundling:
const func = new python.PythonFunction(this, 'WithHooks', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
commandHooks: {
beforeBundling(inputDir: string, outputDir: string): string[] {
return [
'echo "Starting bundling process"',
'pip install --upgrade pip',
'pip install wheel',
'pytest', // Run tests before bundling
];
},
afterBundling(inputDir: string, outputDir: string): string[] {
return [
'echo "Bundling completed"',
'find . -name "*.pyc" -delete', // Clean up compiled files
'find . -name "__pycache__" -delete', // Clean up cache directories
'pip list > installed_packages.txt', // List installed packages
'du -sh .', // Show bundle size
];
},
},
},
});Configure file access method for Docker bundling:
import { BundlingFileAccess } from 'aws-cdk-lib/core';
// Default bind mount (faster)
const bindMountFunc = new python.PythonFunction(this, 'BindMount', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
bundlingFileAccess: BundlingFileAccess.BIND_MOUNT,
},
});
// Volume copy (works in Docker-in-Docker scenarios)
const volumeCopyFunc = new python.PythonFunction(this, 'VolumeCopy', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,
},
});Configure bundling for AWS CodeArtifact private repositories:
import { execSync } from 'child_process';
// Get CodeArtifact authorization token
const domain = 'my-domain';
const domainOwner = '111122223333';
const repoName = 'my_repo';
const region = 'us-east-1';
const codeArtifactAuthToken = execSync(
`aws codeartifact get-authorization-token --domain ${domain} --domain-owner ${domainOwner} --query authorizationToken --output text`
).toString().trim();
const indexUrl = `https://aws:${codeArtifactAuthToken}@${domain}-${domainOwner}.d.codeartifact.${region}.amazonaws.com/pypi/${repoName}/simple/`;
const func = new python.PythonFunction(this, 'CodeArtifactFunction', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
environment: {
PIP_INDEX_URL: indexUrl,
},
// Alternative: use buildArgs for Docker image building
buildArgs: {
PIP_INDEX_URL: indexUrl,
},
},
});Advanced Docker configuration with networking, security, and volumes:
import { DockerVolume } from 'aws-cdk-lib/core';
const func = new python.PythonFunction(this, 'AdvancedDocker', {
entry: './lambda',
runtime: Runtime.PYTHON_3_8,
bundling: {
network: 'host', // Use host networking
securityOpt: 'no-new-privileges', // Security options
user: '1000:1000', // Run as specific user
volumes: [{ // Mount volumes
hostPath: '/tmp/cache',
containerPath: '/cache',
}],
volumesFrom: ['cache-container'], // Use volumes from other containers
workingDirectory: '/app', // Set working directory
environment: { // Environment variables
PYTHONPATH: '/opt/python',
PIP_CACHE_DIR: '/cache',
},
},
});Configuration specific to Python layers:
const layer = new python.PythonLayerVersion(this, 'ConfiguredLayer', {
entry: './layer',
compatibleRuntimes: [Runtime.PYTHON_3_8],
bundling: {
outputPathSuffix: 'python', // Required for proper layer structure
assetExcludes: ['*.pyc', '__pycache__'],
commandHooks: {
beforeBundling: () => ['pip install --upgrade pip'],
afterBundling: () => ['find . -name "*.pyc" -delete'],
},
},
});When using custom Docker images, the build context and bundling process work as follows:
The library provides a default Dockerfile that can be customized:
ARG IMAGE
FROM $IMAGE
# Install system dependencies
RUN yum update -y && yum install -y gcc
# Copy and install requirements
COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt
# Your customizations here.dockerignore files to exclude unnecessary filesAssetHashType.SOURCE for faster builds (default)AssetHashType.OUTPUT when necessaryUse command hooks for debugging bundling issues:
commandHooks: {
beforeBundling: () => [
'pwd', # Show current directory
'ls -la', # List files
'python --version', # Show Python version
'pip --version', # Show pip version
],
afterBundling: () => [
'find . -type f | head -20', # Show bundled files
'du -sh .', # Show bundle size
'pip list', # Show installed packages
],
}