Amazon EC2 インスタンスへの Docker イメージのビルド・デプロイ自動化

ソフトウェアやシステムの開発手法の1つにアジャイル開発があります。アジャイル開発はユーザーニーズに素早く対応するための、アプリケーションを高速に開発する手法です。そしてアジャイル開発には、作成したアプリケーションを素早くリリースするためのCI/CD環境が必要になります。

今回は、AWSのCodepiplineを用い、EC2インスタンスへDockerイメージをビルドし自動デプロイする方法を書きます。構成はシンプルなものですが、ご参考になれれば幸いです。

構築環境について

構成図は下記の通りです。AWS上のWEBサイトのCI/CD環境を構築いたします。

 

基本的な流れ

パイプラインの流れは下記の通りです。

  1. Visual Studio code上に作成したファイル群をCodeCommitにプッシュすると、Codepiplineが起動し、2以降が開始
  2. ファイル群の中にあるDockerファイルから、CodebuildでDockerイメージをビルド
  3. 作成したDockerイメージがECRにプッシュ
  4. ECRにプッシュされたDockerイメージが、EC2インスタンスからプルされる + CodeCommit上にあるWEBサイトのhtmlファイルが、デプロイされる

※すでにECR上に同じDockerイメージがECRにプッシュされている場合は、2と3はスキップ。

 

利用イメージ
WEBサイトの表示内容を変更したい

変更したindex.htmlファイルをCodecommitにプッシュすると、変更したindex.htmlがEC2インスタンスにデプロイされ、WEBサイトの表示内容を変えることができます。

Dockerコンテナを更新したい

変更したDockerファイルをCodecommitにプッシュすると、新しいDockerイメージが作成されECRにプッシュされます。その後EC2インスタンスに新しいDockerイメージがプルされ、新しいDockerコンテナが立ち上がります。

 

設定方法

前準備

配信先のEC2インスタンスへは、事前に下記の3つが必要になります。

  1. EC2インスタンス用のAWS Identity and Access Management (IAM)ロールをアタッチ
  2. CodeDeployエージェントのインストール
  3. CodeDeployエージェントの設定ファイルを編集

VPCには下記の3つが必要になります。

  1. VPCエンドポイントの設定
  2. VPCエンドポイントへのセキュリティグループの設定
  3. EC2インスタンス用に作成したIAMロールに対し、プライベートVPC用のポリシーを付与

詳細は、下記をご確認ください。

Amazon ECRの説明

Amazon ECR上にリポジトリを作成します。ここではCodebuildでビルドするDockerイメージと同じ名前にする必要があります。ここではリポジトリ名は、img_mywebとしています。

 

AWS CodeCommitの説明

ローカルの端末にVisual Studio codeをインストールし利用します。Visual Studio code上に作成したフォルダ構成は下記の通りとしました。

[Visual Studio code上のフォルダ構成]

├── buildspec.yml #CodeBuildでビルド実行時に実行するコマンドを記述するYAMLファイル
├── dockerfile #ビルドするDockerイメージの内容を記載
├── appspec.yml  # CodeDeployで利用するでデプロイ処理を記述するYAMLファイル
├── index.html # 配信先のEC2インスタンスへ配布するhtmlファイル
└── src
│ ├── Docker.sh #EC2インスタンス上で実行させる、ECRからDockerイメージをプルしてコンテナを起動するスクリプト

そのあと、CodeCommit上に下記の内容のファイル群をプッシュいたします。Codecommitとローカル端末のVisual Studio codeとの連携には、下記URLが参考になります。

※ちなみに、AWSのコンソールログイン時にMFAを強制にしていた場合は連携が失敗します。下記方法で回避が可能です。

 

次に、それぞれのファイルについて詳しく見ていきます。

buildspec.yml

Codebuildで実行させるbuildspec.ymlを記載いたします。buildspec.ymlとは、CodeBuildでビルド実行時に実行するコマンドを記述するYAMLファイルのことです。ここでは、img_mywebという名前のDockerイメージをビルドします。

version: 0.2
 
#DOCKER_HUB アカウントを記載
env:
  parameter-store:
    DOCKER_USER: /CodeBuild/DOCKERHUB_USER
    DOCKER_PASSWORD: /CodeBuild/DOCKERHUB_PASS
  variables:
    DOCKER_BUILDKIT: “1”
 
phases:
  pre_build:
    commands:
      – echo Logging in to Amazon ECR…    #ECRにログインしてDockerイメージをプル
      – aws ecr get-login-password –region $AWS_DEFAULT_REGION | docker login –username AWS –password-stdin $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
 
      #CodebuildのAPI呼び出し制限を回避するため、DOCKER_HUBにログイン
      – echo Logging in to Docker Hub…
      – echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USER} –password-stdin
 
      – docker pull $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/img_myweb:latest || true
 
  build:
    commands:
      – echo docker build…
      – docker build -t img_myweb .            #img_mywebという名前のDockerイメージをビルド
  post_build:
    commands:
      – echo Pushing the Docker image…     #作成したDockerイメージ img_mywebをECRにプッシュ
      – docker tag img_myweb:latest $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/img_myweb:latest
      – docker push $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/img_myweb:latest
