【初心者向け】CICDって何が嬉しいの?
AWSではじめるCICD②
投稿日: 2024/5/14
はじめに
こんにちは、渡部(わたなべ)です。
前回の【CICDって何がうれしいの?AWSで始まるCICD①】は基礎知識編となり、今回は実践編となるため、園田からバトンタッチで私、渡部(わたなべ)が説明します。
前回のブログでは、CICDの必要性と魅力について説明しました。今回からいよいよ実践編という事でAWS上でパイプラインの作成に入っていきます。
AWS CodeCommit:
ソースコードを管理するリポジトリでgitをホスティングしているサービス
AWS CodePipeline:
CICDにおけるパイプライン(コードのビルド、テスト、デプロイなどのプロセスを自動化したもの)を定義するツール。AWSでCICDパイプラインを作る上での根幹となります。
AWS CodeBuild:
ソースコードのビルド(コンパイル)及びテストを実施するサービス
ECR(Elastic Container Registry):
コンテナイメージの管理・保管を行うフルマネージドなリポジトリサービス。ECS(Elastic Container Service)と連携し、コンテナのデプロイを行います。
ECS(Elastic Container Service):
コンテナのフルマネージドオーケストレーションサービス。ECRからコンテナイメージを取得し、該当コンテナの実行環境を選択の上、管理を行うことができます。
実行環境はEC2上でECSが起動するもの、およびEC2無しでコンテナが単独で起動するFargateが存在します。基本的にはインスタンスの管理が必要ないFargateを利用することを推奨します。
Cloud9:
AWS環境で利用可能なIDE(統合開発環境)サービス
(今回の説明に必要なコマンド実行等はCloud9から実施しています。)
事前準備
今回の作成する環境ですが、ECSを用いて、インターネットからアクセスできるコンテナをデプロイします。コンテナにはnginxをインストールしてますので、インターネットからコンテナに対してアクセスした際に、作成したwebページを閲覧可能です。
手動でのデプロイ時は複数の工程が必要となりますが、その一連の作業をCode Pipelineを用いて自動化することが今回のゴールとなります。
まずはコンテナをデプロイするNW環境を作成します。
NW環境については以下の構成の通りとなり、VPC及びELB(ALB)が存在する通常の環境です。(すでに本環境がある前提でのお話になりますのでご注意ください。)

■NW構成図
上記NW環境がある前提で、実施する作業の概要となります。
作業1:コンテナイメージの作成
Dockerイメージを作成し、ECR(Elastic Container Registry)に今回使用するDockerイメージをアップロードする。
作業2:コンテナ作成設定
ECRに保存したDockerイメージを起動するために、ECS(Elastic Container Service)にてコンテナ作成の設定を行う。
作業3:ビルド設定の実施
ビルドとテストを行うために、CodeBuildにてビルドプロジェクトを作成する。
作業4:1~3の作業を自動化
Code Pipelineにてパイプラインを作成し、1~3の作業を自動化する
※環境へのデプロイは、CodeBuildにてビルドとテスト終了後にECSにて行われるため、上記の工程を踏むことでシンプルなCI/CDパイプラインの作成を行うことが可能です。
それでは作業1の工程から進めていきましょう。
作業1-① ECR (Elastic Container Registry)のリポジトリ作成
まずはDockerのコンテナイメージをアップロードする「レポジトリ」を作成しましょう。
1:AWSの検索タブでECRを検索

2:左タブのPrivate repositoriesの「Repositories」プライベートリポジトリを選択、「リポジトリを作成」をクリック。

3:可視性設定を「プライベート」、「レポジトリ名」を記入し、「レポジトリを作成」をクリック

4:作成が完了すると、「正常に作成されました」が出力

リポジトリを作成した段階では、リポジトリ内には何もファイルはない状態となっています。ここに、これから作成するDockerコンテナイメージを投入します。

