RailsアプリをEC2からECS/Fargate構成に移行してホストする【HTTPS/固定ドメイン編】

# はじめに

当記事は、【ECS準備編】【ECS起動編】からの続編です。

https://qiita.com/Shuhei_Nakada/items/9e4c51bf9ae59f0b1a2b

https://qiita.com/Shuhei_Nakada/items/247d6f1781d6a3765482

まだ、お読みでない方は先にそちらからご覧ください。



# 使用技術

* ECS/Fargate(blue/greenデプロイメント)
* ELB(ALB)
* Rails6


# 作業内容

1. ドメインの取得
2. ACMの取得
3. ロードバランサーの編集
4. Railsのproduction.rbの編集
5. Route53の設定
6. ECSサービスの更新


# 1. ドメインの取得

現状は、AWS側で自動生成されたDNS名でアクセスできます。

`ALB名-ランダムな数字.リージョン名.サービス名.amazonaws.com`

提供しているサービスとは関係のない名称なので
自分でドメインを作成していきましょう。

例）
`xxxshop.com`
`foodccc.jp`

こういったドメイン名は、レジストラという事業者から購入できます。

お名前.comが有名ですが、AWSのRoute53からも購入できますので
当記事では`Route53`を利用します。

それでは、AWSサービス一覧からRoute53を検索して移動します。

![スクリーンショット 2021-12-14 12.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/a62f0aaa-180c-21e7-d886-4adf6d26a2f2.png)

ドメイン画面に移動して`ドメインの登録`を押します。

![スクリーンショット 2021-12-14 12.25.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/4d17d58e-516b-1014-092d-80d9950b6a8c.png)

まずは、入力フォームに任意のドメイン名を入れます。
その隣にプルダウンメニューで`.com`や`.jp`などが選べます。
選択後、チェックを押して他ドメインとの重複がないか調べてもらいます。

ステータスが使用可能となれば購入できますので
アクション下の`カートに入れる`をクリックします。

すると、右側にショッピングカートが出てきますので、
使用する年数を決めます。

最後に続行ボタンを押します。

![スクリーンショット 2021-12-14 12.29.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/36b36913-98fe-5f27-6abd-2db5345bc48e.png)

次のページは、個人情報の入力画面となります。

メールアドレスなどに間違えがないように入力してください。

![スクリーンショット 2021-12-14 12.36.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/709361ea-b100-b69b-ae31-9b36bad1779a.png)

もし、存在しないメールアドレスだと以下のような忠告がAWSから出されます。

![スクリーンショット 2021-12-14 12.38.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/52872a05-4612-5285-7f1c-760a65b38fb7.png)

最終確認画面で、AWS規約にチェックを入れて、`注文を完了`を押したら購入できます。

![スクリーンショット 2021-12-14 12.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/7407c6d9-4601-4d2c-3afb-a27b82cdf53b.png)



# 2. ACMの取得

続いて、AWS版の証明書となるACMを取得します。

接続先への通信をSSLで暗号化するには、
接続先に`秘密鍵`と`証明書`が必要です。

証明書は、本来は第三者機関の認証局が発行します。
ですが、AWSではACMという機能で無料で作れます。

今回はコンテナへの仲介役としてALBが存在しますので
同ALBに証明書を持たせる形になります。

それでは、まずACMを取得していきましょう。

AWSサービス一覧からacmを選択します。

![スクリーンショット 2021-12-14 13.41.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/fe8f7457-12b3-4371-9fc3-6a745b886fa7.png)

`リクエスト`を押します。

![スクリーンショット 2021-12-14 13.41.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/f498bdcb-68ca-2972-faa7-3280159bed84.png)

`パブリック証明書をリクエスト`で次に進みます。

![スクリーンショット 2021-12-14 13.42.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/1a914c1c-36ca-bf14-97cf-617e007b67e7.png)

完全修飾ドメイン名は、先ほど取得したドメインを入力します。

検証方法はDNS検証を選択します。

最後に`リクエスト`を押します。

![スクリーンショット 2021-12-14 13.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/5ed95465-571c-5645-0f56-619038d3d13c.png)

ステータスが`発行済み`になったら完了です。

![スクリーンショット 2021-12-14 13.49.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/cc12ca70-0e9e-67f2-d6c6-a7a4c39132e7.png)



# 3. ロードバランサーの編集

現在、blue/greenデプロイメントの設計上で、ALBのリスナーには
・　HTTPポート(80)
・　カスタムポート(10080)
の２つが設定されています。

そこにHTTPSポート(443)を追加します。

更に、HTTPポート(80)にはルールを指定して
HTTPSポート(443)にリダイレクトする設定を行います。

では、実装を始めましょう。

まずは、EC2画面から
サイドバーのロードバランサー　→ 対象ALBをチェック　→ リスナーのタブ　→ 
`リスナーの追加`をクリックします。

![スクリーンショット 2021-12-14 14.03.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/c0fc5117-46c7-3893-8c15-25fd25ce8a26.png)

