AWS上でコンテナでのWebアプリの構築(1.CodeBuildでコンテナイメージをビルド・ECRへPush)

2022年早々、AWSでコンテナを使ったWebアプリの構築を試したので、手順をまとめました。
ただコンテナを動かすだけではなく、ソースコードからコンテナイメージをビルドし、自動で最新のコンテナイメージをデプロイするフローを作りました。

下記の図のようにして構築しました。

上記の図の中から、

  1. CodeBuildでコンテナイメージをビルド・ECRへpush
  2. ECS+FargateでECRのコンテナイメージを元にコンテナを起動
  3. CodePipelineで、自動でECSにコンテナをデプロイ

上記3つに分け、今回は「CodeBuildでコンテナイメージをビルド・ECRへpush」について記事にまとめます。

概要

今回は、下記の赤枠の部分について進めます。

ECR初期設定

まず、コンテナイメージを格納するためのECRのリポジトリを作成します。

  1. Amazon ECRの画面にて、「リポジトリを作成」ボタンを押します。
  2. 下記のように任意のリポジトリ名を入力し、「リポジトリを作成」ボタンを押します。可視性設定は、「プライベート」にします。(仕事上でパブリックにイメージを作成することは無いと思うので)
  3. 下記のようにリポジトリが作成できていれば完了です。

CodeCommit(GitHub)にソースコードを用意

コンテナのソースコードと、CodeBuildを動かすためのソースコードを用意します。

用意するソースコード

Dockerfile

まず、Dockerfileです。apache+phpのDockerfileを用意しました。

FROM php:7.3-alpine3.12

RUN apk update && apk add --no-cache \
    # apache
    apache2 apache2-ssl \
    # phpパッケージ
    php7-common php7-apache2 php7-ctype php7-fileinfo php7-json php7-mbstring php7-openssl \
    php7-pdo php7-pdo_mysql php7-mysqli \
    php7-tokenizer php7-xml php7-session \
    # 追加
    php7-bz2 php7-calendar php7-exif php7-gettext php7-pecl-imagick php7-pecl-mcrypt php7-pcntl php7-pdo_mysql php7-shmop php7-sockets \
    php7-sysvmsg php7-sysvsem php7-sysvshm php7-wddx php7-xmlrpc php7-xsl php7-zip \
    # タイムゾーン
    tzdata  && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

buildspec.yml

CodeBuildは、その処理をymlで記載します。
AWSの公式ページからそのままコピペで用意しました。

version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon 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
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -f ./docker/apache-php/Dockerfile -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:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG

ソースコードをGitにPush

  1. 上記ソースコードを下記のようなディレクトリ構成で配置します。

    .
    ├── buildspec.yml
    └── docker/
           └── apache-php/
               └── Dockerfile

    通常、例えば以下のように、トップディレクトリに、docker-compose.ymlなど、別のファイルやディレクトリも置くと思うので、それを考慮したディレクトリ構造としています。

  2. AWSのサービスを使うのであれば、これらをCodeCommitにpushするところなのですが、今回は(すでにGitHubを使ってたので)、GitHub上のリポジトリにこれらのファイルをpushしておきます。

CodeBuild設定

初期設定

  1. 以下からCodeBuildのプロジェクトを作成します。

  2. 任意のプロジェクト名を入力します。

  3. 今回は、先程記載したとおり、GitHubと連携するように設定します。認証用のダイアログが表示されるので案内に従って、承認してください。

  4. 認証したら、リポジトリ名や対象のブランチ名を入力します。

  5. 下記のようにCodeBuildを実行する「環境」を設定していきます。「特権付与」はチェックしておかないとDockerイメージが作成できないのでチェックしておきます。

  6. CodeBuild実行用のロールが必要なので、任意の名前で作成します。

  7. CodeBuildを実行する環境のリソースも設定できます。今回は最小の構成で設定します。

  8. 以下で、先程「buildspec.yml」内に記載のあった環境変数を設定します。

  9. 先程用意したbuildspec.ymlを使うので下記ラジオボタンを選択した状態にします。ファイル名を指定することも出来ます。

  10. 「ビルドプロジェクトを作成する」ボタンを押すと完了です。

初期設定で追加したロールへのポリシー追加

先程作成したロールに対して、ECRを操作するポリシーを追加する必要があるので追加します。

  1. IAMの管理画面から先程追加したポリシーを選択します。

  2. 「ポリシーをアタッチします」ボタンからポリシーを追加します。

  3. 「AmazonEC2ContainerRegistryPowerUser」というポリシーを検索して選択します。

  4. 以下のようにポリシーが設定されていれば完了です。

CodeBuild実行・ECRへのイメージのビルドの確認

  1. 「ビルドを開始」ボタンを押すと、作成したプロジェクトのCodeBuildの実行が開始します。

  2. 以下のように「成功」と表示されればビルド成功です。(写真は何回か手順を間違えたので失敗しています)

  3. ECRの画面を確認すると、確かにイメージが作成出来ていることが確認できます。

これで、ECSで起動するためのコンテナイメージがの準備はできました。
あとは、これを自動化します。

CodeBuildの自動化

mainブランチにpushがあったタイミングで自動でCodeBuildが動くように設定します。

  1. 下記のように対象のプロジェクトの画面で、「編集」プルダウンから、「ソース」を選択します。

  2. 入力項目の下記部分を下記のように入力します。「イベントタイプ」を push にし、「HEAD_REF」に、ブランチを指定し ^refs/heads/main$ のように書くと、「mainブランチにpushがあったタイミング」という指定が出来ます。

  3. この状態で、mainブランチにpushすると、下記のようにCodeBuildが動き出します。

自動でコンテナイメージが作れた

これで、ソースコードを用意したら自動で「CodeBuildでコンテナイメージをビルド・ECRへpush」をすることができました。
次回は「ECS+FargateでECRのコンテナイメージを元にコンテナを起動」について記事にまとめます。