作業1-② コンテナイメージを作成し、ECRにプッシュ
次にレポジトリに格納するコンテナイメージの作成を行います。
そもそもコンテナイメージとは何かですが、「コンテナ作成に関する命令が入ったテンプレート」と考えてください。最終的にECSにてデプロイされるコンテナは、このコンテナイメージを基に作成されます。まずはこのコンテナイメージの作成を行います。
今回はコンテナイメージの設計図とも言えるDockerfileの作成を行います。Cloud9にて以下のファイルの作成を行います。以下の通り記載しましょう。
# DockerHubにて提供されているnginx(Webサーバーソフト)のイメージを取得。
FROM nginx:latest
# updateコマンドによりインストール可能なパッケージの「一覧」を更新。
RUN apt-get -y update && apt-get -y install wget
# nginxデーモンを起動。
CMD ["nginx", "-g", "daemon off;"]
dockerではコマンドをforegroundで動かさないとコンテナが停止してしまうため注意しましょう。「CMD ["nginx", "-g", "daemon off;"]」を記載することで、foregroundで起動させる形となります。
Dockerfileを作成したら、先ほど作成したECRのリポジトリにイメージを投入します。そのためにまずはECRで作成したリポジトリのURIをコピーしましょう。

Cloud9にて該当のファイルを指定し、以下コマンドを打ちます。
※以下、Cloud9から実行するコマンド操作は青字で記載
Docker buildx build -f <リポジトリURI>/<リポジトリ名>:<タグ名>
リポジトリURI:
今回Dockerイメージを保管するECRリポジトリのURIを指定。
リポジトリ名:
1-①にて作成したリポジトリの名称を記載
タグ名:
Dockerイメージのバージョン番号。特にこだわりがなければ”latest”と記載してください。
■コマンド実行後の出力例

コマンド実行後、作成したDockerfileを基にDockerイメージが作成されます。
「docker images」コマンドにてイメージが作成されていることを確認可能です。

Dockerイメージを作成できていることが確認できたら、ECRのリポジトリにDockerイメージを保存するためにECRにloginを行います。
以下コマンドを入力してください。
Daws ecr get-login-password --region <所属リージョン> | docker login --username AWS --password-stdin <リポジトリURI>
所属リージョン:
Dockerイメージを投入するリージョンを指定。基本は作成したVPCと同じリージョンを選択してください(例:ap-northeast-1)
リポジトリURI:
今回Dockerイメージを保管するECRリポジトリのURIを指定

入力後、Login Succeededと出力されれば成功です。
Docker Loginが完了したら、あとは作成したDockerイメージをECRのリポジトリに保存するだけです。そのためにはdocker pushコマンドを利用します。
docker push <リポジトリURI>/<リポジトリ名>:<タグ名> .
AWSアカウントID:
ご自身のAWSアカウントID
所属リージョン:
Dockerイメージを投入するリージョンを指定。基本は作成したVPCと同じリージョンを選択してください(例:ap-northeast-1)
タグ名:
Dockerイメージのバージョン番号。特にこだわりがなければ”latest”と記載してください

コマンド完了後、ECRのリポジトリ内に作成したDockerイメージが保存されていることが確認できます。

作業2-① ECS(Elastic Container Service)
続いてECS(Elastic Container Service)にてコンテナの作成設定を行います。
ECSはAWSによる完全マネージド型コンテナサービスで、クラスター単位でそれぞれのサービスを管理しています。実行するコンテナはECRのレジストリから取得して、別途作成するタスク定義を用いて各クラスター内でサービス設定を行います。
それでは早速ECSの設定を実施しましょう。
■ECS クラスターの作成
まずはECSのページに遷移し、左上に記載されている「クラスター」を選択してください。

その後、「クラスターを作成」をクリックしてください。

クラスターの作成ページにて以下の通り、設定を投入してください。
AWSアカウントID:
ご自身のAWSアカウントID
クラスター名:
ご自由に記載してください
インフラストラクチャ:
「AWS Fargate」を選択

■ECS タスク定義の作成
続いてタスク定義を作成していきます。
タスク定義では、起動するコンテナのスペックといった、コンテナに関する設定を行います。起動時の設定をタスクとして設定しておき、後に作成するサービス設定にて利用します。

