or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bundling-configuration.mdindex.mdpackaging-systems.mdpython-functions.mdpython-layers.md
tile.json

bundling-configuration.mddocs/

Bundling Configuration

Comprehensive bundling options for custom Docker images, private repositories, and complex deployment scenarios.

Capabilities

BundlingOptions Interface

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;
}

Command Hooks Interface

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[];
}

Usage Examples

Poetry Configuration

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
  },
});

Asset Exclusions

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)
    ],
  },
});

Custom Docker Image

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,
  },
});

Custom Build Arguments

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',
    },
  },
});

Asset Hash Configuration

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',
  },
});

Command Hooks

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
        ];
      },
    },
  },
});

Bundling File Access

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,
  },
});

AWS CodeArtifact Integration

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,
    },
  },
});

Complex Docker Configuration

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',
    },
  },
});

Layer-Specific Configuration

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'],
    },
  },
});

Docker Build Context

When using custom Docker images, the build context and bundling process work as follows:

  1. Default Image: Uses AWS Lambda's official Python base images
  2. Custom Build: Builds from your Dockerfile with runtime-specific base image
  3. Build Args: Passed to Docker build for customization
  4. Platform: Automatically set based on target Lambda architecture

Default Dockerfile Structure

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

Performance Optimization

Build Caching

  • Use consistent base images for Docker layer caching
  • Include lockfiles for reproducible dependency resolution
  • Use .dockerignore files to exclude unnecessary files

Asset Hash Optimization

  • Use AssetHashType.SOURCE for faster builds (default)
  • Only use AssetHashType.OUTPUT when necessary
  • Consider custom hashes for manual cache control

Bundling Speed

  • Minimize asset exclusions processing overhead
  • Use bind mounts when possible (default)
  • Cache dependencies in Docker volumes for faster rebuilds

Troubleshooting

Common Issues

  • Build failures: Check Docker image compatibility with target runtime
  • Permission errors: Verify Docker user permissions and security options
  • Network issues: Configure proxy settings and network access
  • Size limits: Monitor bundle size and exclude unnecessary files

Debugging Commands

Use 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
  ],
}