WordPress環境のビルドから公開まで全てをAWS環境で構築する


Docker + CodeBuild + ECR + S3 + RDS + CloudFront + Elastic Beanstalkです。興味のある方は参考にしてみてください(ソースコードあり)

このblogは2019/09現在、docker、AWS(EB)環境で動いています。過去にこのような記事も書きました。
http://tech-blog.tsukaby.com/archives/989

今のままでもいいのですが、中途半端に手動作業が必要だったり、AWS以外に依存していたりとあまり好ましくない部分があったので、完全にAWS統一してみました。

概要

GitHub上でElastic Beanstalk(EB)設定ファイルやWordPressのDockerfileなどを管理します。秘密情報はGitHub上には乗せずにEBの環境設定上に乗せます。

GitHubでpushイベントが発生するとCodeBuildがビルドを初めて、完成したDocker imageをECRにpushし、さらにEBの設定を使ってEBのアプリケーションバージョンを作成し、EBにアップロードします。

その後、手動でEBの環境を作成するか、既に環境が作成されているのであれば、手動でデプロイを行い、完了です。
(RDSは既に存在する前提)

では具体的に説明していきます。AWSとDockerに詳しい人は説明を見ずにコードを見た方が早いかと思います。

https://github.com/tsukaby/tsukaby-tech-blog-docker/tree/3222518d27ced27bd4bd745090c52e1a8c606ec2

Dockerfileの用意

必ずしもDockerである必要はないのですが、可搬性があったり、拡張性があったりして、自分はDockerで組むことを選択しました。(AWSでWordPressを建てるならWordPress専用AMIとかもあるみたいですね。そちらの方が実はいいのかもしれません。)

Dockerfileの作り方は以前書いた記事と同様です。公式のimageをベースにして、プラグインを入れたり、langやthemeを入れたりします。

画像をアップロードするとwp-content/uploadsディレクトリに保存されますが、これはインスタンスを消したりDocker containerを消したりすると消えます。なので永続化を考えないといけないのですが、それはS3に保存させます。

以前書いた記事をご覧ください。

http://tech-blog.tsukaby.com/archives/972

完成したらbuildを確認するなり、localで動かすなりしてみます。localで動かす場合はdocker-composeを用意しているので、これを使うと良いかと思います。

https://github.com/tsukaby/tsukaby-tech-blog-docker/blob/3222518d27ced27bd4bd745090c52e1a8c606ec2/docker-compose.yml

AWSの事前準備

以下を事前に作成しておきます。AWSのweb consoleから軽く操作するだけです。

  • EB上でアプリを作成する(アプリの作成だけで良いです。実際に環境まで作成しなくて良いです)
  • ECR上にDockerリポジトリを作成する
  • S3にEBアプリのバージョンファイルを配置するためのバケットを作成する(このバケットはEBのアプリと同じregionに作成してください)

ビルド

Docker imageをビルドし、レジストリに保存します。
基本的に以下に従って設定していくだけです。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-docker.html

buildspec.ymlファイルを作成し、中にビルドする内容を書きます。EBのバージョン作成も後で必要になりますが、まずはdocker buildとECRへのpushの処理だけ書きます。

version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - $(aws ecr get-login --region ap-northeast-1 --no-include-email)
      - REPOSITORY_URI=985988196667.dkr.ecr.ap-northeast-1.amazonaws.com/tsukaby-tech-blog
      - VERSION=$(git rev-parse HEAD)
      - EB_FILE_NAME=${VERSION}.zip
  build:
    commands:
      - docker build -t ${REPOSITORY_URI}:${VERSION} ./docker
  post_build:
    commands:
      - docker push ${REPOSITORY_URI}:${VERSION}

CodeBuildのプロジェクトを作成し、設定を行います。以下は設定例です。

プロジェクト:任意の名前ビルドバッジを有効にする:ONソースプロバイダ:GitHubリポジトリ:OAuthで認証し、GitHubアカウントのリポジトリGitHubリポジトリ:対象のリポジトリのURLを選択ビルドの開始と(略):ONウェブフック コードの変更がこのレポジトリにプッシュされるたび(略):ONイベントタイプ:プッシュマネージド型イメージオペレーティングシステム:Ubuntuランタイム:Standardイメージ:standard2.0イメージのバージョン:常に最新特権付与 Dockerイメージを構築するか(略):ON新しいサービスロール:ONアーティファクト追加設定 キャッシュタイプ:ローカルDockerLayerCache:ON

必要に応じて変更してください。
ちなみにこのタイミングで実行してもIAMにECRへの権限がないのでビルド失敗します。

IAMを開いて、自動生成されたIAMのポリシーを変更します。
自分の場合は各CodeBuildプロジェクトでservice roleを使いまわしていいや、と思っているので、作成されたservice roleにAmazonEC2ContainerRegistryFullAccessポリシーを付けました。

これで実行するとビルドが成功します。

この画像ではまだ成功していませんが、動いてはいます。

EB, S3への権限追加とEBのバージョン作成も同じように行います。

buildspec.ymlはこう変えます。

