AWS CDK で「Dockerfile をビルドして Amazon ECR リポジトリにイメージを保存する」選択肢として DockerImageAsset と cdklabs/cdk-ecr-deployment を紹介する❗️
aws_ecr_assets.DockerImageAsset
を使う
まず,1番簡単なのは aws_ecr_assets.DockerImageAsset
を使うという選択肢だと思う.
👾 sandbox-cdk-ecr-deployment-stack.ts (Step.1)
Dockerfile
を準備して(今回は ../images/app
ディレクトリに置いた)以下のような AWS CDK コードを実装すれば OK👌
import { Stack, StackProps, aws_ecr_assets, } from 'aws-cdk-lib' import { Construct } from 'constructs' import path = require('path') export class SandboxCdkEcrDeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props) new aws_ecr_assets.DockerImageAsset(this, 'SandboxAppImage', { directory: path.join(__dirname, '../images/app'), }) } }
デプロイすると自動的に cdk-hnb659fds-container-assets-${ACCOUNTID}-ap-northeast-1
という Amazon ECR リポジトリにイメージが保存される.hnb659fds
は AWS CDK 側で付けられた名前でドキュメントに この値には意味がありません
と書かれてておもしろい😃実装も少なく1番お手軽だと思う (๑•̀ㅂ•́)و✧
デメリットとしては任意の Amazon ECR リポジトリにイメージを保存できないというところだと思う.言い換えるとリポジトリ名・ライフサイクルポリシー・リポジトリタグなどは自由に設定できず,AWS CDK 側に管理されてしまうため微妙な使いづらさがある.ちなみにこれはドキュメントにも明記されていて「そういう意図である」と読み取れる📝
DockerImageAsset is designed for seamless build & consumption of image assets by CDK code deployed to multiple environments through the CDK CLI or through CI/CD workflows. To that end, the ECR repository behind this construct is controlled by the AWS CDK. The mechanics of where these images are published and how are intentionally kept as an implementation detail, and the construct does not support customizations such as specifying the ECR repository name or tags.
cdklabs/cdk-ecr-deployment
と組み合わせて使う
そこで aws_ecr_assets.DockerImageAsset
と cdklabs/cdk-ecr-deployment
を組み合わせて使うという選択肢もある💡cdklabs/cdk-ecr-deployment
を使うと,指定した Docker Hub・Amazon ECR リポジトリなどのイメージを任意の Amazon ECR リポジトリにコピーできる.
👾 sandbox-cdk-ecr-deployment-stack.ts (Step.2)
例えば,以下のような AWS CDK コードを実装してデプロイすると,Docker Hub の amazonlinux:2023
イメージを自分で実装した Amazon ECR リポジトリ(今回は sandbox-repository
)にコピーできる.
import { Stack, StackProps, aws_ecr, } from 'aws-cdk-lib' import * as ecrdeploy from 'cdk-ecr-deployment' import { Construct } from 'constructs' export class SandboxCdkEcrDeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props) const repository = new aws_ecr.Repository(this, 'SandboxRepository', { repositoryName: 'sandbox-repository', }) new ecrdeploy.ECRDeployment(this, 'SandboxImageDeployment', { src: new ecrdeploy.DockerImageName('amazonlinux:2023'), dest: new ecrdeploy.DockerImageName(repository.repositoryUriForTag('2023')), }) } }
👾 sandbox-cdk-ecr-deployment-stack.ts (Step.3)
よって aws_ecr_assets.DockerImageAsset
で Amazon ECR リポジトリ cdk-hnb659fds-container-assets-${ACCOUNTID}-ap-northeast-1
に保存されたイメージを自分で実装した Amazon ECR リポジトリにコピーすることで,Dockerfile をビルドして Amazon ECR リポジトリにイメージを保存する流れを AWS CDK で柔軟に実現できる👏
import { Stack, StackProps, aws_ecr, aws_ecr_assets, } from 'aws-cdk-lib' import * as ecrdeploy from 'cdk-ecr-deployment' import { Construct } from 'constructs' import path = require('path') export class SandboxCdkEcrDeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props) const image = new aws_ecr_assets.DockerImageAsset(this, 'SandboxAppImage', { directory: path.join(__dirname, '../images/app'), }) const repository = new aws_ecr.Repository(this, 'SandboxRepository', { repositoryName: 'sandbox-repository', }) new ecrdeploy.ECRDeployment(this, 'SandboxImageDeployment', { src: new ecrdeploy.DockerImageName(image.imageUri), dest: new ecrdeploy.DockerImageName(repository.repositoryUriForTag('my-tag')), }) } }
cdk-ecr-deployment で事前にビルドされたイメージを使う
cdklabs/cdk-ecr-deployment
は内部的にイメージをコピーするための AWS Lambda 関数もデプロイされている.AWS CDK をデプロイするときに環境変数として FORCE_PREBUILT_LAMBDA=1
を設定しておくと,AWS Lambda 関数を作るときに事前にビルドされたイメージを使うようになる.ビルド時間を短縮できるので使っても良いと思う👌実装を見たところ GitHub リポジトリのリリースアセットからダウンロードしているようだった.