资产和 AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

资产和 AWS CDK

资产是可以捆绑至 AWS CDK 库和应用程序中的本地文件、目录或 Docker 映像。例如,资产可能是包含 AWS Lambda 函数处理程序代码的目录。资产可以代表应用程序需要操作的任何构件。

以下教程视频对 CDK 资产进行了全面概述,并说明了如何在基础设施即代码 (IaC) 中使用 CDK 资产。

您可以通过特定 AWS 构造公开的 API 添加资产。例如,在定义 lambda.Function 构造时,code 代码属性允许您传递 asset(目录)。Function 使用资产捆绑目录内容并将其用于函数的代码。同样,ecs.ContainerImage.fromAsset 在定义 Amazon ECS 任务定义时使用基于本地目录构建的 Docker 映像。

资产详细说明

若在应用程序中引用资产,应用程序所合成的云程序集则包含带有 AWS CDK CLI 说明的元数据信息。说明包括在资产在本地磁盘中的位置,以及根据资产类型 [例如要压缩的目录(zip)或待构建的 Docker 映像] 执行的捆绑类型。

AWS CDK 生成资产的源哈希。这可以在构建时用于确定资产内容是否变更。

默认情况下,AWS CDK 会为云程序集目录中的资产创建副本,在源哈希下,默认为 cdk.out。这样云程序集实现了独立,因此,如果将其移至另一台主机进行部署,云程序集仍可部署。有关详细信息,请参阅云程序集

若 AWS CDK 部署引用资产的应用程序(直接通过应用程序代码或通过库引用),AWS CDK CLI 会首先准备这些资产并将其发布至 Amazon S3 存储桶或 Amazon ECR 存储库中。(S3 存储桶或存储库于启动期间创建。) 只有这样,堆栈中定义的资源才会部署。

本节介绍框架中可用的低级别 API。

资产类型

AWS CDK 支持以下类型的资产:

Amazon S3 资产

这些是 AWS CDK 上传至 Amazon S3 的本地文件和目录。

Docker 映像

这些是 AWS CDK 上传至 Amazon ECR 的 Docker 映像。

这些资产类型将在以下部分详细介绍。

Amazon S3 资产

您可以将本地文件和目录定义为资产,随后 AWS CDK 通过 aws-s3-assets 模块将其打包并上传至 Amazon S3。

以下示例定义了本地目录资产和文件资产。

TypeScript
import { Asset } from 'aws-cdk-lib/aws-s3-assets'; // Archived and uploaded to Amazon S3 as a .zip file const directoryAsset = new Asset(this, "SampleZippedDirAsset", { path: path.join(__dirname, "sample-asset-directory") }); // Uploaded to Amazon S3 as-is const fileAsset = new Asset(this, 'SampleSingleFileAsset', { path: path.join(__dirname, 'file-asset.txt') });
JavaScript
const { Asset } = require('aws-cdk-lib/aws-s3-assets'); // Archived and uploaded to Amazon S3 as a .zip file const directoryAsset = new Asset(this, "SampleZippedDirAsset", { path: path.join(__dirname, "sample-asset-directory") }); // Uploaded to Amazon S3 as-is const fileAsset = new Asset(this, 'SampleSingleFileAsset', { path: path.join(__dirname, 'file-asset.txt') });
Python
import os.path dirname = os.path.dirname(__file__) from aws_cdk.aws_s3_assets import Asset # Archived and uploaded to Amazon S3 as a .zip file directory_asset = Asset(self, "SampleZippedDirAsset", path=os.path.join(dirname, "sample-asset-directory") ) # Uploaded to Amazon S3 as-is file_asset = Asset(self, 'SampleSingleFileAsset', path=os.path.join(dirname, 'file-asset.txt') )
Java
import java.io.File; import software.amazon.awscdk.services.s3.assets.Asset; // Directory where app was started File startDir = new File(System.getProperty("user.dir")); // Archived and uploaded to Amazon S3 as a .zip file Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset") .path(new File(startDir, "sample-asset-directory").toString()).build(); // Uploaded to Amazon S3 as-is Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset") .path(new File(startDir, "file-asset.txt").toString()).build();
C#
using System.IO; using Amazon.CDK.AWS.S3.Assets; // Archived and uploaded to Amazon S3 as a .zip file var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps { Path = Path.Combine(Directory.GetCurrentDirectory(), "sample-asset-directory") }); // Uploaded to Amazon S3 as-is var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps { Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt") });
Go
dirName, err := os.Getwd() if err != nil { panic(err) } awss3assets.NewAsset(stack, jsii.String("SampleZippedDirAsset"), awss3assets.AssetProps{ Path: jsii.String(path.Join(dirName, "sample-asset-directory")), }) awss3assets.NewAsset(stack, jsii.String("SampleSingleFileAsset"), awss3assets.AssetProps{ Path: jsii.String(path.Join(dirName, "file-asset.txt")), })