リスナー追加画面に移動したら、
`HTTPSプロトコル`の`443ポート`として、
`blueターゲットグループ`を指定します。

SSL証明書は、先ほどACMで作成したものを設定しましょう。

最後に`リスナーの追加`をクリックします。

これで、HTTPS(443)のリスナーがALBに新しく登録されました。

![スクリーンショット 2021-12-14 14.09.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/99cd3032-4976-b87a-9da7-ad311d033aeb.png)

続いて、既存のHTTP（80）のリスナーに個別ルールを指定します。

まず、対象ALBのリスナータブに戻って、
`ルールの表示/編集`をクリックします。

![スクリーンショット 2021-12-14 14.20.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/887258d0-1eae-288b-62d0-c9314504df1c.png)

そこで新しく個別ルールの挿入していきましょう。

条件は、`パスが/*と一致するなら`　→ `HTTPS（443）にリダイレクトする`　というものです。

*(ワイルドカード)は全てのパスとなるので、必然的にHTTP(80)にアクセスしたユーザーは
無条件でHTTPS（443）にリダイレクトされる意味になります。

![スクリーンショット 2021-12-14 14.30.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/a28f060e-e1e1-bad8-006a-67c1d441da6b.png)



# 4. Railsのproduction.rbの編集

続いて、Rails側のコード変更です。

ここでは、`config.force_ssl = true`をコメントインしています。
これにより、Railsが強制的にHTTPS通信を求める設定になります。

ただし、このままではALBのヘルスチェックはHTTP（80）としているので、
上手くパスしてくれません。

そのため、`追加コードとして、ELB(ALB)のヘルスチェックに限っては
例外的にSSLを強制するコードは適用しない`とする設定を行っています。

これは、下記記事を参考にさせて頂きました。
(私のコードはrubocopで自動修正したものです。)

https://zenn.dev/machamp/articles/alb-rails-ssl


```ruby:config/environments/production.rb
require 'active_support/core_ext/integer/time'

Rails.application.configure do

--省略--

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true
  # ELBヘルスチェックは例外として80->443のリダイレクトはしない設定
  config.ssl_options = { redirect: { exclude: ->(request) { request.env['HTTP_USER_AGENT'].include?('ELB-HealthChecker') } } }

--省略--

end

```



# 5. Route53の設定

続いて、AWS版のDNSサーバーであるRoute53の設定です。

ここでは、Aレコードのエイリアス機能を使用します。

それによって、ドメイン名でアクセスしてきたユーザーを
ALBに向けることができ、最終的に閲覧してほしいRailsコンテナに行き着きます。

**`以前インフラの補足：参考まで`**
私の前インフラ環境では、
EC2は、インスタンス起動時に変動してしまうパブリックアドレスを
ElasticIPで固定化し、Route53に名前解決を担ってもらっていました。

ECSでは、コンテナ生成時にIPアドレスが割り振られますので
固定化はできていませんが、Route53はAレコードのエイリアスを用いて
ALBに向けているので、内部で上手く処理してくれる…と推測しています。

では、実装していきましょう。

まず、Route53画面のホストゾーンを押します。

Route53でドメイン取得していれば、デフォルトでホストゾーンが存在するはずです。
もし他のレジストラでドメインを取得した場合などは、ホストゾーンを自分で作りましょう。

https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/CreatingHostedZone.html


![スクリーンショット 2021-12-14 15.29.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/5765483d-e4cf-23dd-ebd1-de41657efe94.png)

`取得したドメイン`をクリックします。

![スクリーンショット 2021-12-14 15.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/8008d7d2-7de7-e0c8-e414-77a589f21300.png)

`レコードを作成`をクリックします。

![スクリーンショット 2021-12-14 15.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/c77ac3e4-e7e7-586a-84cb-a6b828066635.png)

各種ルーティングポリシーの中から、`シンプルルーティング`を選択します。

![スクリーンショット 2021-12-14 15.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/3d1530b8-b3e8-ddf6-891d-d07c7758eae6.png)

`シンプルなレコードを定義`をクリックします。

![スクリーンショット 2021-12-14 15.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/e12bdb3a-b054-4ece-de19-f5850beb7349.png)

レコード名は、`無記入`でも良いです。
必要であれば、ホスト名を追加してください。

レコードタイプは、`Aレコード`を選択します。

ルーティング先は、`ALB（エイリアス）`を選択して
リージョンは`東京`とした上で
`自分のALB`を選択してください。

最後に`シンプルなレコードを定義`を押します。

![スクリーンショット 2021-12-14 15.40.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/0991bcb9-a517-fb3d-b41e-cfc6bf3fd2f7.png)

元の画面に戻りますので、`レコードを作成`をクリックして
レコードを完成させましょう。

![スクリーンショット 2021-12-14 15.44.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/41a653ab-5ccf-7cbd-6a36-ab85e3ee8029.png)



# 6. ECSサービスの更新

これで、最後の作業です。

