LUCK!

こんにちは、初めまして。エンジニアの杉本翔平です。

Nuxtで作ったプロジェクトをS3にデプロイする。ついでにパイプラインも作成

前回golangでの適当helloworldをFargateにパイプラインでデプロイしました。 Fargateすら必要ない。静的コンテンツを載せるだけでOKという場合があると思います。特に最近ではNuxtが使いやすくなってきて、genすればdistにindex.htmlが作られるという。。。
なので、今回はNuxtをS3にデプロイする方法をまとめました。 もちろんCloudFrontを使ってサブドメインHTTPSにします。

bucket作成

  • 何も考えずにぽちぽち作る
  • プロパティタグから「 Static website hosting」を設定する
    このバケットを使用してウェブサイトをホストする:ON
    インデックスドキュメント:index.html

参考

AWS S3で静的Webページをホスティングする - Qiita

CloudFront 経由で S3 のファイルにアクセスする - Qiita

CloudFrontよりDistributionsを作成する

  • webで「Get Started」する

Origin Domain Name:対象のバケットを選択
Restrict Bucket Access:YES
Origin Access Identity:Create a New Identity
Grant Read Permissions on :Yes, Update Bucket Policy
Alternate Domain Names:ドメインを入れる
SSL Certificate:Custom SSL Certificate (example.com)
Default Root Objec:index.html

Route53の設定

Aレコード、エイリアスは上で作ったCloudFrontのディストリビューションを選択

ポリシーの編集(確認)

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
        "Sid":"PublicReadForGetBucketObjects",
             "Effect":"Allow",
          "Principal": "*",
           "Action":["s3:GetObject"],
           "Resource":["arn:aws:s3:::<BUCKET_NAME>/*"
           ]
         },
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E21H4PD9QM10NM"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
        }
    ]
}

ソースプロジェクトに追加するもの

buildspec.yml

version: 0.2

phases:
  install:
    commands:
      - apt-get update -qq && apt-get install -y apt-transport-https
      - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
      - echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
      - apt-get update && apt-get install yarn
  pre_build:
    commands:
      - echo 'Start pre_build phase'
      - yarn
  build:
    commands:
      - echo 'Start build phase'
      - yarn build
  post_build:
    commands:
      - echo 'Start post_build phase'
      - cat ./node_modules/.bin/gulp
      - echo '------'
      - ./node_modules/.bin/gulp deploy
      # - ./deploy.sh

deploy.sh

#!/bin/bash

# nvm (node version manager) のロード、node のインストール (バージョン指定は .nvmrc ファイルにある)、 npm パッケージのインストール
[ -s "$HOME/.nvm/nvm.sh" ] && source "$HOME/.nvm/nvm.sh" && nvm use
# 既にインストールされていなければ、 npm をインストールする
[ ! -d "node_modules" ] && npm install

npm run generate
AWS_ACCESS_KEY_ID="<AWS_ACCESS_KEY_ID>" AWS_SECRET_ACCESS_KEY="<AWS_SECRET_ACCESS_KEY>" AWS_BUCKET_NAME="<AWS_BUCKET_NAME>" AWS_CLOUDFRONT="<AWS_CLOUDFRONT>" ./node_modules/.bin/gulp deploy
chmod +x deploy.sh

gulpfile.js

var gulp = require('gulp')
var awspublish = require('gulp-awspublish')
var cloudfront = require('gulp-cloudfront-invalidate-aws-publish')
var parallelize = require('concurrent-transform')

// https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html

var config = {
  // 必須
  params: { Bucket: process.env.AWS_BUCKET_NAME },
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,

  // 任意
  deleteOldVersions: false, // PRODUCTION で使用しない
  distribution: process.env.AWS_CLOUDFRONT, // Cloudfront distribution ID
  region: process.env.AWS_DEFAULT_REGION,
  headers: {
    /*'Cache-Control': 'max-age=315360000, no-transform, public',*/
  },

  // 適切なデフォルト値 - これらのファイル及びディレクトリは gitignore されている
  distDir: 'dist',
  indexRootPath: true,
  cacheFileName: '.awspublish',
  concurrentUploads: 10,
  wait: true // Cloudfront のキャッシュ削除が完了するまでの時間 (約30〜60秒)
}

gulp.task('deploy', function() {
  // S3 オプションを使用して新しい publisher を作成する
  // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
  var publisher = awspublish.create(config, config)

  var g = gulp.src('./' + config.distDir + '/**')
  // publisher は、上記で指定した Content-Length、Content-Type、および他のヘッダーを追加する
  // 指定されていない場合、 x-amz-acl はデフォルトで public-read に設定される
  g = g.pipe(
    parallelize(publisher.publish(config.headers), config.concurrentUploads)
  )

  // CDN のキャッシュを削除する
  if (config.distribution) {
    console.log('Configured with Cloudfront distribution')
    g = g.pipe(cloudfront(config))
  } else {
    console.log(
      'No Cloudfront distribution configured - skipping CDN invalidation'
    )
  }

  // 削除したファイルを同期する
  if (config.deleteOldVersions) g = g.pipe(publisher.sync())
  // 連続したアップロードを高速化するために、キャッシュファイルを作成する
  g = g.pipe(publisher.cache())
  // アップロードの更新をコンソールに出力する
  g = g.pipe(awspublish.reporter())
  return g
})

gulpを追加

npm install --save-dev gulp gulp-awspublish gulp-cloudfront-invalidate-aws-publish concurrent-transform
npm install -g gulp

CodeDeployからデプロイプロジェクトを作る

特に難しいところはない。 特権を付与することを忘れずに

環境変数

AWS_CLOUDFRONT           <AWS_CLOUDFRONTのID>
AWS_SECRET_ACCESS_KEY     <AWS_SECRET_ACCESS_KEY>
AWS_BUCKET_NAME         <AWS_BUCKET_NAME>
AWS_DEFAULT_REGION      ap-northeast-1
AWS_ACCESS_KEY_ID         <AWS_ACCESS_KEY_ID>

fontsとiconsがデプロイされなかったので、手動であげる。

pipelineを作る

  • ノリでいける