大多数情况下,您无需直接使用 aws-s3-assets 模块中的 API。支持资产的模块(例如 aws-lambda)为您提供使用资产的便捷方法。对于 Lambda 函数,您可以采用 fromAsset() 静态方法在本地文件系统中指定目录或 .zip 文件。

Lambda 函数示例

常见用例是将处理程序代码作为 Amazon S3 资产用于创建 Lambda 函数。

以下示例使用 Amazon S3 资产在本地目录 handler 中定义 Python 处理程序。此外还创建了本地目录资产为 code 属性的 Lambda 函数。以下是该处理程序的 Python 代码。

def lambda_handler(event, context): message = 'Hello World!' return { 'message': message }

主 AWS CDK 应用程序的代码应如下所示。

TypeScript
import * as cdk from 'aws-cdk-lib'; import { Constructs } from 'constructs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as path from 'path'; export class HelloAssetStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new lambda.Function(this, 'myLambdaFunction', { code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), runtime: lambda.Runtime.PYTHON_3_6, handler: 'index.lambda_handler' }); } }
JavaScript
const cdk = require('aws-cdk-lib'); const lambda = require('aws-cdk-lib/aws-lambda'); const path = require('path'); class HelloAssetStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); new lambda.Function(this, 'myLambdaFunction', { code: lambda.Code.fromAsset(path.join(__dirname, 'handler')), runtime: lambda.Runtime.PYTHON_3_6, handler: 'index.lambda_handler' }); } } module.exports = { HelloAssetStack }
Python
from aws_cdk import Stack from constructs import Construct from aws_cdk import aws_lambda as lambda_ import os.path dirname = os.path.dirname(__file__) class HelloAssetStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) lambda_.Function(self, 'myLambdaFunction', code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')), runtime=lambda_.Runtime.PYTHON_3_6, handler="index.lambda_handler")
Java
import java.io.File; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.lambda.Function; import software.amazon.awscdk.services.lambda.Runtime; public class HelloAssetStack extends Stack { public HelloAssetStack(final App scope, final String id) { this(scope, id, null); } public HelloAssetStack(final App scope, final String id, final StackProps props) { super(scope, id, props); File startDir = new File(System.getProperty("user.dir")); Function.Builder.create(this, "myLambdaFunction") .code(Code.fromAsset(new File(startDir, "handler").toString())) .runtime(Runtime.PYTHON_3_6) .handler("index.lambda_handler").build(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.Lambda; using System.IO; public class HelloAssetStack : Stack { public HelloAssetStack(Construct scope, string id, StackProps props) : base(scope, id, props) { new Function(this, "myLambdaFunction", new FunctionProps { Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), Runtime = Runtime.PYTHON_3_6, Handler = "index.lambda_handler" }); } }
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" ) func HelloAssetStack(scope constructs.Construct, id string, props *HelloAssetStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } stack := awscdk.NewStack(scope, id, sprops) dirName, err := os.Getwd() if err != nil { panic(err) } awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{ Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler")), awss3assets.AssetOptions{}), Runtime: awslambda.Runtime_PYTHON_3_6(), Handler: jsii.String("index.lambda_handler"), }) return stack }

Function 方法使用资产捆绑目录内容,并将其用于函数代码。

提示

