Skip to content

Instantly share code, notes, and snippets.

@mrpackethead
Created November 29, 2025 05:38
Show Gist options
  • Select an option

  • Save mrpackethead/2421373ae3faba55a4c98e9fca6bbaac to your computer and use it in GitHub Desktop.

Select an option

Save mrpackethead/2421373ae3faba55a4c98e9fca6bbaac to your computer and use it in GitHub Desktop.
Arm64 remote code build
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