12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[AWS CDK] コンテナイメージもまとめてデプロイ!?DockerImageAssetの動作確認をしてみた

Last updated at Posted at 2020-08-22

AWS CDKとは

AWSリソースをアプリケーションコード (TypeScript / Python / Java / C#) で定義できる,AWS公式のInfrastructre as a Code (IaC)ツールです.

構造化ファイル(YAML / JSON)を使ってリソース定義を行うCloudFormationと比較すると,

  • 制御構文や抽象化を使うことで,比較的少ないコード量でリソース定義しやすい
  • エディタによるエラーチェック・サジェスチョン・ドキュメント参照がしやすい

等のメリットがあります.
概要・特色を知りたい方は,Black Belt Online Seminarの資料がオススメです.
また,試してみたい方は,CDK Workshopから入るのがオススメです.

CDK Docker Image Assetsとは

CDKでは,各種AWSリソースとともに,Dockerfileからコンテナイメージをビルドして,cdk deployコマンドで一緒にデプロイすることができます.
これを用いると,例えば,ECS環境とアプリケーションのコンテナイメージを1つのリポジトリで管理でき,負担軽減される場面もあるかも?と思います.

ちょうど業務でそのような場面があり使ってみた,のですが...
API Referenceを読むと,それらしきクラスやメソッドが色々なところに存在し,ぱっと見どれを使えば良いか分からない!どのリポジトリにpushされるかもよく分からない!
そこで,簡単なテストスタックを作って,どのようにコンテナイメージがpushされるか確認してみました.

検証環境

  • CDK 1.59.0 (2020/08/17時点での最新バージョン1)
  • TypeScriptで実装

CDKは頻繁にアップデートが行われ,2,3日でバージョンが上がることもザラにあります.この記事に関わる部分も破壊的変更が行われる可能性もあり,こまめに最新情報をチェックするのをオススメします.

方法1 aws-ecr-assets moduleを使う

はじめに見つけた方法です.下記のコード抜粋のように,Dockerfileがあるディレクトリを指定して,DockerImageAssetを作ってあげるだけでOKです.

import * as cdk from '@aws-cdk/core';
import assets = require('@aws-cdk/aws-ecr-assets');

export class AssetsStack extends cdk.Stack {

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        
        new assets.DockerImageAsset(this, `docker-image`, {
          directory: path.join(__dirname, 'containers'), // Dockerfileがあるディレクトリを指定
        });
    }
}

しかし,この方法,ECRリポジトリやコンテナイメージのタグを定義してないけど,どこへpushされるのだろう???

スタックをデプロイすると,aws-cdk/assetsというECRリポジトリが自動的に作成され,その中にビルドしたイメージがpushされていました.イメージタグはCDKが自動的に採番するようです.

ecr-repos-wo-specify.jpg

お手軽で良いのだけど,特定のECRリポジトリにpushしたい場合や,イメージタグを指定したい場合はどうするのだろう…? DockerImageAssetのコンストラクタには,

  • repositoryName (push先のリポジトリを指定)
  • extraHash (イメージタグを指定)

という引数が存在するのですが,既に非推奨となっており,将来的に削除される可能性があります.
また,本検証では,これらの引数を指定すると,イメージがpushされませんでした.
ということで,push先のリポジトリ・イメージタグを指定するには,方法2を使う必要があります.

方法2 StackSynthesizerを使う

下記のコード抜粋のように,Stack.synthesizer.addDockerImageAssetを使って定義します.

import * as cdk from '@aws-cdk/core';
import assets = require('@aws-cdk/aws-ecr-assets');

export class AssetsStack extends cdk.Stack {

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        
        this.synthesizer.addDockerImageAsset({
            directoryName: path.join(__dirname, 'app1'), // Dockerfileがあるディレクトリを指定,
            repositoryName: "my-ecr-repos", // ECRリポジトリ名を指定
            sourceHash: "image-tag", // イメージタグを指定.
        });
}

所望のリポジトリにコンテナイメージがpushされています.

ecr-repos.jpg

方法2の注意点

  • Dockerfileを書き換えても,sourceHashを変更しなければ,同じタグのイメージが新たなイメージで上書きされるようです.前のバージョンも残しておきたい場合は,都度sourceHashを変更する必要があります.私は,gitのコミットハッシュからイメージタグを決定し,CDK context valueを通してsourceHashを与えるようにしました.

  • 同一スタック内で複数回addDockerImageAssetを行った場合,最後に行った指定のみが有効になりました.複数のリポジトリに色々なコンテナイメージをpushしたい場合に注意が必要です.

import * as cdk from '@aws-cdk/core';
import assets = require('@aws-cdk/aws-ecr-assets');

export class AssetsStack extends cdk.Stack {

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        
        // 1つ目のイメージ../app1/Dockerfileを使って,my-repos1へtestタグでpushしたい.
        this.synthesizer.addDockerImageAsset({
            directoryName: path.join(__dirname, 'app1'),
            repositoryName: "my-repos1",
            sourceHash: "test",
        });

        // 2つ目のイメージ../app2/Dockerfileを使って,my-repos2へtestタグでpushしたい.
        this.synthesizer.addDockerImageAsset({
            directoryName: path.join(__dirname, 'app2'),
            repositoryName: "my-repos2",
            sourceHash: "test",
        });

       // この場合,2つ目のイメージだけがpushされます.
       // 両方ともpushしたい場合,スタックを分ければOK.
       // 同一スタック内での複数イメージpushは未検証 (イメージ1, 2でsourceHashを変えればよいのか…?)
}

ソースコード

パイプライン(CodeBuild)でデプロイする場合の注意点

CodeBuildでは,都度ビルド用コンテナ環境が作成され,その中でbuildspec.ymlに記述されたコマンドが実行されます.コンテナイメージのビルドでは,docker-in-dockerを行うため,Privilegedの有効化が必要です.

まとめ

方法1 (aws-ecr-assets module)は,現状EXPERIMENTAL指定となっており,非推奨機能も多いようです.
今後は,方法2 (Stack.synthesizer)に移行していきそうな雰囲気がありました.

  1. 2020/08/22時点では,ver1.60.0がリリースされていました.

12
3
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
12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?