TOP> コラム一覧>

【初心者向け】CICDって何が嬉しいの? AWSではじめるCICD②

はじめに

こんにちは、渡部です。

前回の【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構成図

作業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 -t <リポジトリURI>/<リポジトリ名>:<タグ名> .

リポジトリURI:
今回Dockerイメージを保管するECRリポジトリのURIを指定。

リポジトリ名:
1-①にて作成したリポジトリの名称を記載

タグ名:
Dockerイメージのバージョン番号。特にこだわりがなければ”latest”と記載してください。

■コマンド実行後の出力例

画面スクリーンショット

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

画面スクリーンショット

Dockerイメージを作成できていることが確認できたら、ECRのリポジトリにDockerイメージを保存するためにECRにloginを行います。

以下コマンドを入力してください。

aws 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 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
    ビルド及びテストを実施するフェーズ。Docker buildや環境のテスト(pytestなど)はこのフェーズで記述
  • post_build
    ビルド及びテストの出力結果が保存されているファイル名をここに記載。これらのファイルは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の画面を開き、「パイプラインを作成する」をクリックしてください。

画面スクリーンショット

続いて作成オプションを選択するとありますため、以下の通り設定してください。

今回はカスタムパイプラインを構築するを選択し、「次に」をクリックしてください。

画面スクリーンショット

続いてパイプラインの設定を選択します。

ここでは実行モードに「優先済み」を選択いただき「次に」をクリックして下さい。

画面スクリーンショット

続いて、ソースステージの追加を行います。

ここでは事前に作成したCodeCommitのリポジトリを選択します。

画面スクリーンショット

続いてビルドステージを追加します。

ここではCodeBuildの項目で作成したビルドプロジェクトを選択します。

画面スクリーンショット

続いてテストステージとなります。

Pytestといったテスト用のパッケージを利用している場合は、ここでテストステージを設けるのが一般的ですが、今回は利用していないのでスキップします。

画面スクリーンショット

続いてデプロイステージとなります。

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

画面スクリーンショット

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

画面スクリーンショット

「パイプラインを作成する」をクリックすると、作成したパイプラインが早速動き出します。

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

画面スクリーンショット

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

画面スクリーンショット

作業4-② 承認フェーズの追加

作成したパイプラインに承認フェーズを追加していきます。承認フェーズを各フェーズの間に挟むことで、パイプラインの内容全てが自動で実行されるのを防ぐことができます。例えば、CodeCommitに投入したコードが、バグが治っていない改修前のコードであった場合、承認フェーズを間に挟まないとビルドからその先にデプロイまで実行されるため、バグが治っていない状態でリリースされてしまいます。

間に承認フェーズを挟むことで、リリース前に一度確認を手動で行い、障害が発生するリスクを下げることが可能です。

承認フェーズを追加するには、対象のパイプライン画面にて「編集」をクリックします。

画面スクリーンショット

承認フェーズを追加したい位置で、「ステージを追加する」をクリックします。

今回はSourceとBuildの間に追加します。

画面スクリーンショット

続いて、ステージ名を記載します。

今回はシンプルに「SourceApproval」と記載します。

画面スクリーンショット

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

画面スクリーンショット

以下の通り設定してください。

承認リクエストを実施時に、SNSで関係者に承認通知を実施したり、コメントをメールで通知することも可能ですが、今回は承認実施のみを行います。

設定したら、「完了」をクリックしてください。

画面スクリーンショット

フェーズ「SourceApproval」が追加されたことを確認します。

問題なければ、パイプラインの編集を完了し、保存してください。

画面スクリーンショット

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

画面スクリーンショット

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

画面スクリーンショット

最後に

今回利用しているDockerコンテナではnginxサーバが動作しているため、アクセス時に表示されるページに変更を加え、パイプラインを動かしリリースすることで、リリースが上手く動作しているかを確認することが出来ます。

今回CodeBuildのbuildspec.ymlではビルドのみを実行していますが、こちらにpytestといったテスト用のパッケージを利用することで、テストを事前に実行した状態でリリースすることができます。

また、今回のリリースでは説明の関係上、「【初心者向け】CICDって何が嬉しいの? AWSではじめるCICD①」で説明したブルーグリーンデプロイではなく、ローリングアップデートという手法を用いてリリースしています。

皆様のご参考になれば幸いです。

関連コラム

CTCは、AWSのビジネス利活用に向けて、お客様のステージに合わせた幅広い構築・運用支援サービスを提供しています。
経験豊富なエンジニアが、ワンストップかつ柔軟にご支援します。
ぜひ、お気軽にお問い合わせください。

ご相談はこちら

【著者プロフィール】

渡部 喬登(わたなべ たかと)

伊藤忠テクノソリューションズ株式会社 クラウドアーキテクト

CTCが提供するマネージドサービス担当者として、VMware SD-WANなどを用いたクラウドネットワーク検証、構築を実施。 クラウドネットワーク検証でクラウドの可能性を感じ、AWS関連業務に異動願を出しAWS担当となる。 現在はAWS関係のサービス検証及び自動化等の開発を実施している。

渡部 喬登(わたなべ たかと)

pagetop