aws-cdk-lib.aws_ecs.TagParameterContainerImage

class TagParameterContainerImage

LanguageType name
.NETAmazon.CDK.AWS.ECS.TagParameterContainerImage
Gogithub.com/aws/aws-cdk-go/awscdk/v2/awsecs#TagParameterContainerImage
Javasoftware.amazon.awscdk.services.ecs.TagParameterContainerImage
Pythonaws_cdk.aws_ecs.TagParameterContainerImage
TypeScript (source)aws-cdk-lib » aws_ecs » TagParameterContainerImage

Extends ContainerImage

A special type of ContainerImage that uses an ECR repository for the image, but a CloudFormation Parameter for the tag of the image in that repository.

This allows providing this tag through the Parameter at deploy time, for example in a CodePipeline that pushes a new tag of the image to the repository during a build step, and then provides that new tag through the CloudFormation Parameter in the deploy step.

See also: #tagParameterName

Example


/**
 * These are the construction properties for `EcsAppStack`.
 * They extend the standard Stack properties,
 * but also require providing the ContainerImage that the service will use.
 * That Image will be provided from the Stack containing the CodePipeline.
 */
export interface EcsAppStackProps extends cdk.StackProps {
  readonly image: ecs.ContainerImage;
}

/**
 * This is the Stack containing a simple ECS Service that uses the provided ContainerImage.
 */
export class EcsAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: EcsAppStackProps) {
    super(scope, id, props);

    const taskDefinition = new ecs.TaskDefinition(this, 'TaskDefinition', {
      compatibility: ecs.Compatibility.FARGATE,
      cpu: '1024',
      memoryMiB: '2048',
    });
    taskDefinition.addContainer('AppContainer', {
      image: props.image,
    });
    new ecs.FargateService(this, 'EcsService', {
      taskDefinition,
      cluster: new ecs.Cluster(this, 'Cluster', {
        vpc: new ec2.Vpc(this, 'Vpc', {
          maxAzs: 1,
        }),
      }),
    });
  }
}

/**
 * This is the Stack containing the CodePipeline definition that deploys an ECS Service.
 */
export class PipelineStack extends cdk.Stack {
  public readonly tagParameterContainerImage: ecs.TagParameterContainerImage;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    /* ********** ECS part **************** */

    // this is the ECR repository where the built Docker image will be pushed
    const appEcrRepo = new ecr.Repository(this, 'EcsDeployRepository');
    // the build that creates the Docker image, and pushes it to the ECR repo
    const appCodeDockerBuild = new codebuild.PipelineProject(this, 'AppCodeDockerImageBuildAndPushProject', {
      environment: {
        // we need to run Docker
        privileged: true,
      },
      buildSpec: codebuild.BuildSpec.fromObject({
        version: '0.2',
        phases: {
          build: {
            commands: [
              // login to ECR first
              '$(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)',
              // if your application needs any build steps, they would be invoked here

              // build the image, and tag it with the commit hash
              // (CODEBUILD_RESOLVED_SOURCE_VERSION is a special environment variable available in CodeBuild)
              'docker build -t $REPOSITORY_URI:$CODEBUILD_RESOLVED_SOURCE_VERSION .',
            ],
          },
          post_build: {
            commands: [
              // push the built image into the ECR repository
              'docker push $REPOSITORY_URI:$CODEBUILD_RESOLVED_SOURCE_VERSION',
              // save the declared tag as an environment variable,
              // that is then exported below in the 'exported-variables' section as a CodePipeline Variable
              'export imageTag=$CODEBUILD_RESOLVED_SOURCE_VERSION',
            ],
          },
        },
        env: {
          // save the imageTag environment variable as a CodePipeline Variable
          'exported-variables': [
            'imageTag',
          ],
        },
      }),
      environmentVariables: {
        REPOSITORY_URI: {
          value: appEcrRepo.repositoryUri,
        },
      },
    });
    // needed for `docker push`
    appEcrRepo.grantPullPush(appCodeDockerBuild);
    // create the ContainerImage used for the ECS application Stack
    this.tagParameterContainerImage = new ecs.TagParameterContainerImage(appEcrRepo);

