0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CDKで一発作成!S3→Codebuild→ECRでDockerイメージをpushするCodePipeline

Last updated at Posted at 2025-01-02

記事概要

本記事では、CDKで以下の構成をデプロイします。

image (3).png

以下の記事で、S3にアップロードしたソースコードからDockerイメージを作成しECRにプッシュする、というプロセスを自動化するCodePipelineを作成しました。

S3バケットやECRリポジトリ、CodeBuildやCodePipelineなど、マネジメントコンソールで作成してきたAWSリソースを一発で作成できるCDKコードを作成したので、デプロイ方法を紹介します。

CDKの練習を兼ねて作成したコードのため、とりあえずデプロイできるというクオリティです。可読性、保守性などを踏まえて後々ブラッシュアップしたいと思います…

CDKでデプロイされるリソース

CDKをデプロイすると、以下が作成されます。

  • ECRプライベートリポジトリ
    • 作成されたDockerイメージのpush先となるリポジトリ
  • S3バケット
    • DockerイメージのもとになるDockerfileやその他のソースコードのアップロード先
    • ソースコード類はまとめてzipファイルにし、作成したS3バケットに直接配置する構成になっています
  • CodeBuildプロジェクト
    • buildspecをコマンドで挿入しているため、今回buildspec.ymlファイルの準備は不要です
  • CodePipelineのパイプライン
    • ソースステージで作成したS3バケットをプロバイダーとして指定
    • ビルドステージで作成したCodeBuildプロジェクトをプロバイダーとして指定

S3にアップロードするzipファイルは自分で用意してS3バケットにアップロードします。アップロードのトリガーにパイプラインが実行されます。
※ buildspec.ymlはzipファイルに含める必要はありません

CDKのデプロイ方法

動作環境

今回はCloudShellで実行したため、そのままCDKコマンドが実行できます。それ以外の環境で実行する場合、AWS CDK の前提条件を確認のうえ、必要なセットアップを行ってください。

CDKプロジェクトの作成

以下のようにディレクトリを1つ作成し、そのディレクトリ内で cdk init コマンドによりプロジェクトの初期化を行います。ディレクトリ名に合わせてCDKコードが生成されるため、 本記事のCDKを実行する場合はディレクトリ名を cdk にすることをおすすめします。

mkdir cdk
cd cdk
cdk init app --language typescript

実行すると、bin ディレクトリや lib ディレクトリ、cdk.jsonファイルなどが作成されます。

CDKコードの挿入

今回はすでに作成されている /lib/cdk-stack.ts下記のCDKコードに書き換えます。必要に応じて一部カスタマイズしてください。
CloudShellだと編集しづらいため、ローカル環境でファイルを用意してから、CloudShellへアップロードすることをおすすめします。

CDKコードのカスタマイズ

  • アップロードするzipファイルを変更したい場合は、以下の 'artifact.zip' を変更してください。

※ 作成したS3バケット直下にzipファイルを配置する構成になっています

const Resourcepath = 'artifact.zip'
  • リソースを作成するリージョンを変更したい場合は、以下の "ap-northeast-1" を変更してください。
"AWS_DEFAULT_REGION": "ap-northeast-1",

変数部分は cdk.json など別ファイルに外だしするのが一般的だと思いますが、追々アップデートしていきたいと思います。

CDKブートストラップ・デプロイ

CDKでAWSリソースをデプロイするためのブートストラップとして、S3やIAMロールなどを作成するプロセスとしてブートストラップを行います。作成したディレクトリ(今回だとcdkディレクトリ)で以下のコマンドを実行します。

cdk bootstrap

ブートストラップはCDKプロジェクト作成時に一度だけ実行します

最後に、以下のコマンドでデプロイを行います。以後、CDKコードを変更しその内容をデプロイしたい場合は、以下のコマンドだけ実行すればOKです。

cdk deploy

デプロイ前に、必要なIAMリソースを作成してよいか聞かれるため y を入力してください。
image (1).png

CDKコード

/lib/cdk-stack.ts の内容を以下に書き換えます。

import * as cdk from 'aws-cdk-lib';
import * as ecr from "aws-cdk-lib/aws-ecr";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as cb from "aws-cdk-lib/aws-codebuild";
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions';
import * as events from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import { Construct } from 'constructs';

export class CdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ECRプライベートリポジトリ
    const EcrRepository = new ecr.Repository(this, 'Repository', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      imageTagMutability: ecr.TagMutability.MUTABLE,
      emptyOnDelete: true
    });

    // S3バケット
    const ResourceBucket = new s3.Bucket(this, 'CreateBucket' ,{
      versioned: true,
    });
    const Resourcepath = 'artifact.zip'
    
    //buildspecオブジェクト
     const buildSpecObject = {
    "version": "0.2",
    "env": {
      "variables": {
        "AWS_DEFAULT_REGION": "ap-northeast-1",
        "DOCKER_USER": "AWS",
        "REPOSITORY_URI": EcrRepository.repositoryUri,
        "IMAGE_NAME": EcrRepository.repositoryName,
        "ACCOUNT_ID": cdk.Stack.of(this).account
      }
    },
    "phases": {
      "pre_build": {
        "commands": [
          "echo Logging in to Amazon ECR...",
          "aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username $DOCKER_USER --password-stdin $REPOSITORY_URI"
        ]
      },
      "build": {
        "commands": [
          "echo Building the Docker image...",
          "docker build -t \"$REPOSITORY_URI:latest\" ."
        ]
      },
      "post_build": {
        "commands": [
          "echo Pushing the Docker image...",
          "docker push \"$REPOSITORY_URI:latest\""
        ]
      }
    }
  }

        
    //CodeBuildプロジェクト
    const CodebuildProject = new cb.Project(this, 'Ci-Project', {
    source: cb.Source.s3({
      bucket: ResourceBucket,
      path: Resourcepath
      }),
      buildSpec: cb.BuildSpec.fromObject(buildSpecObject),
    });
    
    // パイプラインの作成
    const pipeline = new codepipeline.Pipeline(this, 'S3TriggeredPipeline', {
    });
    
     // ソースステージの追加
    const sourceOutput = new codepipeline.Artifact();
    const sourceAction = new codepipeline_actions.S3SourceAction({
      actionName: 'S3Source',
      bucket: ResourceBucket,
      bucketKey: Resourcepath,
      output: sourceOutput,
    });
    pipeline.addStage({
      stageName: 'Source',
      actions: [sourceAction],
    });
    
    // ビルドステージの追加
    const buildAction = new codepipeline_actions.CodeBuildAction({
      actionName: 'CodeBuild',
      project: CodebuildProject,
      input: sourceOutput,
      outputs: [new codepipeline.Artifact()],
    });
    pipeline.addStage({
      stageName: 'Build',
      actions: [buildAction],
    });
    
  // EventBridgeルールの作成
    const rule = new events.Rule(this, 'S3ObjectCreatedRule', {
      eventPattern: {
        source: ['aws.s3'],
        detailType: ['Object Created'],
        detail: {
          bucket: {
            name: [ResourceBucket.bucketName]
          },
          object: {
            key: [Resourcepath]
          }
        }
      }
    });

    // EventBridgeルールのターゲットとしてパイプラインを追加
    rule.addTarget(new targets.CodePipeline(pipeline));
  }
};

本記事はここまでとなります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?