Serverless Framework を用いて、API Gateway の カスタムドメインを設定する方法を調査しました。
目次
背景
AWS APIGatewayのエンドポイントは次のような形式になっています。
https://<API-ID>.execute-api.<REGION-ID>.amazonaws.com/<STAGE-NAME>/…
APIGateway + Lambdaで構成されたようなサービスを開発していて、サービスをいったん削除してデプロイし直す、といったことをすると、<API-ID>の部分が変わってしまいます。
外部のサービスと連携したりしている場合、設定していたエンドポイントが変わることになり、再度設定が必要なため不便です。
今回はデプロイし直してもエンドポイントが変わらないようにするための調査を行ったので、一例を紹介します。
環境
Lambda 関数とレイヤーのデプロイに Serverless Framework を使用しています。
Serverless Framework はNode.jsで作られたCLIツールで AWS Lambda、Azure Functions、Google Cloud Functions等の Serverless Applicationを構成管理、デプロイするためのツールです。
また、Lambda関数のランタイムとしてGo言語を、goのビルドにmakeを使用しました。
各ツールのインストールや環境構築については割愛します。
serverless-domain-manager
Serverless Framework のプラグイン serverless-domain-manager を使用します。
READMEに従ってインストールを行います。
$ npm install serverless-domain-manager --save-dev
また、前提条件としてデプロイを行うIAMロールに必要となる権限があるので、その付与を行っておきます。
https://github.com/amplify-education/serverless-domain-manager/blob/master/README.md#prerequisites
独自ドメイン取得と設定
次に独自ドメインの取得と設定を行います。
- 独自ドメイン取得
Freenom というサービスでsome-service.cfという無料のドメインを取得しました。 - AWS Route53でホストゾーン作成
ドメイン名と同じ、some-service.cfというホストゾーンを作成しています。
またホストゾーン作成時に割り当てられる Name Server を Freenom で作成したドメインに設定しておきます。 - AWS Certificate ManagerでSSL証明書
手順の詳細は、次の記事が参考になりました。
無料の独自ドメインとAWS Certificate Managerを使ったお手軽SSL対応
プロジェクトの作成
Serverless Framework のコマンドでプロジェクトのテンプレートを作成します。
$ sls create --template aws-go
モジュール名は testendpoint としました。
$ go mod init testendpoint
ディレクトリ構成はテンプレートのままですが、以下のようになります。
./
│ .gitignore/
│ go.mod
│ go.sum
│ Makefile
│ serverless.yml
│
├─.serverless/
│
├─hello/
│ main.go
│
└─world/
main.go
serverless.yml でリージョンを us-east-2 に設定して、ビルド(make)とデプロイ(sls deploy)を行ってみます。
デプロイした API Gateway のエンドポイントを確認して、ブラウザからアクセスするとLambda関数から返却されたメッセージが確認できます。

サービスを削除(sls remove)して、再度デプロイを行うと画像の API ID の部分が変わるため、毎回エンドポイントの確認が必要になります。
serverless.yml の編集
事前に用意していたドメイン some-service.cf でアクセスできるようにするため、serverless.yml へ以下の内容を追記します。
plugins の項目に serverless-domain-manager を指定して、プラグインの使用を宣言します。
custom の customDomain の各項目で使用するドメインについての設定を行います。
plugins:
- serverless-domain-manager
custom:
customDomain:
domainName: 'some-service.cf'
basePath: ''
certificateName: 'some-service.cf'
certificateArn: 'arn:aws:acm:<region>:<account>:certificate/01234567-0123-0123-0123-01234567890'
endpointType: 'regional'
stage: ${self:provider.stage}
createRoute53Record: true
明記している項目以外にも設定できる項目はありますが、記載している項目の内容は次の通りです。
- domainName
APIGatewayとRoute53で作成されるドメイン名になり、必ず設定する必要があります。 - basePath
エンドポイントに付加するベースパスです。 - certificateName
AWS Certificate Manager で作成した証明書の名前です。
指定しない場合はドメイン名に最も近い名前が選ばれる、とserverless-domain-managerのREADMEにありますが、明示的にsome-service.cfとしています。 - certificateArn
AWS Certificate Manager で作成した証明書のARNです。
AWS マネジメントコンソールのCertificate Managerの画面等から確認することができます。 - endpointType
デフォルトはedgeとなっていますが、今回はus-east-2へデプロイしているので、regionalとしています。
CloudFrontを介してedgeで配信する場合は、リージョンをus-east-1にする必要があるため注意が必要です。 - stage
デプロイされるドメインのステージです。 - createRoute53Record
Route53 を使用してマッピングされたレコードを作成するため true としています。
DNS に Route53 を使用しない場合は false とします。
全ての項目のデフォルト値と詳細説明はREADMEの以下のリンクから確認することができます。
https://github.com/amplify-education/serverless-domain-manager/blob/master/README.md#installing
デプロイ
ここまで設定したら、デプロイ(sls deploy)を行う前に、sls create_domain でRoute53レコードを作成します。
sls create_domain 後、デプロイして、エンドポイント https://some-service.cf/hello へアクセスしてみると、先の動作確認と同じメッセージが確認できました。

これで、何度デプロイをし直してもエンドポイントは変わらない状態になりました。
また、sls create_domain で作成したレコードは sls delete_domain で削除することができます。
まとめ
今回、実際に開発を進めているプロジェクトで API Gateway のエンドポイントを固定化したい需要があって調査を行ったのですが、デプロイし直すたびに連携している外部サービスへ登録しているURL(エンドポイント)を設定し直す必要がなくなり、人手による手間とミスを削減できたかと思います。