    const cdkCodeBuild = new codebuild.PipelineProject(this, 'CdkCodeBuildProject', {
      buildSpec: codebuild.BuildSpec.fromObject({
        version: '0.2',
        phases: {
          install: {
            commands: [
              'npm install',
            ],
          },
          build: {
            commands: [
              // synthesize the CDK code for the ECS application Stack
              'npx cdk synth --verbose',
            ],
          },
        },
        artifacts: {
          // store the entire Cloud Assembly as the output artifact
          'base-directory': 'cdk.out',
          'files': '**/*',
        },
      }),
    });

    /* ********** Pipeline part **************** */

    const appCodeSourceOutput = new codepipeline.Artifact();
    const cdkCodeSourceOutput = new codepipeline.Artifact();
    const cdkCodeBuildOutput = new codepipeline.Artifact();
    const appCodeBuildAction = new codepipeline_actions.CodeBuildAction({
      actionName: 'AppCodeDockerImageBuildAndPush',
      project: appCodeDockerBuild,
      input: appCodeSourceOutput,
    });
    new codepipeline.Pipeline(this, 'CodePipelineDeployingEcsApplication', {
      artifactBucket: new s3.Bucket(this, 'ArtifactBucket', {
        removalPolicy: cdk.RemovalPolicy.DESTROY,
      }),
      stages: [
        {
          stageName: 'Source',
          actions: [
            // this is the Action that takes the source of your application code
            new codepipeline_actions.CodeCommitSourceAction({
              actionName: 'AppCodeSource',
              repository: new codecommit.Repository(this, 'AppCodeSourceRepository', { repositoryName: 'AppCodeSourceRepository' }),
              output: appCodeSourceOutput,
            }),
            // this is the Action that takes the source of your CDK code
            // (which would probably include this Pipeline code as well)
            new codepipeline_actions.CodeCommitSourceAction({
              actionName: 'CdkCodeSource',
              repository: new codecommit.Repository(this, 'CdkCodeSourceRepository', { repositoryName: 'CdkCodeSourceRepository' }),
              output: cdkCodeSourceOutput,
            }),
          ],
        },
        {
          stageName: 'Build',
          actions: [
            appCodeBuildAction,
            new codepipeline_actions.CodeBuildAction({
              actionName: 'CdkCodeBuildAndSynth',
              project: cdkCodeBuild,
              input: cdkCodeSourceOutput,
              outputs: [cdkCodeBuildOutput],
            }),
          ],
        },
        {
          stageName: 'Deploy',
          actions: [
            new codepipeline_actions.CloudFormationCreateUpdateStackAction({
              actionName: 'CFN_Deploy',
              stackName: 'SampleEcsStackDeployedFromCodePipeline',
              // this name has to be the same name as used below in the CDK code for the application Stack
              templatePath: cdkCodeBuildOutput.atPath('EcsStackDeployedInPipeline.template.json'),
              adminPermissions: true,
              parameterOverrides: {
                // read the tag pushed to the ECR repository from the CodePipeline Variable saved by the application build step,
                // and pass it as the CloudFormation Parameter for the tag
                [this.tagParameterContainerImage.tagParameterName]: appCodeBuildAction.variable('imageTag'),
              },
            }),
          ],
        },
      ],
    });
  }
}

const app = new cdk.App();

// the CodePipeline Stack needs to be created first
const pipelineStack = new PipelineStack(app, 'aws-cdk-pipeline-ecs-separate-sources');
// we supply the image to the ECS application Stack from the CodePipeline Stack
new EcsAppStack(app, 'EcsStackDeployedInPipeline', {
  image: pipelineStack.tagParameterContainerImage,
});

Initializer

new TagParameterContainerImage(repository: IRepository)

Parameters

  • repository IRepository

Properties

NameTypeDescription
tagParameterNamestringReturns the name of the CloudFormation Parameter that represents the tag of the image in the ECR repository.
tagParameterValuestringReturns the value of the CloudFormation Parameter that represents the tag of the image in the ECR repository.

tagParameterName

Type: string

Returns the name of the CloudFormation Parameter that represents the tag of the image in the ECR repository.


tagParameterValue

Type: string

Returns the value of the CloudFormation Parameter that represents the tag of the image in the ECR repository.

Methods

NameDescription
bind(scope, containerDefinition)Called when the image is used by a ContainerDefinition.

bind(scope, containerDefinition)

public bind(scope: Construct, containerDefinition: ContainerDefinition): ContainerImageConfig

Parameters

  • scope Construct
  • containerDefinition ContainerDefinition

Returns

  • ContainerImageConfig

Called when the image is used by a ContainerDefinition.