Zenn
👷🏼‍♂️

【YOLO】③DockerイメージのビルドからECSデプロイまでをパイプライン化する

2025/03/31に公開

はじめに

前回までの記事でYOLO12を使用したテストアプリを作成~ECS上でのDockerコンテナ起動まで行いました。

今回は「AWS CodePipeline」を使用してAWS上にCI/CD環境を構築し、今まで手動で行っていたDockerイメージのビルド~ECSへのデプロイを自動化します。

本稿は前回記事の続きですので、テストアプリの作成およびECR、ECSを構築済みの前提で手順記載しております。
不明点あれば前回記事もご参照いただければ幸いです。

https://zenn.dev/gj77a/articles/e5cd1056fcbdc4

https://zenn.dev/gj77a/articles/b4e566c612c765

本稿では以下の流れでCI/CD環境の構築を実施します。

  1. CodeBuildのソースプロバイダにGitHubを指定できるように設定
  2. CodeBuild実行時に必要なbuildspec.ymlファイルの作成
  3. DockerイメージをビルドするためにCodeBuildを作成
  4. CodePipelineを作成し、各ステージに対応するAWSサービスを指定(ソースはGitHubを指定)
  5. ローカルに作成済みの各種ファイルをGitHubにプッシュ
  6. プッシュをトリガーにDockerイメージのビルド~ECSへのデプロイが自動で実行されることを確認

GitHubとCodeBuildの連携

今回はGitHubをビルドソースの配置先として使用します。
元々は AWS CodeCommit を利用していたのですが、 AWS CodeCommit2024/7/27時点で新規アカウントでの使用を制限されており、
今後完全撤廃される可能性が高いサービスのため、代替サービスとしてGitHubを採用しました。

GitHubなどの外部サービスをCodeBuildのビルドソースとして使用する場合、当然ながら連携設定を行う必要があります。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/connections-github-app.html

簡単に設定できるので先に完了させておきましょう。
マネジメントコンソールの AWS デベロッパー用ツール 画面にて設定できます。
※GitHubアカウントおよびリポジトリ作成済みの前提です

今回、接続名は「yolo12-test-app」としました。

必要なIAMポリシーおよびロールの作成もここで行います。
GitHub連携に必要なポリシーだけでなく、ビルド時に必要な他AWSサービス連携用のポリシーもついでに記述します。
ここで作成するIAMロールは後述のCodeBuild作成時に使用します。

  1. IAMポリシーの作成(ポリシー名:CodeBuildBasePolicy-yolo12-test)
CodeBuildBasePolicy-yolo12-test
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"logs:CreateLogGroup",
				"logs:CreateLogStream",
				"logs:PutLogEvents"
			]
		},
		{
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"s3:PutObject",
				"s3:GetObject",
				"s3:GetObjectVersion",
				"s3:GetBucketAcl",
				"s3:GetBucketLocation",
				"s3:ListBucket"
			]
		},
		{
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ecr:GetAuthorizationToken",
				"ecr:BatchCheckLayerAvailability",
				"ecr:BatchGetImage",
				"ecr:CompleteLayerUpload",
				"ecr:GetDownloadUrlForLayer",
				"ecr:InitiateLayerUpload",
				"ecr:PutImage",
				"ecr:UploadLayerPart"
			]
		},
		{
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"codebuild:CreateReportGroup",
				"codebuild:CreateReport",
				"codebuild:UpdateReport",
				"codebuild:BatchPutTestCases",
				"codebuild:BatchPutCodeCoverages"
			]
		},
        {
            "Effect": "Allow",
            "Resource": [
                 "作成した接続のARN"
            ],
            "Action": [
                "codeconnections:GetConnectionToken",
                "codeconnections:GetConnection"
            ]
        }
    ]
}
  1. IAMロールの作成(ロール名:codebuild-project-service-role-yolo12-test)

上記で作成したIAMポリシーをアタッチしてください。
信頼ポリシーは以下の通り設定します。

信頼ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codebuild.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

以上でGitHubの連携設定および必要なIAMロールの作成は完了です。

buildspec.ymlの作成

まず初めに buildspec.yml の作成から行います。
このファイルは CodeBuild でのビルド実行時に、「どの環境で実行するか」「どんなコマンドでビルドするか」を指定するファイルです。
具体的には、AWSアカウントIDやDockerコマンドを記述します。

buildspec.yml
version: 0.2  # Buildspecファイルのバージョン

env:
  variables:
    AWS_DEFAULT_REGION: ap-northeast-1  # AWSのデフォルトリージョン
    AWS_ACCOUNT_ID: アカウントID  # AWSアカウントID
    IMAGE_REPO_NAME: yolo12-test-ecr  # Dockerイメージのリポジトリ名
    IMAGE_TAG: latest  # Dockerイメージのタグ

phases:
  build:
    commands:
      # ECRにログイン
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
      
      # Dockerイメージをビルド
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      
      # Dockerイメージにタグを付ける
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      
      # DockerイメージをECRにプッシュ
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      
      # imagedefinitions.jsonファイルを生成
      # 「"name":」にはECSのタスク定義で設定したコンテナ名を入れる
      - printf '[{"name":"yolo12-test-container","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json

artifacts:
  files: imagedefinitions.json  # ビルド成果物としてimagedefinitions.jsonを指定