version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - $(aws ecr get-login --region ap-northeast-1 --no-include-email)
      - REPOSITORY_URI=985988196667.dkr.ecr.ap-northeast-1.amazonaws.com/tsukaby-tech-blog
      - VERSION=$(git rev-parse HEAD)
      - EB_FILE_NAME=${VERSION}.zip
  build:
    commands:
      - docker build -t ${REPOSITORY_URI}:${VERSION} ./docker
      - cd eb
      - envsubst < Dockerrun.aws.tmpl.json > Dockerrun.aws.json
      - zip -r ../${EB_FILE_NAME} ./
      - cd ..
  post_build:
    commands:
      - docker push ${REPOSITORY_URI}:${VERSION}
      - aws s3 mv ${EB_FILE_NAME} s3://tsukaby-eb-binary/tsukaby-tech-blog/
      - |
        aws elasticbeanstalk delete-application-version \
          --application-name tsukaby-tech-blog --version-label ${VERSION} \
          --region ap-northeast-1
      - |
        aws elasticbeanstalk create-application-version \
          --application-name tsukaby-tech-blog --version-label ${VERSION} \
          --source-bundle S3Bucket="tsukaby-eb-binary",S3Key=tsukaby-tech-blog/${EB_FILE_NAME} \
          --region ap-northeast-1

Dockerrun.aws.tmpl.jsonというものが新たに追加されています。詳細は私のリポジトリで確認してください。
https://github.com/tsukaby/tsukaby-tech-blog-docker/blob/3222518d27ced27bd4bd745090c52e1a8c606ec2/eb/Dockerrun.aws.tmpl.json

tsukaby-eb-binaryにEBのバージョンファイルを配置するのですが、このバケットに対するフルアクセス権限を持つポリシーを作成して、CodeBuildのサービスロールにアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::tsukaby-eb-binary",
                "arn:aws:s3:::tsukaby-eb-binary/*"
            ]
        }
    ]
}

EBのポリシーも同じように作成してアタッチします。以下は全てのEBアプリ(リソース)に対してEB Version関する操作のみ全て可能なポリシーです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "elasticbeanstalk:UpdateApplicationVersion",
                "elasticbeanstalk:DescribeApplicationVersions",
                "elasticbeanstalk:CreateApplicationVersion",
                "elasticbeanstalk:DeleteApplicationVersion"
            ],
            "Resource": "*"
        }
    ]
}

EB環境の作成

以下にjsonがあるので、この設定ファイルとコマンドを使って、EB環境を一発で作ることができます。

https://github.com/tsukaby/tsukaby-tech-blog-docker/blob/master/eb/environments/prd.json

・・・がこのファイルはそのままは使えません。VPCのIDなどはAWSアカウントごとに違うので変更しないといけないですし、バージョンなども設定する必要があります。適宜変更してください。

必要な部分を変更した後で以下のようなコマンドでEBの環境を作成することができます。

$ aws elasticbeanstalk create-environment --environment-name ${ENV_NAME} --version-label ${VERSION_LABEL} --cli-input-json file://eb/environments/prd.json

ENV_NAMEやVERSION_LABELはご自身の環境に合わせて変更してください。これらの引数を使わずにjsonファイル内に直接書いてもOKです。

CUIから作る方法もありますが、もちろんAWS Web Console(GUI)から作成する方法もあります。

EB環境へのデプロイ

前節では環境の作成方法を説明しました。既に環境が存在する場合は環境を作成せずに、デプロイのみ行います。

これはコマンドでやってもいいのですが、GUIからやる方が簡単かと思います。

アップロードとデプロイのボタンを押してアプリケーションバージョンのページに飛び、対象のバージョンをどのEB環境にデプロイするか選ぶだけです。簡単。

補足

EB Logs

EB環境を作成しても正しく立ち上がらない可能性があります。そのときはEBのlogを出力してみると良いかと思います。Dockerなのか、中のアプリなのか、EC2の初期化なのか、どこに問題があるのかわかるかと思います。
ログ出力はGUIから操作できるので簡単です。

RDS SecurityGroup

RDSのセキュリティグループまわりは注意が必要です。RDSのインバウンドの解放条件を同サブネット内に限定したり、同セキュリティグループが設定されたEC2に限定したりして、外部から接続できないようにすると安全です。

EB Version

EBのバージョンはS3以下に保存されていて、これには上限があります。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_service_limits.html#limits_elastic_beanstalk

デフォルトだと1000です。確かアプリケーションごとではなくて、アカウントごと、です。なのでEBを多用している場合、上限に引っかかる場合があります(仕事で上限行ったことあります)。

必要に応じて自動削除の仕組みなどを入れておくと良いかもしれません。
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/applications-versions.html

CloudFront

EBで公開するところまでは説明しましたが、自分の環境の場合、さらに独自ドメインの導入とCloudFrontの導入も行なっています。

このあたりはこちらの記事が詳しいので、それに従ってみると良いかと思います。

WordPressサイトをCloudFrontで配信する - Qiita

過去にも書いたのですが、一部User-Agentの設定を行わないと、WordPressのVisualEditorが使えなくなるので注意です。

http://tech-blog.tsukaby.com/archives/1413

以上です。設定に時間はかかりますが、それほど難しいことはしていないので、多少AWSの知識がある人にとっては簡単かと思います。

よかったらDocker + AWSでWordPress構築やってみてください。