Java .jar 文件是具有不同扩展名的 ZIP 文件。文件原样上传至 Amazon S3,但若作为 Lambda 函数部署,其中包含的文件会被提取,而这可能并非如您预期。为避免这种情况,请将 .jar 文件放在目录中并将目录指定为资产。

部署时属性示例

Amazon S3 资产类型还公开了可在 AWS CDK 库和应用程序中引用的 deploy-time 属性。AWS CDK CLI 命令 cdk synth 将资产属性显示为 AWS CloudFormation 参数。

以下示例使用部署时属性将映像资产位置作为环境变量传递至 Lambda 函数中。(文件类型无关紧要;此处使用的 PNG 图像仅为示例。)

TypeScript
import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import * as path from 'path'; const imageAsset = new Asset(this, "SampleAsset", { path: path.join(__dirname, "images/my-image.png") }); new lambda.Function(this, "myLambdaFunction", { code: lambda.Code.asset(path.join(__dirname, "handler")), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.lambda_handler", environment: { 'S3_BUCKET_NAME': imageAsset.s3BucketName, 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, 'S3_OBJECT_URL': imageAsset.s3ObjectUrl } });
JavaScript
const { Asset } = require('aws-cdk-lib/aws-s3-assets'); const path = require('path'); const imageAsset = new Asset(this, "SampleAsset", { path: path.join(__dirname, "images/my-image.png") }); new lambda.Function(this, "myLambdaFunction", { code: lambda.Code.asset(path.join(__dirname, "handler")), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.lambda_handler", environment: { 'S3_BUCKET_NAME': imageAsset.s3BucketName, 'S3_OBJECT_KEY': imageAsset.s3ObjectKey, 'S3_OBJECT_URL': imageAsset.s3ObjectUrl } });
Python
import os.path import aws_cdk.aws_lambda as lambda_ from aws_cdk.aws_s3_assets import Asset dirname = os.path.dirname(__file__) image_asset = Asset(self, "SampleAsset", path=os.path.join(dirname, "images/my-image.png")) lambda_.Function(self, "myLambdaFunction", code=lambda_.Code.asset(os.path.join(dirname, "handler")), runtime=lambda_.Runtime.PYTHON_3_6, handler="index.lambda_handler", environment=dict( S3_BUCKET_NAME=image_asset.s3_bucket_name, S3_OBJECT_KEY=image_asset.s3_object_key, S3_OBJECT_URL=image_asset.s3_object_url))
Java
import java.io.File; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.lambda.Function; import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.s3.assets.Asset; public class FunctionStack extends Stack { public FunctionStack(final App scope, final String id, final StackProps props) { super(scope, id, props); File startDir = new File(System.getProperty("user.dir")); Asset imageAsset = Asset.Builder.create(this, "SampleAsset") .path(new File(startDir, "images/my-image.png").toString()).build()) Function.Builder.create(this, "myLambdaFunction") .code(Code.fromAsset(new File(startDir, "handler").toString())) .runtime(Runtime.PYTHON_3_6) .handler("index.lambda_handler") .environment(java.util.Map.of( // Java 9 or later "S3_BUCKET_NAME", imageAsset.getS3BucketName(), "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(), "S3_OBJECT_URL", imageAsset.getS3ObjectUrl())) .build(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.Lambda; using Amazon.CDK.AWS.S3.Assets; using System.IO; using System.Collections.Generic; var imageAsset = new Asset(this, "SampleAsset", new AssetProps { Path = Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png") }); new Function(this, "myLambdaFunction", new FunctionProps { Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")), Runtime = Runtime.PYTHON_3_6, Handler = "index.lambda_handler", Environment = new Dictionarystring, string { ["S3_BUCKET_NAME"] = imageAsset.S3BucketName, ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey, ["S3_OBJECT_URL"] = imageAsset.S3ObjectUrl } });
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awslambda" "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" ) dirName, err := os.Getwd() if err != nil { panic(err) } imageAsset := awss3assets.NewAsset(stack, jsii.String("SampleAsset"), awss3assets.AssetProps{ Path: jsii.String(path.Join(dirName, "images/my-image.png")), }) awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{ Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler"))), Runtime: awslambda.Runtime_PYTHON_3_6(), Handler: jsii.String("index.lambda_handler"), Environment: map[string]*string{ "S3_BUCKET_NAME": imageAsset.S3BucketName(), "S3_OBJECT_KEY": imageAsset.S3ObjectKey(), "S3_URL": imageAsset.S3ObjectUrl(), }, })

权限

若直接通过 aws-s3-assets 模块、IAM 角色、用户或组使用 Amazon S3 资产,并且需要在运行时读取资产,请通过 asset.grantRead 方法向这些资产授予 IAM 权限。

以下示例向 IAM 组授予文件资产的读取权限。

TypeScript
import { Asset } from 'aws-cdk-lib/aws-s3-assets'; import * as path from 'path'; const asset = new Asset(this, 'MyFile', { path: path.join(__dirname, 'my-image.png') }); const group = new iam.Group(this, 'MyUserGroup'); asset.grantRead(group);
JavaScript
const { Asset } = require('aws-cdk-lib/aws-s3-assets'); const path = require('path'); const asset = new Asset(this, 'MyFile', { path: path.join(__dirname, 'my-image.png') }); const group = new iam.Group(this, 'MyUserGroup'); asset.grantRead(group);
Python
from aws_cdk.aws_s3_assets import Asset import aws_cdk.aws_iam as iam import os.path dirname = os.path.dirname(__file__) asset = Asset(self, "MyFile", path=os.path.join(dirname, "my-image.png")) group = iam.Group(self, "MyUserGroup") asset.grant_read(group)
Java
import java.io.File; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.iam.Group; import software.amazon.awscdk.services.s3.assets.Asset; public class GrantStack extends Stack { public GrantStack(final App scope, final String id, final StackProps props) { super(scope, id, props); File startDir = new File(System.getProperty("user.dir")); Asset asset = Asset.Builder.create(this, "SampleAsset") .path(new File(startDir, "images/my-image.png").toString()).build(); Group group = new Group(this, "MyUserGroup"); asset.grantRead(group); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.IAM; using Amazon.CDK.AWS.S3.Assets; using System.IO; var asset = new Asset(this, "MyFile", new AssetProps { Path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png")) }); var group = new Group(this, "MyUserGroup"); asset.GrantRead(group);
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" ) dirName, err := os.Getwd() if err != nil { panic(err) } asset := awss3assets.NewAsset(stack, jsii.String("MyFile"), awss3assets.AssetProps{ Path: jsii.String(path.Join(dirName, "my-image.png")), }) group := awsiam.NewGroup(stack, jsii.String("MyUserGroup"), awsiam.GroupProps{}) asset.GrantRead(group)

Docker 映像资产

AWS CDK 支持通过 aws-ecr-assets 模块将本地 Docker 映像作为资产进行捆绑。

以下示例定义本地构建并推送至 Amazon ECR 的 Docker 映像。映像基于本地 Docker 上下文目录(包含 Dockerfile)构建,并由 AWS CDK CLI 或应用程序的 CI/CD 管线上传至 Amazon ECR。映像可以在 AWS CDK 应用程序中自然引用。

TypeScript
import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') });
JavaScript
const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') });
Python
from aws_cdk.aws_ecr_assets import DockerImageAsset import os.path dirname = os.path.dirname(__file__) asset = DockerImageAsset(self, 'MyBuildImage', directory=os.path.join(dirname, 'my-image'))
Java
import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; File startDir = new File(System.getProperty("user.dir")); DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") .directory(new File(startDir, "my-image").toString()).build();
C#
using System.IO; using Amazon.CDK.AWS.ECR.Assets; var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image") });
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" ) dirName, err := os.Getwd() if err != nil { panic(err) } asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{ Directory: jsii.String(path.Join(dirName, "my-image")), })

my-image 目录必须包含 Dockerfile。AWS CDK CLI 基于 my-image 构建 Docker 映像,将其推送至 Amazon ECR 存储库,并将存储库名称指定为堆栈的 AWS CloudFormation 参数。Docker 映像资产类型公开了 AWS CDK 库和应用程序中可引用的 deploy-time 属性。AWS CDK CLI 命令 cdk synth 将资产属性显示为 AWS CloudFormation 参数。

Amazon ECS 任务定义示例

常见使用案例是通过创建 Amazon ECS TaskDefinition 运行 Docker 容器。以下示例指定了 AWS CDK 在本地构建并推送至 Amazon ECR 的 Docker 映像资产位置。

TypeScript
import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets'; import * as path from 'path'; const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { memoryLimitMiB: 1024, cpu: 512 }); const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') }); taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromDockerImageAsset(asset) });
JavaScript
const ecs = require('aws-cdk-lib/aws-ecs'); const ecr_assets = require('aws-cdk-lib/aws-ecr-assets'); const path = require('path'); const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { memoryLimitMiB: 1024, cpu: 512 }); const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') }); taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromDockerImageAsset(asset) });
Python
import aws_cdk.aws_ecs as ecs import aws_cdk.aws_ecr_assets as ecr_assets import os.path dirname = os.path.dirname(__file__) task_definition = ecs.FargateTaskDefinition(self, "TaskDef", memory_limit_mib=1024, cpu=512) asset = ecr_assets.DockerImageAsset(self, 'MyBuildImage', directory=os.path.join(dirname, 'my-image')) task_definition.add_container("my-other-container", image=ecs.ContainerImage.from_docker_image_asset(asset))
Java
import java.io.File; import software.amazon.awscdk.services.ecs.FargateTaskDefinition; import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; import software.amazon.awscdk.services.ecs.ContainerImage; import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; File startDir = new File(System.getProperty("user.dir")); FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage") .directory(new File(startDir, "my-image").toString()).build(); taskDefinition.addContainer("my-other-container", ContainerDefinitionOptions.builder() .image(ContainerImage.fromDockerImageAsset(asset)) .build(); )
C#
using System.IO; using Amazon.CDK.AWS.ECS; using Amazon.CDK.AWS.Ecr.Assets; var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps { MemoryLimitMiB = 1024, Cpu = 512 }); var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image") }); taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions { Image = ContainerImage.FromDockerImageAsset(asset) });
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" ) dirName, err := os.Getwd() if err != nil { panic(err) } taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("TaskDef"), awsecs.TaskDefinitionProps{ MemoryMiB: jsii.String("1024"), Cpu: jsii.String("512"), }) asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{ Directory: jsii.String(path.Join(dirName, "my-image")), }) taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{ Image: awsecs.ContainerImage_FromDockerImageAsset(asset), })