タスク定義を選択後、「新しいタスク定義の作成」をクリックしてください。
作成時に専用のタスクロール及びタスク実行ロールが作成されます。(「タスクロール」のカラムにて、「IAMコンソール」をクリックすることでロールが作成される。)
作成されたロールには、以下の許可ポリシーを追加してください。
- AmazonEC2ContainerRegistryReadOnly
- AmazonECSTaskExecutionRolePolicy
- CloudWatchFullAccess

■サービス作成
続いてサービスの設定を行います。
サービスの設定を行うには、クラスター設定にて作成したクラスターを選択し、項目「サービス」の画面にある「作成」をクリックします。

以下の通り設定を行っていきます。なお、VPCとセキュリティグループ、ALBの設定については適切なものを選択ください。あくまで説明時に選択されているVPC、サブネット、セキュリティグループはご自身で作成された物をご利用ください。必要なタスクは「1」を指定することでコンテナが1台起動します。

作成をクリック後、以下のバナーが上部に出現します。

CloudFormationにて作成の工程を確認することができます。本画面にてCREATE_COMPLETEと表示されたら作成完了となります。

クラスターの詳細画面においても、上部に対象のサービスがデプロイされましたと表示されていれば作成完了となります。

実際に作成したサービスに基づいて起動しているコンテナには、以下二つの方法から確認することが可能です。
- 作成したVPCにあるELBに紐づくFQDNでアクセス。
- 作成したサービスを選択することで確認ができるネットワーク設定欄にある、DNS名のオープンアドレスをクリック。

オープンアドレスをクリックすることで、デプロイされたコンテナにアクセスすることができます。今回であればnginxを用いてwebサーバを立てているため、以下のような画面が表示されます。

作業2-② CodeCommit
続いてCodeCommitの利用に関する説明を行っていきます。ECRにコンテナイメージをアップロードする際には、今まではCloud9上でコマンドを直接入力してプッシュしておりましたが、今後は特定のファイルに、入力するコードを事前に記入の上自動で実行されるようにします。
自動実行自体はCodePipelineを利用するのですが、その事前準備として、CodeCommitリポジトリに必要なコードをプッシュします。
まずはCodeCommitの画面に遷移し、「リポジトリを作成」をクリックしましょう。

リポジトリ名を自由入力し、「作成」をクリックしてください。

作成後、画面上部に成功と記載された緑色のバナーが出力されていればOKです。

では作成したリポジトリに必要なプログラムをプッシュしていきましょう。
作業2-③ Cloud9よりCodeCommitにコードをプッシュする
Cloud9上で以下のコマンドを記入してください。
Git clone https://git-codecommit.<作成リージョン>.amazonaws.com/v1/repos/<リポジトリ名>
所属リージョン:
Dockerイメージを投入するリージョンを指定。基本は作成したVPCと同じリージョンを選択してください。例:ap-northeast-1
リポジトリ名:
CodeCommitにて作成したリポジトリの名称

Git cloneを行うことで、Codecommitで作成したリポジトリに紐づくフォルダが作成されます。本フォルダ内にリポジトリにプッシュするファイルを入れていきます。

リポジトリにプッシュするファイルを投入したら、今度はgit addとgit commitを行っていきます。Git addコマンドでローカルリポジトリにプッシュするファイルを指定し、git commitコマンドでローカルリポジトリ内にあるファイルを更新します。Git commit時はコミット用のコメントを必ず記載してください。
Git add .
git commit -m “<コメント>”

最後にgit pushを行い、ローカルリポジトリからリモートリポジトリへと投入ファイルを送信します。
git push

プッシュが上手く完了していれば、CodeCommitのリポジトリ内に投入したファイルがリポジトリ内にあることを確認できます。

作業3-① CodeBuild
続いてCodeBuildにてCodeCommitに投入したコード群を用いてコードのビルドからテストまで行っていきます。
ビルド処理自体はbuildspec.ymlというyamlファイルにコマンド等を記載して実行することとなります。まずはCodeBuildでビルドプロジェクトを作成していきましょう。
CodeBuildのページを開く、「プロジェクトの作成」をクリックしてください。