artifacts:
  files:
    – ‘**/*’

$AWS_DEFAULT_REGION:使用するリージョンに読み替えてください。

$AWS_ACCOUT:使用するAWSアカウントに読み替えてください。

補足1

pre_buildフェーズにおいて、ECR上の作成済のDockerイメージをプルする、docker pullコマンドを実行しています。この記述を追加することで、ビルドに要する時間をスキップできます。初回やdockerfile変更時などで、ECR上に存在しない場合は、buildフェーズで一からビルドされます。

補足2

Docker Hubのアカウントを事前に用意します。AWS Systems Managerに記載し、それを参照してDocker Hubにログインしています。(buildspec.ymlの赤文字部分)。これを記述しない場合、まれに下記のアラートが発生する可能性があります。これはCodebuildのAPI呼び出し制限に引っかかるためです。

toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit

詳しくは、下記をご確認ください。後述の”AWS Codebuildの説明”においても補足します。

 

dockerfile

次にdockerfileです。Apacheをプルするだけなのでシンプルなものです。

FROM httpd

 

appspec.yml

次に、Codedeployで実行させるappspec.ymlを記載いたします。appspec.ymlとは、CodeDeployで利用するでデプロイ処理を記述するYAMLファイルです。ここでは、Codecommitにプッシュしたindex.htmlを、配信先のEC2インスタンスの/var/www/htmlディレクトリに配信するように指示しており、その後Docker.shを実行します。

version: 0.0
os: linux
files:
   – source: index.html                 #配信したいファイル名
     destination: /var/www/html    #配信先のEC2インスタンスのディレクトリ
file_exists_behavior: OVERWRITE   #destinationにファイルが既にある場合は上書き
hooks:
  AfterInstall:
     – location: src/Docker.sh           #ECRからDockerイメージをプルし、コンテナを作成するプログラム。詳細は後述

 

index.html

WEBサイトで公開するhtmlファイルです。簡易なものを用意しました。

<!DOCTYPE html>
<html>
<head>
  <title>これはテストです。</title>
  <meta charset=”UTF-8″>
</head>
<body>
  <h1>これはWEBサイトです。</h1>
</body>
</html>

 

Docker.shプログラム

img_mywebのイメージをECRからプルし、古いコンテナがある場合は削除&img_mywebのイメージを用いて、コンテナを起動するプログラムです。ところどころスリープを入れています。appspec.yml上で本プログラムの実行を指示しています。

#!/bin/sh

aws ecr get-login-password –region $AWS_DEFAULT_REGION | docker login –username AWS –password-stdin $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
sleep 10s
sudo docker pull $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/img_myweb:latest

#Delete old container
sudo docker stop myweb
sleep 10s
sudo docker rm myweb
sleep 10s

#Create new container
sudo docker run -d -p 80:80 –name myweb -v /var/www/html:/usr/local/apache2/htdocs $AWS_ACCOUT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/img_myweb

$AWS_DEFAULT_REGION:使用するリージョンに読み替えてください。

$AWS_ACCOUT:使用するAWSアカウントに読み替えてください。

AWS Codebuildの説明

ビルドプロジェクトの作成

CodeBuildの画面から、ビルドプロジェクトを作成していきます。”ビルドプロジェクトを作成する”ボタンを押します。

■ソース

  作成したCodecommitのリポジトリ名とブランチ名を指定します。

■環境

・オペレーティングシステム:Amazon Linux2/ランタイム:Standard/イメージ:Standardの最新を選択します。

・特権付与にチェックを入れます。Dockerのビルドを可能にするためです。

・buildspec.ymlに前述した、Docker Hubのアカウントをビルドプロジェクトにて記載いたします。追加設定 > パラメータの作成画面 を押下し下記内容でパラメータを作成ください。

名前 タイプ
DOCKERHUB_USER DOCKER HUBのIDを指定 パラメータ
DOCKERHUB_PASS DOCKER HUBのPasswordを指定 パラメータ

■Buildspec 

ビルド仕様 は “buildspec ファイルを使用”を選択してください。(デフォルトのままでOKです)

 

その後、”ビルドプロジェクトを作成する”ボタンを押して完了です。

補足

ビルドプロジェクトで利用するロールに、下記のポリシーをアタッチください。ECRにログインできるようにするためです。

AWS管理:AmazonEC2ContainerRegistryPowerUser

AWS CodeDeployの説明

アプリケーションの作成

CodeDeployの画面から、”アプリケーションを作成”ボタンを押します。

“コンピューティングプラットフォーム”は”EC2/オンプレミス”を選択します。

 

デプロイグループの作成

“デプロイグループの作成”ボタンを押します。

・サービスロール

   AWS管理ポリシーの”AWSCodeDeployRole”がアタッチされたロールを事前に用意し指定ください。

・環境設定

   ”Amazon EC2 インスタンス”をチェック > タググループ1にて、配布したいEC2インスタンスに付与されているタグ名を記載します。

・ロードバランサー

   ここでは無効を指定します。

その後、”デプロイグループの作成”ボタンを押して完了です。

AWS CodePiplineの説明

最後に作成した各Code群をパイプラインでつなぎます。”パイプラインを作成する”ボタンを押下して、作成してきた各構成要素を選択していけば完成です。

 

結果

最後に、index.htmlファイルをVisual Studio code上で変更して、CodeCommitにプッシュしてみます。

 

デプロイ前

WEB画面は下記のとおりです。

※事前にデプロイ先のEC2インスタンスがブラウザから見れるように設定ください。具体的にはEC2インスタンスへのインバウンドのHTTPアクセスを許可してください。

 

ローカルの端末のVisual Studio code上で、index.htmlの中身を修正します(赤文字:修正行)。

<!DOCTYPE html>
<html>
<head>
  <title>これはテストです</title>
  <meta charset=”UTF-8″>
</head>
<body>
  <h1>これは変更後のWEBサイトです</h1>
  <p>デプロイ成功しました!</p>
</body>
</html>

同様に、Visual Studio code上でCodecommitへプッシュするコマンドを実行します。

> git add .

> git commit -m “modify index.html”

> git push origin master

 

デプロイ後:

WEB画面は下記のとおりとなりました。変更されていることがわかります。

 

 

最後に

シンプルな構成でしたが、こちらを理解すると応用ができますので、お役に立てれば幸いです。

タイトルとURLをコピーしました