部署时属性示例

以下示例说明如何使用部署时属性 repositoryimageUri 创建具有 AWS Fargate 启动类型的 Amazon ECS 任务定义。请注意,Amazon ECR 存储库查询需要映像的标签而非其 URI,因此我们从资产 URI 的末尾截取标签。

TypeScript
import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as path from 'path'; import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; const asset = new DockerImageAsset(this, 'my-image', { directory: path.join(__dirname, "..", "demo-image") }); const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { memoryLimitMiB: 1024, cpu: 512 }); taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) });
JavaScript
const ecs = require('aws-cdk-lib/aws-ecs'); const path = require('path'); const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets'); const asset = new DockerImageAsset(this, 'my-image', { directory: path.join(__dirname, "..", "demo-image") }); const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { memoryLimitMiB: 1024, cpu: 512 }); taskDefinition.addContainer("my-other-container", { image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop()) });
Python
import aws_cdk.aws_ecs as ecs from aws_cdk.aws_ecr_assets import DockerImageAsset import os.path dirname = os.path.dirname(__file__) asset = DockerImageAsset(self, 'my-image', directory=os.path.join(dirname, "..", "demo-image")) task_definition = ecs.FargateTaskDefinition(self, "TaskDef", memory_limit_mib=1024, cpu=512) task_definition.add_container("my-other-container", image=ecs.ContainerImage.from_ecr_repository( asset.repository, asset.image_uri.rpartition(":")[-1]))
Java
import java.io.File; import software.amazon.awscdk.services.ecr.assets.DockerImageAsset; import software.amazon.awscdk.services.ecs.FargateTaskDefinition; import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions; import software.amazon.awscdk.services.ecs.ContainerImage; File startDir = new File(System.getProperty("user.dir")); DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image") .directory(new File(startDir, "demo-image").toString()).build(); FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create( this, "TaskDef").memoryLimitMiB(1024).cpu(512).build(); // extract the tag from the asset's image URI for use in ECR repo lookup String imageUri = asset.getImageUri(); String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1); taskDefinition.addContainer("my-other-container", ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository( asset.getRepository(), imageTag)).build());
C#
using System.IO; using Amazon.CDK.AWS.ECS; using Amazon.CDK.AWS.ECR.Assets; var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image") }); var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps { MemoryLimitMiB = 1024, Cpu = 512 }); taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions { Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last()) });
Go
import ( "os" "path" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" ) dirName, err := os.Getwd() if err != nil { panic(err) } asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyImage"), awsecrassets.DockerImageAssetProps{ Directory: jsii.String(path.Join(dirName, "demo-image")), }) taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("TaskDef"), awsecs.FargateTaskDefinitionProps{ MemoryLimitMiB: jsii.Number(1024), Cpu: jsii.Number(512), }) taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{ Image: awsecs.ContainerImage_FromEcrRepository(asset.Repository(), asset.ImageTag()), })

