CodeBuild、ECR、および CodeDeploy を使用したコンテナ内での継続的デリバリーの自動化
継続的インテグレーション/継続的デリバリー(CI/CD)は、ソース管理の変更から、自動ビルド、サーバーへの自動デプロイまで、アプリケーションの更新を自動化するプロセスです。AWSはこれに対してCodePipelineというサービスを提供しており、コンテナと連携して動作するように設定できます。
コンテナにおける継続的デリバリー
コンテナは従来のアプリケーションよりも少し複雑です。多くのコンテナ化されたアプリケーションは、実際に2つのコンテナイメージを使用します。最初のものはベースイメージと呼ばれ、基本的には依存関係や他のアプリケーションが事前にロードされたカスタムAMIです。これはビルド時間を短縮するために行われます。なぜなら、アプリケーションコードを更新するだけであれば、NGINXや他のソフトウェアをコンテナ上で再インストールする必要がないからです。2つ目のイメージは実際のアプリケーションイメージで、ベースイメージを拡張し、自分自身のコードを含みます。
そのため、私たちが設定するCI/CDパイプラインは実際には二つのパイプラインになります。最初のパイプラインは、ベースイメージの変更を監視し、その変更が発生した際に再ビルドとECRへの更新をトリガーします。二つ目のパイプラインは、二つのソースステージを含みます。一つはベースイメージのECRリポジトリでの変更を監視し、もう一つはアプリケーションイメージのソースコードの更新をリスニングします。このようにして、アプリケーションイメージだけを更新する場合、ベースイメージを再ビルドする必要はありません。
2つのパイプラインを使用すると、CodePipelineは次の2つの方法のいずれかでアプリケーションの更新をトリガーします:
- アプリケーションイメージへの変更は、最新のベースイメージを使用してアプリケーションイメージの再構築を引き起こします。このベースイメージは再構築する必要はありません。更新はECRにプッシュされ、オプションでECSまたは別のコンテナサービスへのデプロイメントが行われます。
- ベースイメージの変更は、ベースイメージの再構築をトリガーし、これがECRへの更新を展開します。これにより、アプリケーションイメージの再構築がトリガーされ、ECRにプッシュされ、その後ECSにプッシュされます。
しかし、このデュアルパイプラインセットアップはすべてのアプリケーションに必要なわけではなく、もしあなたがUbuntuのようなプリビルドの基本OSイメージを使用しているだけなら、すべてを処理するためのパイプラインは1つだけで足ります。
IAMロールの設定
まず、CodeBuildがあなたの代理で他のAWSサービス(ECRなど)とやり取りするために必要な権限を与えるサービスロールを設定する必要があります。IAM管理コンソールを開き、「ロール」の下に新しいロールを作成します。「AWSサービス」を選択し、リストからCodeBuildを選択します。
ポリシーについては、以下の権限を持つ新しいポリシーを作成することをお勧めします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CloudWatchLogsPolicy",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
},
{
"Sid": "CodeCommitPolicy",
"Effect": "Allow",
"Action": [
"codecommit:GitPull"
],
"Resource": [
"*"
]
},
{
"Sid": "S3GetObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"*"
]
},
{
"Sid": "S3PutObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"*"
]
},
{
"Sid": "ECRPullPolicy",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": [
"*"
]
},
{
"Sid": "ECRAuthPolicy",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": [
"*"
]
},
{
"Sid": "S3BucketIdentity",
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource":
"*"
}
]
}
これをポリシーエディターのJSONタブに貼り付けます。名前を付けて、役割に添付します。また、事前に作成されたポリシーである AmazonEC2ContainerRegistryPowerUser も添付する必要があります。
これら2つのポリシーが追加されたら、役割に名前を付けて「作成」をクリックします。
ソースコントロールとCodeBuildの設定
CodePipelineは、GitHub、BitBucket、およびAWS自身のCodeCommitソース管理からのコード更新をサポートしています。CodeCommitをセカンダリーリリースリポジトリとして使用すると、最良の体験が得られますが、GitHubでも問題ありません。GitLabや他のプロバイダーを使用している場合は、更新をプッシュするためにCodeCommitを使用する必要があります。
このステップでは、2つの異なるリポジトリを用意する必要があります。1つはベースイメージ用、もう1つはアプリケーションイメージ用です。カスタムベースイメージを使用していない場合は、その設定をスキップできます。
ベースイメージ用に、buildspecファイルを作成する必要があります。これは基本的に、CodeBuildがイメージをビルドする際に実行するコマンドのリストです。CodeBuildの設定時に手動で入力することもできますが、リポジトリのルートにbuildspec.ymlという名前のファイルとして保存する方が良いです。
あなたの正確な設定は、アプリケーションの要件によって異なる場合がありますが、次のような形になるはずです。
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws --version
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- REPOSITORY_URI=012345678910.dkr.ecr.us-east-1.amazonaws.com/base-image
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
この例では、ECRにログインし、イメージタグをCodeBuildのビルドIDに設定し、Dockerイメージをビルドし、変更をECRリポジトリにプッシュします。REPOSITORY_URI変数の宣言をターゲットECRリポジトリのURIに変更する必要があります。
buildspec.ymlとして保存し、ベースイメージリポジトリとアプリケーションイメージリポジトリのルートに配置します。CodeBuildコンソールから手動でビルドを開始することでbuildspecをテストすることができます。もしくは、パイプラインのセットアップに進み、発生する可能性のあるエラーを修正してください。
パイプラインの設定
ビルド仕様が整ったら、CodePipeline コンソールを開き、ベースイメージ用の新しいパイプラインを作成します。名前を付け、新しいサービスロールの作成を許可します。ソース管理のステージでは、使用しているタイプを選択し、リポジトリとブランチを選びます。必要であれば、リリースを追跡するための追加のブランチを設定することもでき、CodePipeline は master への変更を無視します。
ビルドステージでは、「プロジェクトを作成」を選択します。これにより、CodeBuildを設定できるダイアログが表示されます。
通常、CodeBuildをソースコントロールにリンクする必要がありますが、この方法で新しいプロジェクトを作成するとき、パイプラインが自動的にそれを処理します。ビルドが実行される環境を構成する必要があり、カスタムDockerイメージを選択してビルドに必要なすべてのプログラムを追加することも、buildspec.ymlのプリビルドフェーズで手動でインストールすることもできます。特別なものが必要ない場合は、Amazon Linux 2とデフォルトのランタイムを選択できます。これにはほとんどのプログラミング言語のランタイムやDockerがプリインストールされています。
以前に作成したサービスロールも選択する必要があります:
最後に、ビルドスペックファイルの名前を手動で変更することもできます。ソースのルートディレクトリに置きたくない場合や、区別が必要な複数のファイルがある場合に便利です。また、ここにビルドコマンドを手動で挿入することもできますが、Git上のファイルとして管理することをお勧めします。
デプロイ段階では、ベースイメージのためにそれをスキップしたいと思うでしょう。buildspecファイルは変更をビルドしてECRにプッシュします。これがこのステップに必要なすべてです。ベースイメージリポジトリに変更をプッシュすることでパイプラインをテストできます。
アプリケーションイメージパイプラインの設定
次に、アプリケーションのイメージ用に追加のパイプラインを設定します。コンソールから新しいパイプラインを作成し、ソースとして「ECR」を選択します。基になるイメージリポジトリを選択し、イメージタグは空のままにします。これにより、デフォルトでlatestになります。
ビルドステージでは、基本イメージステージとほぼ同じようにCodeBuildを設定する必要があります---新しいビルドプロジェクトを作成し、デフォルトの環境を選択し、以前に作成したサービスロールを入力します。
デプロイメントステージはオプションです。それがない場合、ベースイメージやアプリケーションイメージの変更は、単にアプリケーションイメージを再構築し、変更をECRにプッシュするトリガーとなります。しかし、デプロイメントにECSを使用している場合、ビルドしたイメージをサーバーに更新する別のステージを追加できます。
いずれにせよ、パイプラインを作成するには「作成」をクリックしてください。ただし、動作する前にいくつかの変更が必要ですので、パイプラインの「編集」をクリックし、その後「ステージを編集」をクリックしてソース管理ステージを編集してください:
現状では、ソースコントロール段階は基本イメージのためにECRから単にプルしています。これは必要ですが、アプリケーションコードも必要であり、有用なことを行うためにはアプリケーションコードの変更にも応じる必要があります(基本イメージだけではなく)。
「アクションを追加」をクリックします。
アクションタイプとしてCodeCommit(または他のソース管理)を選択し、リポジトリとブランチを選んでください。「出力アーティファクト」には、これはアプリケーションのソースコードであることを示すためにSourceArtifactを入力します。
ECRステージを編集して、出力アーティファクトがベースイメージであることを指定する必要があります。
これでCodeBuildが実行するために必要なすべてが揃っているはずです。そして、パイプラインを更新すると、再度実行されるはずですが、エラーなく実行されることを願っています。
エラーに遭遇した場合、CodeBuildのビルドスペックが正しく機能していない可能性があります。CodeBuildコンソールからビルドログを見るか、AWSのビルド仕様リファレンスを参照して、全体の仕組みについての詳細を確認できます。












