はじめに
本記事で紹介している内容は、2024年11月に発表されたCodePipelineの機能で簡単に実装できるようになっています。
AWS CodePipeline が ECR イメージの公開と AWS InspectorScan を新しいアクションとしてサポート開始
CodeBuildの勉強を兼ねてわざわざ以下の手順を踏んでいますが、とにかくDockerイメージのビルド・Amazon ECRへのプッシュが自動化できればOKという方は、以下のような素晴らしい記事がありますので、ぜひそちらをご参照ください。
AWS CodePipelineのコンテナビルドが簡単に!?
記事の概要
こちらの記事で、ぽちぽちコマンドを実行してローカル環境でDockerイメージのビルド&Amazon ECRへのプッシュを行いました。 数回ならいいですが、ソースコードやDockerfileの中身が変わるたびにコマンドを実行しているとめんどくさいのでCodeBuildで自動化してみます。
CodeBuildの利用で以下のようにフローが変わるイメージです。★がAfterで自動化される部分になります。
-
Before
- Dockerコマンド/AWS CLIが実行可能な開発環境を用意(初回のみ)
- ソースコードとDockerfileを作成・変更
- Dockerコマンド実行でDockerイメージを作成 ★
- AWS CLIでDockerイメージをECRへプッシュする ★
-
After
- CodeBuildビルドプロジェクトの作成(初回のみ)
- ソースコードとDockerfileを作成・変更し、S3にアップロードする
- CodeBuildでビルドを実行
ソースコードの準備
今回はPythonコードをコンテナで実行して簡単なWebアプリケーションを公開するので、app.pyというソースコードとDockerfileを用意します。
今回はWebサイトに、Hello world ver2
と表示させます。ソースコードとDockerfileの内容は記事の最後に記載しました。
S3へのアップロード
CodeBuildで自動化するにあたり、これらのソースコードをS3にアップロードする必要があります。今回は2つファイルをアップロードする必要がありますが、同じパスにアップロードするようにしてください。今回は以下の構成にしました。
<S3バケット>
∟ build-resource //任意の名前でOK
∟ app.py
∟ Dockerfile
S3バケットを作成していない場合は、S3の画面から「バケットを作成」ボタンをクリックしてバケットを作成できます。
※バケット名は他者の所有するバケットも含めて一意の名前にする必要があります
CodeBuildの設定
CodeBuildを使い始めるには
- ビルドプロジェクト
- buildspec
の2つを定義します。
- ビルドプロジェクト
- ソースコードの取得先、ビルド環境、実行するビルドコマンド、ビルドの出力先といったビルドの実行方法を指定
- buildspec
- YAML形式でCodeBuildがビルドを行う際のコマンドや関連する設定を記載する
今回、ビルドプロジェクトはマネジメントコンソールで設定し、buildspecはymlファイルを用意します。
buildspec.ymlの作成
先にbuildspec.ymlファイルを作成しておきます。buildspec.ymlのフォーマットやサンプルは公式ドキュメントでご確認ください。
version: 0.2
env:
variables:
IMAGE_REPO_NAME: "<ECRプライベートリポジトリの名前>"
IMAGE_TAG: "latest"
AWS_ACCOUNT_ID: "<アカウントID>"
AWS_DEFAULT_REGION: "<リージョン>"
phases:
pre_build:
commands:
- 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
build:
commands:
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
buildspec.ymlにcommands
で記載しているコマンドは全て、以下の記事で実行したコマンドそのものです。(変数を使っているので分かりにくいですが、手動で実行したコマンドをそのまま貼り付けてもOKです)
AWS CloudShellでDockerイメージを作成してAmazonECRプライべートリポジトリにpushしてみる
自分が実行したコマンドをbuildspec.ymlで定義しているだけです、わかりやすいですね。
buildspec.ymlを作成したら、ソースコードと同じS3のディレクトリにアップロードします。S3バケット内の構成は最終的に以下になります。
<S3バケット>
∟ build-resource //任意の名前でOK
∟ app.py
∟ Dockerfile
∟ buildspec.yml
ビルドプロジェクトの作成
もう一つ必要な準備として、マネジメントコンソールでビルドプロジェクトの設定をしていきます。
-
CodeBuildの画面で「プロジェクトの作成」をクリックします
-
プロジェクト名は任意の名前を入力し、ソースプロバイダは「Amazon S3」を選択し、バケットにソースコードをアップロードしたS3バケットを選択。「S3オブジェクトキーまたはS3フォルダ」はS3バケットの構成に合わせて入力(今回の構成の場合は
build-resource
を入力)
-
環境はデフォルトの設定です。コンテナの動作環境に合わせてオペレーティングシステムは「Amazon Linux」としました。イメージ、イメージのバージョンは最新のものを選んでおけばOKだと思います。
- 今回はbuildspec.ymlを別途用意したので、ビルド仕様では「buildspec.yml ファイルを使用する」を選択します。ファイル名は指定することもできますが、デフォルトで「buildspec.yml」が指定されるのでそのままにしておきます。
ここまで入力したら、「ビルドプロジェクトを作成する」ボタンをクリックします。
IAMロールの編集
ビルドプロジェクト作成後、一つだけ変更を行います。デフォルトで作成されるIAMロールはCodeBuil自体の実行やS3へのアクセスは可能ですが、ECRへのアクセス許可が不足しているので追加します。
- 作成したビルドプロジェクトの「プロジェクト詳細」タブを開いてスクロールしていくと「環境」セクション内に「サービスロール」が表示されているので、リンクをクリックします。
- 「許可を追加」>「ポリシーを追加」をクリックします。今回は検証のみなので、追加するポリシーとしてAWSマネージドポリシーの
AmazonEC2ContainerRegistryFullAccess
を選択します
実際は最低限のアクセス許可のみの追加が推奨されます
ここまででCodeBuildの設定は完了です。
ビルドの確認
実際に自動ビルドを試してみます。
ビルドの実行
作成したビルドプロジェクトの画面に「ビルドを開始」ボタンがあるので、これをクリックします。
ステータスが「進行中」から「成功」に変わったらビルド完了となります。
buildspecの記述通りにビルドし、指定したECRリポジトリへイメージがpushされているはずなので、ECRリポジトリのイメージ一覧を確認してみます。
新しいイメージが追加されていることが確認できると思います。
AppRunnerでデプロイして確認する
せっかくなので、pushしたDokcerイメージをAppRunnerにデプロイして確認してみたいと思います。AppRunnerについては以下の記事で設定済みですので、詳細な手順はこちらをご参照ください。
AWS AppRunnerを使ってAWS ECRに配置したDockerイメージをAWSにデプロイする
AppRunnerでサービスをデプロイ済であれば、再度AppRunnerのサービスの管理画面で「デプロイ」ボタンをクリックすることで、新しいDockerイメージを使ってサービスがデプロイされます。
ステータスが「Running」になったらデプロイ完了ですので、「デフォルトドメイン」のリンクをクリックして、インターネットに公開されているサービスを確認してみます。
Hello world ver2
と表示されており、今回アップデートしたソースコードの内容が反映されていることが確認できました。
ソースの内容
参考としてS3にアップロードするソースコード(Python)とDockerfileを記載しておきます。
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
str_out = '<h2>Hello world ver2</h2>'
return str_out
app.run(host='0.0.0.0',port=80)
Dockerfile
#ベースイメージとして pythonn v3.12 を指定
FROM python:3.12
# 以降の RUN, CMD コマンドを実行する作業ディレクトリを指定
WORKDIR /app
# カレントディレクトリにあるファイルをコンテナ上の 「/app」 ディレクトリにコピーする
ADD . /app
# Flaskをインストール
RUN pip install flask
# 待受けポートの指定
EXPOSE 80
# コンテナが起動時に実行するコマンドを指定
CMD ["python", "app.py"]
この記事はここまでとなります。