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

[前回](https://qiita.com/sugimotosyo/items/dc49c1f1c5a54233cb9f)は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](https://qiita.com/dogwood008/items/a92abae789f4b0466f38)
  
  [CloudFront 経由で S3 のファイルにアクセスする - Qiita](https://qiita.com/NaokiIshimura/items/46994e67b712831c3016)
  
  
# 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を作る
- ノリでいける