LoginSignup
61
69

More than 3 years have passed since last update.

Vue.js + AWS S3でのHTTPS対応とCircle CIでの自動デプロイ手順

Last updated at Posted at 2019-12-14

Vue.js で作ったSPAを静的サイトとしてAWS S3(+ CloudFront)からホスティングすれば、ランニングコストを低く抑えられるのでオススメです。アクセス数にもよりますが、個人のウェブサイトなどであれば100円程度/月で済んだりします。

今回はそんな Vue.js の AWS S3 へのデプロイ手順と、CloudFront を使った独自ドメイン + HTTPS 対応方法、さらに CircleCI を使った CI/CD の導入までザッと整理します。

最終的な本番環境イメージ

最終的な本番環境の構成イメージは次のとおりです。

vue_s3_cloudfront_circleci.jpg

Vue.js アプリの準備 (前提)

前提として、ここでは Vue.js アプリのデプロイ手順を扱います。

Vue.js の基礎知識については、過去の記事をご覧ください。

1. AWS S3 へのデプロイ手順

まずは単純な AWS S3 へのデプロイ手順です。

S3の準備

本番サーバとなるS3のセットアップです。

バケット新規作成

S3 のコンソールからバケットを新規作成します。

「バケット」はドメインと同じようなネーミングにしておくと分かりやすいです。「ブロックパブリックアクセス」は静的サイトとして公開するので全てオフにします。

静的サイトとして使う

バケット作成後、プロパティタブから「静的ウェブサイトホスティング」を選択して、静的サイトとして使えるようにします。

スクリーンショット 2019-11-23 12.27.14.png

設定項目は次のとおりです。

  • インデックスドキュメント(必須): index.html
  • エラードキュメント(必須): error.html

バケットポリシーの追加

アクセス権限タブから「バケットポリシー」を選択し、次のようにJSONコードでポリシーを追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
    ]
}

S3へのデプロイ

これで最低限の本番環境は整ったので、開発コンソールで本番用コードをビルドします。

npm run build

生成される dist ディレクトリを先ほど作った S3 にアップします。

そしてブラウザから次のURLを叩けば、 Vue.js の静的サイトが表示されます。

<bucket-name>.s3-website-<AWS-region>.amazonaws.com/dist

例えば、バケット名が「mybucket」、リージョンが「東京(ap-northeast-1)」の場合は、S3のURLは次のようになります。

mybucket.s3-website-ap-northeast-1.amazonaws.com/dist

これでデプロイ自体は完了です。

2. CloudFront での独自ドメイン + HTTPS化手順

次にデプロイしたS3の静的サイトを、独自ドメイン + HTTPS でアクセスできるようにします。

これは Route53 + AWS Certificate Manager + CloudFront で実現できます。

Route53 独自ドメイン登録

ケース1: Route53 で新規取得

コンソールの登録済みドメインページの「ドメインの登録」から独自ドメインを購入します。

ケース2: Route53 のサブドメインを使う

Route53 に登録済のドメインのサブドメインを使う場合は、必要な追加設定はありません。

ケース3: 他社ドメインを Route 53 に登録

他社で取得したドメインを使う場合、「Route53」と「他社ネームサーバ」のそれぞれで設定が必要です。

Route 53 での設定

コンソールのホストゾーンページの「ホストゾーンの作成」から他社取得ドメインを登録します。

タイプ「NS」と「SOA」がデフォルトで自動生成されます。「NS」は他社ネームサーバに入力する情報です(次のような4つの値)。

ns-2xx.awsdns-26.com.
ns-1xxx.awsdns-36.org.
ns-1xxx.awsdns-33.co.uk.
ns-8xx.awsdns-40.net.

他社ネームサーバでの設定

Route53 で自動生成された NS レコードの値を、他社ネームサーバ1〜4として登録します。

AWS Certificate Manager で証明書登録

AWS Certificate Manager のコンソールにて、Route53 に登録したドメインの証明書を取得します。

(注意)CloudFront で HTTPS 化をする場合、必ず「US EAST」で登録しないといけません。東京リージョンを選ばないように注意しましょう。