ビルドプロジェクトの作成画面に遷移したら以下を参考に設定を行ってください。
以下注意点です。
- リポジトリ名はCodeCommitで作成したリポジトリ名を選択してください。
- サービスロールは新たにCodeBuild専用の物を作成しますが、作成後に以下の許可ポリシーを追加してください。
- AmazonEC2ContainerRegistryPowerUser
- AmazonS3FullAccess
- AWSCodeBuildAdminAccess
- AWSCodeCommitFullAccess
- 追加設定にある以下設定は必ず有効化してください。
「Dockerイメージを構築するか、ビルドで昇格されたアクセス権限を取得するには、このフラグを有効にします」

「ビルドプロジェクトを作成する」をクリックし、画面上部に緑色のバナーが出ることを確認してください。

■Buildspec.ymlの作成
Buildspec.ymlはビルドプロジェクトにおいてかなり重要なファイルとなります。別途説明を行いましたが、buildspec.ymlに記載されるコマンドをビルド及びテストの際に実行してくれます。このファイルをソースコードのルートフォルダに配置することで、CodeBuildがbuildspec.ymlを読み込んで、コマンドを上から自動で実行してくれます。
Buildspec.yml記述時には4つのフェーズがあるのが特徴です。具体的には以下の通りです。
- install
CodeBuildが実行するコンテナ内で、ビルドやテストに必要なパッケージ等をインストールするフェーズ - pre_build
ビルド実行前に必要な処理を行うフェーズ。ビルドに使用するファイルの整形やECRレポジトリへのログイン、Docker Loginなどはこちらのフェーズで記述 - build
ビルド及びテストを実施するフェーズ。Docker buildや環境のテスト(pytestなど)はこのフェーズで記述 - post_build
ビルド及びテスト実施後にCodeBuildに実行してほしいコマンドを実施するフェーズ
他にも4フェーズとは別にversion, envやArtifactsと呼ばれる項目を設けます。
- version
Buildspec.ymlのバージョンを記載します - env
環境変数を設定することができます。こちらは必須項目ではないので、設けなくても問題ないです - Artifacts
ビルド及びテストの出力結果が保存されているファイル名をここに記載。これらのファイルはS3に保存されます
〇作成した「Buildspec.yml」ファイル
version: 0.2
env:
variables:
SRC_AWS_ACCOUNT_ID:
phases:
install:
runtime-versions:
python: 3.9
commands:
pre_build:
commands:
- aws ecr get-login-password --region <所属リージョン> | docker login --username AWS --password-stdin .dkr.ecr.<所属リージョン>.amazonaws.com
- echo $DOCKERHUB_PASS | docker login -u $DOCKERHUB_USER --password-stdin
build:
commands:
- docker build -t <リポジトリ名>:<イメージ番号> .
- docker run -d -p 80:80 <リポジトリ名>:<イメージ番号>
- docker tag <リポジトリ名>:<イメージ番号> :<イメージ番号>
- docker push :<イメージ番号>
- printf '[{"name":"","imageUri":"%s"}]' :<イメージ番号> > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
AWSアカウントID:
ご自身のAWSアカウントID
所属リージョン:Dockerイメージを投入するリージョンを指定。基本は作成したVPCと同じリージョンを選択してください。例:ap-northeast-1
DOCKERHUB_USER:
Docker Hubのユーザー名
DOCKERHUB_PASS:
Docker Hubのユーザー名に紐づくパスワード
イメージ番号:
Dockerイメージのバージョン番号。特にこだわりがなければ”latest”と記載してください。
リポジトリ名:
ECRにあるリポジトリの名称
ECR URI:
ECRにあるリポジトリのURI
Buildspec.yml作成後はcodecommitの専用リポジトリにコードをプッシュしてください。(やり方については、codecommitに関する説明をご覧ください。)
作業4-① CodePipeline
それでは今回のCI/CDの根幹である、CodePipelineの作成に入りましょう。CodePipelineではパイプライン作成時に、事前に作成したパイプラインに組み込むアイテムを指定していきます。指定したアイテムを順に実行していき、最終的にデプロイまで行ってくれます。
それではさっそく作っていきましょう。
まずはCodePipelineの画面を開き、「パイプラインを作成する」をクリックしてください。