构建参数示例

AWS CDK CLI 在部署期间构建映像时,您可以通过 buildArgs(Python:build_args)属性选项为 Docker 构建步骤提供自定义构建参数。

TypeScript
const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image'), buildArgs: { HTTP_PROXY: 'http://10.20.30.2:1234' } });
JavaScript
const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image'), buildArgs: { HTTP_PROXY: 'http://10.20.30.2:1234' } });
Python
asset = DockerImageAsset(self, "MyBuildImage", directory=os.path.join(dirname, "my-image"), build_args=dict(HTTP_PROXY="http://10.20.30.2:1234"))
Java
DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"), .directory(new File(startDir, "my-image").toString()) .buildArgs(java.util.Map.of( // Java 9 or later "HTTP_PROXY", "http://10.20.30.2:1234")) .build();
C#
var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps { Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"), BuildArgs = new Dictionarystring, string { ["HTTP_PROXY"] = "http://10.20.30.2:1234" } });
Go
dirName, err := os.Getwd() if err != nil { panic(err) } asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{ Directory: jsii.String(path.Join(dirName, "my-image")), BuildArgs: map[string]*string{ "HTTP_PROXY": jsii.String("http://10.20.30.2:1234"), }, })

权限

如果您使用支持 Docker 映像资产的模块(例如 aws-ecs),那么当您直接使用资源或通过 ContainerImage.fromEcrRepository(Python:from_ecr_repository)使用资源时,AWS CDK 会为您管理权限。如果您直接使用 Docker 映像资产,请确保使用主体拥有拉取映像的权限。

大多数情况下,应使用 asset.repository.grantPull 方法(Python:grant_pull)。这会修改主体的 IAM 策略,使其能够从此存储库中提取映像。如果提取映像的主体不在同一个账户中,或者 AWS 服务不在您的账户中代入角色(例如 AWS CodeBuild),则必须授予对资源策略的拉取权限,而不是对主体策略的拉取权限。使用 asset.repository.addToResourcePolicy 方法(Python:add_to_resource_policy)授予相应的主体权限。

AWS CloudFormation 资源元数据

注意

本节仅与构造作者相关。在某些情况下,工具需要了解某个 CFN 资源正在使用本地资产。例如,您可以使用 AWS SAM CLI 在本地调用 Lambda 函数,以便进行调试。有关详细信息,请参阅 AWS SAM 集成

要启用此类使用案例,外部工具会在 AWS CloudFormation 资源中查阅一组元数据条目:

  • aws:asset:path – 指向资产的本地路径。

  • aws:asset:property – 使用资产的资源属性的名称。

通过使用这两个元数据条目,工具可以识别特定资源是否使用资产,并提供高级本地体验。

要将这些元数据条目添加至资源中,请使用 asset.addResourceMetadata(Python:add_resource_metadata)方法。