基本的にはローカルで実行していたDockerコマンドをそのまま転記した形式になります。
しかし1点重要な項目として imagedefinitions.json の作成 というものがありますので、そちらについて補足説明いたします。

imagedefinitions.json とはCodePipelineを使用してECSにデプロイを実行する際に参照される定義ファイルのことです。
デプロイ先ECSのコンテナ名と、デプロイ対象とするDockerイメージのイメージURIを指定します。
処理としてはprintf で上記内容をjsonファイルとして作成し、artifacts: で後工程で参照可能となるようにビルド成果物に含めてアーティファクトストア(S3)上に保管しています。

必須項目となるため、うっかり記述を忘れないようにしましょう。(自分への戒め)

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/file-reference.html

buildspec.ymlの作成が完了しましたら、アプリのルートディレクトリ直下に保存してください。(GitHub上にプッシュ)

CodeBuildの作成

続いてCodePipelineのビルドステージで使用する CodeBuild のビルドプロジェクトを作成します。
ビルド環境にはLambdaを使用したかったのですが、LambdaはDcokerイメージのビルドをサポートしていないためEC2を選択しています。

またCodeBuildを指定のVPC内に作成することも可能ですが、そのためにはプライベートサブネットやNATゲートウェイが必要だったりと制約があるため注意が必要です。
今回は特にVPC内のリソースにアクセスする要件が無いため、非VPCで作成します。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/lambda.html

設定値(他はデフォルト)

項目名 設定値
プロジェクト名 yolo12-test-buildproject
ソースプロバイダ GitHub
リポジトリ GitHubアカウントのリポジトリ
GitHubリポジトリ https://github.com/<user-name>/<repository-name>
プロビジョニングモデル オンデマンド
環境イメージ マネージド型イメージ
コンピューティング EC2
Running mode Container
OS Amazon Linux
イメージ aws/codebuild/amazonlinux-x86_64-standard:5.0
サービスロール 既存のサービスロール
ロール名 codebuild-project-service-role-yolo12-test
特権付与 有効
ビルド仕様 buildspecファイルを使用する
CloudWatch Logs ビルド時の詳細ログを確認したい場合は有効のままにする
S3ログ ビルド時の詳細ログを確認したい場合は有効にする

CodePipelineの作成

最後に本稿の要である CodePipeline の作成に着手します。
項目数が多いため、パイプライン作成画面上の「Step」ごとに分割して記載します。

Step1:作成オプションを選択する

設定値(他はデフォルト)

項目名 設定値
作成オプションを選択する カスタムパイプラインを構築する

Stp2:パイプラインの設定を選択する

設定値(他はデフォルト)

項目名 設定値
パイプライン名 yolo12-test-pipeline
サービスロール 新しいサービスロール
ロール名 yolo12-test-pipeline-role

Step3:ソースステージを追加する

設定値(他はデフォルト)

項目名 設定値
ソースプロバイダー GitHub(GitHubアプリ経由)
接続 既存の接続を選択
リポジトリ名 既存のリポジトリを選択
デフォルトブランチ 既存のブランチを選択
ステージ障害時の自動再試行を有効にする 無効化する

Step4:ビルドステージを追加する

設定値(他はデフォルト)

項目名 設定値
プロバイダーを構築する その他のビルドプロバイダー(AWS CodeBuild)
プロジェクト名 yolo12-test-buildproject
ステージ障害時の自動再試行を有効にする 無効化する

Step5:テストステージを追加

テストステージの追加に伴い、全体の実行時間増加やそれに伴う追加コストが発生するため、今回テストステージはスキップします。

Step6:デプロイステージを追加する

設定値(他はデフォルト)

項目名 設定値
デプロイプロバイダー Amazon ECS
クラスター名 yolo12-test-cluster
サービス名 yolo12-test-service

イメージ定義ファイル にはデフォルトで imagedefinitions.json が設定されるため、空白のままで問題ありません。

Step7:レビュー

確認画面です。
これまでのStepで設定した内容を再確認し、問題がなければ「パイプラインを作成する」を押下してください。

実行確認

前項のStep7でパイプラインを作成する」を押下後、自動でパイプラインが起動します。
まずは初回実行が正常に終了するか確認しましょう。
すべてのステージで緑色のチェック表示となっていれば成功です。

(※画面コピー取得し忘れました・・・)

初回実行が正常終了したことを確認できましたら、次にGitHubへのプッシュをトリガーにしてパイプラインが起動するかを確認しましょう。

ローカルで適当なファイルを変更し、GitHubのmasterブランチにプッシュしてください。
(※例:「upload.html」に<h1>Pipeline test</h1> を追加)

GitHubへのプッシュを起点にして、自動でパイプラインが実行されることを確認できればOKです!

アプリの動作に問題ないことも確認しておきましょう。

おわりに

今回はGitHub + AWSサービスを利用してCI/CDパイプラインを構築する方法についてご紹介しました。
CI/CD環境の構築をマネジメントコンソール上で行うことで、視覚的に全体の構造や処理の流れを理解しやすかったのではないかと思います。
設定項目や留意事項は多いですが、その分ちゃんと正常終了した際には謎の達成感を得られますね・・・。

次回は今回作成したパイプラインを AWS CDK を使用してコードベースで再構築してみようと思います。

ここまでお付き合いいただきありがとうございました。
次回もお読みいただけると幸いです。

Discussion

ログインするとコメントできます