CodeBuild+CodeDeploy+CodePipelineでEC2に自動デプロイしてみた


やってみたこと概要

  1. githubリポジトリが更新されるとパイプラインのSourceが実行される
    • デプロイするソース:vue-chat
    • Sourceの成果物はS3の「codepipeline-ap-northeast-1-…」バゲット vue-chat/SourceArtiに出力
  2. vue-chat/SourceArtiに出力されたソースをCodeBuildがビルド
    • 同バゲットvue-chat/BuildArtifにビルド済みソースを出力
  3. vue-chat/BuildArtifのビルド済みソースをCodeDeployが受け取りEC2に配置
  4. 配置されたソース内のappspec.ymlの内容が実行されてデプロイ完了

CodeBuild

AWSマネジメントコンソールでCodeBuildを選択しビルドプロジェクトを作成

githubのvue-chatリポジトリをビルドする設定

Buildspec

Buildspecは「ビルドコマンドの挿入」を選択し、以下のコマンドを記述

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 10
  pre_build:
    commands:
      - npm update -g npm
      - npm install
  build:
    commands:
      - npm run build
artifacts:
  files:
    - '**/*'
  • phases
    • ビルド工程を記述する宣言
  • install
    • ビルド環境を宣言
  • pre_build
    • node.jsをCodeBuildのビルド環境にインストール
  • build
    • npmビルド実行
  • artifacts
    • ビルドしたソースを出力する宣言
  • files
    • 出力するソース('**/*'はソース一式 本来は'dist/*'が良さそう)

CodeBuildびアーティファクトの設定はマネジメントコンソールからもできるが
「セマンスティックバージョニングの有効化」にチェックをつけると
上記のBuildspecの内容が優先される

IAMロール(CodeBuild)

CodeBuildのサービスロールに「AmazonS3OutpostsReadOnlyAccess」を追加して
ビルド済みソースをS3にアップロードできるようにする

サービスロールはCodeBuild-ビルドプロジェクト-環境に記載されている

ログ(CodeBuild)

CodeBuildのビルド実行ログはS3に出力するようにした

CodeBuildでビルド実行するとS3には圧縮されたログファイルが出力される

デプロイするEC2を作成

AmazonLinux2でEC2インスタンスを作成

IAMロール(EC2)

CodeBuildがS3に出力したビルド済みソースをEC2に配置するために「AmazonS3ReadOnlyAccess」を設定

CodeDeploy Agentインストール

CodeDeployからEC2にデプロイができるようにEC2にagentライブラリをインストール
下記コマンドはEC2デプロイのためにCodeDeployを導入するから引用しています

# ec2-userで実行
$ sudo yum update
$ sudo yum install ruby
$ sudo yum install aws-cli
$ cd /home/ec2-user
$ aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . --region ap-northeast-1
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status

アプリケーション起動に必要なライブラリをインストール

今回はVue.jsプロジェクトを起動するのでvue-cliをEC2にインストール

$ npm install -g @vue/cli

CodeDeploy

デプロイプロジェクトを作成

IAMロール(CodeDeploy)

CodeDeployのサービスロールは
CodeBuildで出力したビルド済みソースを受け取るため「AmazonS3ReadOnlyAccess」と
EC2にソースを配置するため「AmazonEC2FullAccess」を設定
(AmazonEC2RoleforAWSCodeDeployだとPermissionErrorになってしまった)

githubプロジェクトにデプロイ設定

CodeDeployでデプロイするためにプロジェクトにデプロイ工程を記述したファイルを作成

appspec.yml

デプロイするプロジェクトのルートディレクトリにappspec.ymlを作成

appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html
hooks:
  ApplicationStart:
    - location: /scripts/codedeploy_start.sh
      timeout: 180
  • files.destination
    • S3のソースを配置する場所
  • ApplicationStart.location
    • アプリケーション配置後の処理を記述したshファイルを指定

アプリケーション起動shファイル

appspec.ymlで指定した「codedeploy_start.sh」を作成する
npmコマンドでVue.jsアプリケーションを実行するだけ

codedeploy_start.sh
#!/bin/bash

npm run serve

CodePipeline

上記で作成・設定した内容でパイプラインを作成

パイプライン実行

これでリポジトリに変更をプッシュするだけでデプロイできちゃうのか(゚▽゚)ワクワク

しかし、現実は

CodeDeployが失敗。。。

エラーを見てみるとnpm run serveした時にpackage.jsonが見つからなかった模様

appspec.ymlからcodedeploy_start.shを実行した時のカレントディレクトリは/なので
codedeploy_start.shでcd 配置したソースのディレクトリを記述する必要がある

配置したソースのディレクトリにはパイプライン実行毎に振られるランダムなIDが含まれているのでどのように記述すれば良いか調査中
(配置ディレクトリ例:/opt/codedeploy-agent/deployment-root/3ee0a546-27db-4534-a055-098b9173f625/d-4ARZ3L0Q6/deployment-archive/vue-chat