Created
November 29, 2025 05:38
-
-
Save mrpackethead/2421373ae3faba55a4c98e9fca6bbaac to your computer and use it in GitHub Desktop.
Arm64 remote code build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as core from 'aws-cdk-lib'; | |
| import { | |
| aws_ecr as ecr, | |
| aws_codebuild as codebuild, | |
| aws_s3_assets as s3_assets, | |
| aws_lambda as lambda, | |
| aws_iam as iam, | |
| custom_resources as cr, | |
| } from 'aws-cdk-lib'; | |
| import * as constructs from 'constructs'; | |
| /** | |
| * Properties for AgentCoreArm64Build construct | |
| */ | |
| export interface AgentCoreArm64BuildProps { | |
| /** Path to the directory containing the Dockerfile and application code */ | |
| readonly containerPath: string; | |
| /** Name for the ECR repository */ | |
| readonly repositoryName: string; | |
| /** Name for the CodeBuild project */ | |
| readonly projectName: string; | |
| /** CodeBuild compute type (default: LARGE) */ | |
| readonly computeType?: codebuild.ComputeType; | |
| /** Docker image tag (default: 'latest') */ | |
| readonly imageTag?: string; | |
| } | |
| /** | |
| * Construct for building ARM64 container images using AWS CodeBuild. | |
| * | |
| * Creates an elastic build pipeline that: | |
| * - Uploads container source to S3 | |
| * - Builds ARM64 images natively (no QEMU emulation) | |
| * - Pushes to ECR | |
| * - Triggers builds automatically on deployment | |
| * | |
| * Ideal for workloads requiring ARM64 containers (like Bedrock AgentCore Runtimes) | |
| * without maintaining dedicated ARM64 build infrastructure. | |
| */ | |
| export class AgentCoreArm64Build extends constructs.Construct { | |
| /** Full ECR image URI including tag (e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/repo:latest) */ | |
| public readonly imageUri: string; | |
| /** ECR repository where the image is stored */ | |
| public readonly repository: ecr.Repository; | |
| /** CodeBuild project that performs the ARM64 build */ | |
| public readonly buildProject: codebuild.Project; | |
| /** Custom resource that triggers and waits for build completion during deployment */ | |
| public readonly buildComplete: core.CustomResource; | |
| constructor(scope: constructs.Construct, id: string, props: AgentCoreArm64BuildProps) { | |
| super(scope, id); | |
| const containerAsset = new s3_assets.Asset(this, 'Asset', { | |
| path: props.containerPath, | |
| }); | |
| this.repository = new ecr.Repository(this, 'Repo', { | |
| repositoryName: props.repositoryName, | |
| removalPolicy: core.RemovalPolicy.DESTROY, | |
| emptyOnDelete: true, | |
| }); | |
| const imageTag = props.imageTag ?? 'latest'; | |
| this.buildProject = new codebuild.Project(this, 'Build', { | |
| projectName: props.projectName, | |
| source: codebuild.Source.s3({ | |
| bucket: containerAsset.bucket, | |
| path: containerAsset.s3ObjectKey, | |
| }), | |
| environment: { | |
| buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_3_0, | |
| computeType: props.computeType ?? codebuild.ComputeType.LARGE, | |
| privileged: true, | |
| }, | |
| cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER), | |
| environmentVariables: { | |
| ECR_REGISTRY: { value: `${core.Stack.of(this).account}.dkr.ecr.${core.Stack.of(this).region}.amazonaws.com` }, | |
| IMAGE_REPO_NAME: { value: this.repository.repositoryName }, | |
| IMAGE_TAG: { value: imageTag }, | |
| AWS_DEFAULT_REGION: { value: core.Stack.of(this).region }, | |
| }, | |
| buildSpec: codebuild.BuildSpec.fromObject({ | |
| version: '0.2', | |
| phases: { | |
| pre_build: { | |
| commands: [ | |
| 'echo Logging in to Amazon ECR...', | |
| 'aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY', | |
| ], | |
| }, | |
| build: { | |
| commands: [ | |
| 'echo Building ARM64 Docker image for AgentCore...', | |
| 'docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .', | |
| 'docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $ECR_REGISTRY/$IMAGE_REPO_NAME:$IMAGE_TAG', | |
| ], | |
| }, | |
| post_build: { | |
| commands: [ | |
| 'echo Pushing image to ECR...', | |
| 'docker push $ECR_REGISTRY/$IMAGE_REPO_NAME:$IMAGE_TAG', | |
| ], | |
| }, | |
| }, | |
| }), | |
| }); | |
| containerAsset.grantRead(this.buildProject); | |
| this.repository.grantPullPush(this.buildProject); | |
| const triggerBuildFn = new lambda.SingletonFunction(this, 'TriggerFn', { | |
| uuid: 'agentcore-arm64-build-trigger', | |
| runtime: lambda.Runtime.PYTHON_3_13, | |
| handler: 'index.on_event', | |
| code: lambda.Code.fromInline(` | |
| import boto3 | |
| import time | |
| def on_event(event, context): | |
| request_type = event['RequestType'] | |
| if request_type == 'Create': return on_create(event) | |
| if request_type == 'Update': return on_update(event) | |
| if request_type == 'Delete': return on_delete(event) | |
| raise Exception("Invalid request type: %s" % request_type) | |
| def on_create(event): | |
| props = event["ResourceProperties"] | |
| project_name = props["ProjectName"] | |
| codebuild = boto3.client('codebuild') | |
| response = codebuild.start_build(projectName=project_name) | |
| build_id = response['build']['id'] | |
| while True: | |
| build_info = codebuild.batch_get_builds(ids=[build_id]) | |
| status = build_info['builds'][0]['buildStatus'] | |
| if status == 'SUCCEEDED': | |
| break | |
| elif status in ['FAILED', 'FAULT', 'TIMED_OUT', 'STOPPED']: | |
| raise Exception(f"Build failed with status: {status}") | |
| time.sleep(10) | |
| return {'PhysicalResourceId': build_id} | |
| def on_update(event): | |
| return on_create(event) | |
| def on_delete(event): | |
| pass | |
| `), | |
| timeout: core.Duration.minutes(15), | |
| }); | |
| triggerBuildFn.addToRolePolicy(new iam.PolicyStatement({ | |
| actions: ['codebuild:StartBuild', 'codebuild:BatchGetBuilds'], | |
| resources: [this.buildProject.projectArn], | |
| })); | |
| const provider = new cr.Provider(this, 'Provider', { | |
| onEventHandler: triggerBuildFn, | |
| }); | |
| const buildTrigger = new core.CustomResource(this, 'Trigger', { | |
| serviceToken: provider.serviceToken, | |
| resourceType: 'Custom::AgentCoreArm64BuildTrigger', | |
| properties: { | |
| ProjectName: this.buildProject.projectName, | |
| AssetHash: containerAsset.assetHash, | |
| }, | |
| }); | |
| buildTrigger.node.addDependency(this.buildProject); | |
| buildTrigger.node.addDependency(this.repository); | |
| this.buildComplete = buildTrigger; | |
| this.imageUri = `${this.repository.repositoryUri}:${imageTag}`; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment