Node.js
AWS
serverless

Serverless(node.js)で独自ドメインSSLの適用方法

前回書いた記事ではS3に配置した静的コンテンツをSSLの独自ドメインで公開する方法について備忘しましたが、

今回はServerless Frameworkを使って、
独自ドメインの適用の仕方について調べて試した内容について備忘します。
前回同様、 ドメイン取得後数年寝かし続けていたドメイン koshikawa.net で検証しました。

ゴール

  • serverless でデプロイするwebサイトに独自ドメインを適用する。
  • デプロイ時に指定する環境毎にサブドメインを変える。
    • sls deploy --stage prd なら koshikawa.net に反映される
    • sls deploy --stage dev なら dev.koshikawa.net に反映される

結果はこんな感じ

本番 (koshikawa.net) prdとコンテンツは同じ  本番 (prd.koshikawa.net) 開発 (dev.koshikawa.net)
koshikawa.net.png prd.koshikawa.net.png dev.koshikawa.net.png

やり方

参考サイト

事前にやっておくこと

  • 個別ドメインをRoute53でゾーン管理しておく、ACMの証明書を発行しておく。
  • S3に deploymentBucket を作っておく。
  • コマンド実行するユーザに必要な権限を付与しておく。(serverless-domain-manager の README.mdに記載あり)

書いたソース

index.js
'use strict';

const serverless = require('serverless-http');
const express = require('express');
const app = express();

app.get('/', function (req, res) {
    res.send('Hello, world! on Serverless Framework');
});

app.get('/goodbye', function (req, res) {
    res.send('Goodbye, world! on Serverless Framework');
});

module.exports.handler = serverless(app);

serverless.yml

serverless.yml
# serverless.yml

service: ${self:custom.name}

plugins:
  - serverless-offline
  - serverless-domain-manager

provider:
  name: aws
  region: ap-northeast-1
  runtime: nodejs8.10
  stage: ${opt:stage, 'dev'}
  deploymentBucket:
    name: ${self:custom.name}.${self:provider.region}.deploys

custom:
  name: koshikawanet
  customDomain:
    domainName: '${self:provider.stage}.koshikawa.net'
    certificateName: '*.koshikawa.net'
    basePath: ''
    stage: ${self:provider.stage}
    createRoute53Record: true

functions:
  hello:
    handler: index.handler
    events:
      - http: GET /
  goodbye:
    handler: index.handler
    events:
      - http: GET /goodbye

deploy前にcreate_domain

sls offline start でローカルで動作確認できたら、
sls create_domainコマンドにて以下を実行します。
・API Gatewayにカスタムドメイン作成および
・Route53に対して生成されたCloudFrontのFQDNのAliasを貼る

開発 (--stage devは省略可)

$ sls create_domain --stage dev
...
Serverless: 'dev.koshikawa.net' was created/updated. New domains may take up to 40 minutes to be initialized.

本番

$ sls create_domain --stage prd
...
Serverless: 'prd.koshikawa.net' was created/updated. New domains may take up to 40 minutes to be initialized.

※ 手元の環境では反映時間に40分もかからず10分くらいで反映されました。
serverless.comの記事にも10分〜20分くらいって書いてあります。

1分待たずdeployを行ったところ、カスタムドメインに対してBase Path Mappingsの設定がされず、
{"message":"Forbidden"}が返却される事象となり、作り直しを余儀なくされたので、
余裕をもって行いましょう。

deploy

開発 (--stage devは省略可)

$ sls create_domain --stage dev
...
Service Information
service: koshikawanet
stage: dev
region: ap-northeast-1
stack: koshikawanet-dev
api keys:
  None
endpoints:
  GET - https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev
  GET - https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye
functions:
  hello: koshikawanet-dev-hello
  goodbye: koshikawanet-dev-goodbye
Serverless Domain Manager Summary
Domain Name
  dev.koshikawa.net
Distribution Domain Name
  xxxxxxx.cloudfront.net
Serverless: Invoke aws:deploy:finalize

これで https://dev.koshikawa.net にデプロイできました。

本番

$ sls create_domain --stage prd
...
Service Information
service: koshikawanet
stage: prd
region: ap-northeast-1
stack: koshikawanet-prd
api keys:
  None
endpoints:
  GET - https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prd
  GET - https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prd/goodbye
functions:
  hello: koshikawanet-prd-hello
  goodbye: koshikawanet-prd-goodbye
Serverless Domain Manager Summary
Domain Name
  prd.koshikawa.net
Distribution Domain Name
  xxxxxxx.cloudfront.net

これで https://prd.koshikawa.net にデプロイできました。

本番サイト koshikawa.net に prd 環境のAPIをマッピングする

prd.koshikawa.netは本番サイトとしてドメインに環境名が入っていてかっこ悪いので、
koshikawa.netにprdと同じ内容が反映されるように設定します。

  • API Gatewayのコンソール画面で カスタムドメイン koshikawa.net を作ります。
    • Base Path Mappingsの設定でprd環境でデプロイしたAPIを指定します。
      イメージ:
      koshikawa.net-apigateway1.png
  • カスタムドメイン作成後にCloudFrontのFQDNが決まるので、Route53のゾーン設定画面にてkoshikawa.netのAレコードとしてCloudFrontのFQDNをAliasとして設定します。
    API Gatewayコンソール上でのCloudFrontのFQDNの表示例:
    koshikawa.net-apigateway2.png

参考: もちろんコマンドでも設定可能

API Gateway でリージョン別 API 用のカスタムドメイン名をセットアップする

base-path-mapping の指定例:

aws apigateway create-base-path-mapping \
    --domain-name 'koshikawa.net' \
    --base-path '' \
    --rest-api-id xxx \
    --stage 'prd'

現場からは以上です。
寝かしていたドメインの育て方については依然検討中です。