続いてパイプラインの設定を選択するとありますため、以下の通り設定してください。
パイプラインタイプという項目がありますが、今回はV1を選択します。
V2ではV1では選択できない細かい変数の指定等を行えますが、今回はシンプルなパイプラインの実装を行うため、V1で作成します。
必要な設定を投入したら「次に」をクリックしてください。

続いて、ソースステージの追加を行います。
ここでは事前に作成したCodeCommitのリポジトリを選択します。

続いてビルドステージを追加します。
ここではCodeBuildの項目で作成したビルドプロジェクトを選択します。

続いてデプロイステージとなります。
ここではデプロイプロバイダーとしてECSを選択してください。その後、事前にECSにて作成したサービスを選択してください。

一通り設定を完了すると、レビューというページに遷移します。設定に間違いがなければそのまま「パイプラインを作成する」をクリックしてください。

「パイプラインを作成する」をクリックすると、作成したパイプラインが早速動き出します。
SourceをCodeCommitから取得し、CodeBuildでビルドとテストを実行、最終的にビルドでdocker pushした新しいイメージを基に、ECSにてデプロイを行います。一通り成功すれば、以下のように「成功しました」と表示されます。

各フェーズにある「詳細を表示」をクリックすると、各フェーズで実行されている内容の詳細を確認できます。以下はBuildフェーズでbuildspec.ymlに記載されたコマンドを基に動作している様子となります。

作業4-② 承認フェーズの追加
作成したパイプラインに承認フェーズを追加していきます。承認フェーズを各フェーズの間に挟むことで、パイプラインの内容全てが自動で実行されるのを防ぐことができます。例えば、CodeCommitに投入したコードが、バグが治っていない改修前のコードであった場合、承認フェーズを間に挟まないとビルドからその先にデプロイまで実行されるため、バグが治っていない状態でリリースされてしまいます。
間に承認フェーズを挟むことで、リリース前に一度確認を手動で行い、障害が発生するリスクを下げることが可能です。
承認フェーズを追加するには、対象のパイプライン画面にて「編集」をクリックします。

承認フェーズを追加したい位置で、「ステージを追加する」をクリックします。
今回はSourceとBuildの間に追加します。

続いて、ステージ名を記載します。
今回はシンプルに「SourceAapproval」と記載します。

続いて、「アクショングループを追加する」をクリックしてください。

以下の通り設定してください。
承認リクエストを実施時に、SNSで関係者に承認通知を実施したり、コメントをメールで通知することも可能ですが、今回は承認実施のみを行います。
設定したら、「完了」をクリックしてください。

フェーズ「SourceApproval」が追加されたことを確認します。
問題なければ、パイプラインの編集を完了し、保存してください。

保存後、SourceとBuildの間に新たに「SourceApproval」フェーズが追加されていることを確認できます。一度動作確認のために、画面右上の「変更をリリース」するをクリックし、再度リリースをしてみましょう。

再度パイプラインを最初から動かすと、承認フェーズで止まっていることを確認できると思います。「Review」ボタンをクリック後、承認を実施することで、ビルドフェーズに進むことが可能です。

最後に
今回利用しているDockerコンテナではnginxサーバが動作しているため、アクセス時に表示されるページに変更を加え、パイプラインを動かしリリースすることで、リリースが上手く動作しているかを確認することが出来ます。
今回CodeBuildのbuildspec.ymlではビルドのみを実行していますが、こちらにpytestといったテスト用のパッケージを利用することで、テストを事前に実行した状態でリリースすることができます。
また、今回のリリースでは説明の関係上、「【初心者向け】CICDって何が嬉しいの? AWSではじめるCICD①」で説明したブルーグリーンデプロイではなく、ローリングアップデートという手法を用いてリリースしています。
ブルーグリーンデプロイの実装には、別途手順があるため、次回以降のブログにて紹介したいと思います。併せて次回は今回のCICD環境にテストを追加していきます。
それでは、「【初心者向け】CICDって何が嬉しいの? AWSではじめるCICD③」でお会いしましょう。
CTCは、AWSのビジネス利活用に向けて、お客様のステージに合わせた幅広い構築・運用支援サービスを提供しています。
経験豊富なエンジニアが、ワンストップかつ柔軟にご支援します。
ぜひ、お気軽にお問い合わせください。