現在、ECSと連携しているALBは
`・プロダクションリスナー：　HTTP(80)`
`・テストリスナー：　カスタムTCP(10080)`
としています。

そこを
`・プロダクションリスナー：　HTTPS（443）`
`・テストリスナー：カスタムTCP（10080）`
に変更します。

しかし、ECSと連携しているALBのリスナー設定は
サービスの更新では対応できないようなので
新しく別のサービスを起動して対応します。

新しいサービスが正常に起動できたことを確認後、
古い方のサービスを削除します。

注意すべき点は、新しいサービスを起動する前に
ALBのプロダクションリスナーとテストリスナーのデフォルト設定を
blueとgreenに正しく分けておく工夫が必要です。

では、実装していきましょう。

まず、EC2の画面から
サイドバーのロードバランサー　→ 対象ALBのチェック　→ リスナーのタブ　から
現況を確認します。

ルールの列にある転送先に注目すると、
`HTTPS:443`と`HTTP:10080`のターゲットグループがgreenで同じになっていますので
このケースでは正しくありません。

blue/greenデプロイメントで何度かサービスの更新をしていると
デフォルトの転送先が意図しないものに切り替わってしまっている可能性がありますので
もし同じ現象になっている方は手動で変更します。

今回のケースでは、HTTPS：443が`blue`ではなく`green`となってしまっているので
ここを`blue`に変更していきます。
(HTTP:10080がblueとなっていても同じやり方でgreenに直せます。)

それでは、`対象リスナーをチェックして、編集をクリックします。`

![スクリーンショット 2021-12-14 18.28.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/eb81921a-bf5f-a58f-b3b4-2cd29fa0f548.png)

リスナー編集画面に移動したら、現在設定されている転送先を
`ゴミ箱のアイコン`を押して削除します。

![スクリーンショット 2021-12-15 7.46.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/22b7e56a-280a-48d5-c21b-a54e8d84ec5b.png)


その後、`アクションの追加`を押して
`転送先`を選択します。

![スクリーンショット 2021-12-14 18.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/fb5c2c5c-6505-2269-270f-8a5d3a97d18f.png)

続いて、`blueターゲットグループ`をプルダウンで選択して
`更新`を押します。

これで、リスナーを
・HTTPS：443 は　blueターゲットグループ
・HTTP：10080 は　greenターゲットグループ
と整備ができました。

![スクリーンショット 2021-12-14 18.35.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/a58d5c74-5671-9605-0a0a-5bc072bbc5ca.png)

ここからECSサービスを新規作成します。
`更新`ではなく、`作成`を押します。

![スクリーンショット 2021-12-14 18.40.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/4901feb1-9116-11f9-5e07-f307b9b34716.png)

設定内容は、`ECS起動編`で入力したものと同じです。

![スクリーンショット 2021-12-14 18.43.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/dcaac37b-8ba6-f420-4f04-8f013d355355.png)

ここも設定内容は、`ECS起動編`で入力したものと同じです。

![スクリーンショット 2021-12-14 18.51.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/87374852-13d9-7662-e3bf-8de970b7a689.png)

ここだけ違いますので、注意します。

プロダクションリスナーはHTTPS：443とします。
（前回はHTTP：80としていました。）

テストリスナーはHTTP：10080です。

ターゲットグループは、blue-tg, green-tgの順に登録します。

![スクリーンショット 2021-12-14 18.55.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/4230a834-dbee-1d56-ed7d-dd7d8107154c.png)

ここも設定内容は、`ECS起動編`で入力したものと同じです。

![スクリーンショット 2021-12-14 19.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/49313942-22a0-5af1-016e-40009b8616af.png)

ここも設定内容は、`ECS起動編`で入力したものと同じです。

![スクリーンショット 2021-12-14 19.03.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/060a159d-4b54-6543-c806-68b60630e1eb.png)

`サービスの作成`を押して、タスクの起動を待ちましょう。

![スクリーンショット 2021-12-14 19.04.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/3c59f571-a405-8512-0d19-a03453a7e67f.png)

前回と同様に、ECSサービスのイベントタブより
`has reached a steady state.`
が確認できれば、成功しています。

![スクリーンショット 2021-12-14 19.32.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/5e87b7f0-bedb-20f7-4795-067bb3e000bc.png)

これで新しいサービスからタスクを生成できました。

現状は古いサービスも残っているかと思いますので、
無駄に料金コストがかからないように削除しましょう。

![スクリーンショット 2021-12-15 7.52.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/fe827392-35b6-72c3-93b5-85b3e277e7a2.png)



# 続編

https://qiita.com/Shuhei_Nakada/items/2e3a5afde0bd215b334d



# 終わりに

ふと、疑問に思ったけどterraformって、GUIで作成したもの全てを
コードから構築できるんだろうか？

細かい部分だけ、部分的にGUIでしないといけなかったら
整理するの大変に感じそう…

今回も長い記事になってしまいましたが、最後までお読みいただき、
ありがとうございました！