*.独自ドメイン と設定すれば、サブドメイン分もまとめて登録できます。

証明書の発行が完了すると、DNS 設定が書かれたCSVファイルをダウンロードできます。

Route53 に CNAME 追加

ダウンロードした DNS 設定の内容にしたがって、Route53 に CNAME を追加します。

ドメインのホストゾーン画面から「レコード設定の作成」を選択し、次のように設定します。

  • 名前: DNS 設定の Record Name(例 _3560a31fe01xxxxxxxxxx
  • タイプ: CNAME
  • 値: DNS 設定の Record Value(例 _xxx.acm-validations.aws.

(僕の環境下では、追加した CNAME はすぐに反映されました。)

CloudFront の設定

ここまで来て、やっと CloudFront の設定ができます。

CloudFront のコンソールからディストリビューションを追加します。「Web」を選択して、次のように設定していきます。

Origin Settings

  • Origin Domain Name: 本番 S3 バケットを選択
  • 以外、デフォルト

Default Cache Behavior Settings

  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • 以外、デフォルト

Distribution Settings

  • Alternate Domain Names (CNAMEs): 本番で利用するドメイン
  • SSL Certificat: Custom SSL Certificate(ACM で作った証明書を選択)
  • Default Root Object: dist/index.html
  • 以外、デフォルト

以上の内容でディストリビューションを作成します。

作成後、CloudFront ディストリビューションの「Domain Name」をコピーします。

Route53 に CloudFront のエンドポイントを追加

Route53 ホストゾーンの「レコードセットの追加」から、先ほどコピーした「Domain Name」をAレコードとして追加します。

  • 名前: 独自ドメイン(もしくはサブドメイン)
  • タイプ: A
  • 値: CloudFront ディストリビューションの「Domain Name」

ブラウザから独自ドメインを叩いて、S3の静的サイトがHTTPSで表示できればOKです。

403, 404エラーに対応

Failed to load resource: the server responded with a status of 403

vue-router などで URL が動的に変わる場合、何も設定をしていないとブラウザのコンソール上でこういったエラーが出てしまいます。

例えば、コンタクトページ /contact を Vue.js SPA 内で作った場合、S3上に dist/contact.html という実際のファイルがないので、このようなエラーが出ると考えられます。

解決方法

CloudFront でエラーページの設定すれば、このエラーを解決できます。

CloudFronnt ディストリビューションの「Error Pages」タブからカスタムエラーレスポンスを作成します。

  • HTTP Error Code: 403, 404(2回に分けて作成)
  • Customize Error Response: Yes
  • Response Page Path: /
  • HTTP Response Code: 200 OK

3. CircleCI での CI/CD 導入手順

コードを更新するたびに手作業でテストして、ビルドして、デプロイするのは大変なので、CircleCI で一連の作業を全て自動化します。

事前準備: アカウント連携

アカウントを持っていない場合は、CircleCI のホームページからサインアップして、自身の GitHub アカウントと連携させます。

IAM ポリシーの追加

CircleCI に付与する S3 のファイル更新権限を準備します。

IAM のコンソール から「ポリシーの作成」を選択し、次の JSON でポリシー内容を規定します。(<bucketname> は各自のバケット名)

{
   "Version": "2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "s3:ListBucket",
            "s3:GetBucketLocation"
         ],
         "Resource":"arn:aws:s3:::<bucketname>"
      },
      {
         "Effect":"Allow",
         "Action":[
            "s3:PutObject",
            "s3:PutObjectAcl",
            "s3:DeleteObject"
         ],
         "Resource":"arn:aws:s3:::<bucketname>/*"
      }
   ]
}

ポリシー作成後に表示される「アクセスキーID」と「シークレットアクセスキー」をコピーしておきます。

スクリーンショット 2019-11-22 21.39.28.png

CircleCI の権限設定

CircleCI プロジェクトの設定画面「AWS Permissions」で、先ほど生成した「アクセスキーID」と「シークレットアクセスキー」を登録します。

スクリーンショット 2019-11-22 21.39.16.png

CircleCI の CI/CD 設定

プロジェクトのルートパスに .circleci/config.yml を作成し、CircleCI の CI/CD 設定を書きます。

AWS S3 に自動デプロイする設定は次のとおりです。

(注意)YAMLファイルではインデントが重要です

.circleci/config.yml
version: 2.1

orbs:
  aws-s3: circleci/aws-s3@1.0.11

executors:
  default:
    docker:
      - image: circleci/node:10.17.0
      - image: circleci/python:2.7

commands:
  npm_install:
    steps:
      - restore_cache:
          key: dependency-cache-{{ checksum "package.json" }}
      - run: npm install
      - save_cache:
          key: dependency-cache-{{ checksum "package.json" }}
          paths:
              - node_modules

jobs:
  build:
    executor: default
    working_directory: ~/repo
    steps:
      - checkout
      - npm_install
      - run: npm run test

  deploy:
    executor: default
    working_directory: ~/repo
    steps:
      - checkout
      - npm_install
      - run:
          name: build
          command: API_ID=$API_ID API_TOKEN=$API_TOKEN npm run build
      - aws-s3/sync:
          from: dist
          to: s3://mybucket/dist
          overwrite: true

workflows:
  version: 2
  continuous-deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master

全般

orbs は、デプロイに必要なコマンドなどの設定がまとめられたパッケージで、ここでは circleci/aws-s3@1.0.11 を使っています。

コマンドの実行環境には dockercircleci/node:10.17.0circleci/python:2.7 を使っています。

jobsbuild プロセス(CI)と deploy プロセス(CD)を定義し、workflows で処理の順番を指定しています。

commands では、各プロセスで実行するコマンドの実行内容を定義しています。

CI (継続的インデグレーション)

build プロセスの部分です。npm_install して npm run test するだけの単純な設定です。

これで GitHub に push されたコードに対して自動テストが実行されます。(マージ前のブランチ画面でテストが成功したか確認できます。)

CD (継続的デリバリー)

deploy プロセスの部分です。

まず、npm_install し、npm run build で本番用コード dist を生成します。

そのビルドしたコードを aws-s3/sync で S3 にアップロードします。

workflowsfilters: branches: only: master を指定しているので、master ブランチへのマージのみをトリガーとして、この deploy プロセスが走ります。

環境変数の設定

.circleci/config.yml で使う環境変数は、CircleCI の管理画面(プロジェクトページ > Environment Variables)で定義します。

.env ファイルの取り扱い

Vue.js アプリで使う環境変数は、.env ファイル内に VUE_APP_ の接頭辞で定義します(公式ドキュメントはこちら)。

この .env ファイルには API キーなどの機密情報が含まれるので、通常は .gitignore で git の管理対象から外します。

一方、CircleCI では GitHub から本番用コードをビルドするので、.env がないと問題が発生してしまいます。

これを回避するために、npm run build 実行時に CircleCI の管理画面で定義した環境変数を渡してあげます。

例えば、API_IDAPI_TOKEN という環境変数を定義した場合は、次のようになります。

command: API_ID=$API_ID API_TOKEN=$API_TOKEN npm run build

なお、渡された環境変数を Vue.js 内で使うには、webpack.config.jswebpack.DefinePlugin を追加しないといけません。(これについての詳細は、今後別記事にまとめます。)

※ もっと効率的な環境変数の渡し方があれば教えていただきたいです!

デプロイ動作確認

コードを変更して GitHub にプッシュし、master ブランチにマージさせます。

そのマージをトリガーに処理が走れば、CircleCI の管理画面にステータスが表示されます。

deploy プロセスまで完了したら、変更が本番環境に反映されます。

本番ファイル更新がすぐに反映されない?

S3 の本番ファイルを更新しても、CloudFront のエッジサーバ上にキャッシュが残っていると、その更新は即座に反映されません。

CloudFront の Invalidation を実行すれば、このキャッシュをリセットできます。より詳しい内容は以下の記事でまとめています。

References

61
69
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
61
69