今まで勤めていた会社ではAWSやGCP等の「今どきな」クラウドを全く触る機会がなかったため、この辺りの知識がかなり遅れています・・・
未だにサーバを建てるといえば、VPS契約してyumでhttpサーバやmakeコマンドでMySQLをインストールするとか、そんな次元の人間です。
転職先の会社ではAWSを利用しており、面談でも「新しい技術使っていいよ、コンテナとかサーバーレスとか」みたいな話が出たので、まずは簡単なWebアプリをAWS Fargateで動かすことを目標に作業を行ってみました。
これはAWS未経験の中年エンジニアが奮闘した記録である(要するに参考にできるような記事ではない)
環境について
以下の環境で実施しています
・Intel Mac 2019
・Dockerインストール済み
・IDEはIntellij Idea
また、aws cliをインストールしておく必要があります
https://aws.amazon.com/jp/cli/
まずはKtorでWebアプリを作成する
といっても、Ktor Project Generatorでサンプルコード込みで作成してしまえばよいだけです・・・
https://start.ktor.io/
上記のサイトでスタートアッププロジェクトがZip形式でダウンロードできるので、適当な場所にダウンロードします。
Intellij Ideaで開く
Zipを展開した後、Intellij Ideaで開きます。自動でGradleの更新が動いて、いろいろなライブラリのダウンロードが開始されます。
ライブラリダウンロード後、とりあえず起動して動作を確認します

起動後、ブラウザで「http://0.0.0.0:8080」にアクセスれば、Hello woldが表示されるはずです

ひとまず、これで簡単なWebアプリの準備はできました
Ktorに準備されたタスクを実行してみる
Ktorを利用すると、Gradleにタスクがいくつか追加されます

それぞれのタスクの詳細については、以下を参照されたい
https://ktor.io/docs/docker.html
まずは「publishImageToLocalRegistry」を実行し、ローカルのDockerRegistryにイメージが登録されることを確認してみます
ローカルのDockerにImageを登録する
現在のローカルDocker Registryは以下のとおりです

プロジェクト内の「build.gradle.kts」に以下の設定を追加します
ktor {
docker {
localImageName.set("ktor-docker-fagate")
imageTag.set("0.0.1-preview")
}
}
Intellij Ideaから「publishImageToLocalRegistry」を実行します。
このタスクを実行すると、ローカルレジストリに作成したWebアプリのイメージが登録されます


この状態で下記コマンドを実行すると作成したイメージからコンテナが生成され、Hello Worldが表示されます
docker run -p 8080:8080 ktor-docker-fagate:0.0.1-preview
上記コマンド実行後、http://0.0.0.0:8080にアクセスするとHello worldが表示されます
AWS ECRを利用するまでの色々
Fargateに乗せるためのDockerイメージは、Amazon Elastic Container Registryを利用してみたいと思います。
AWSはアカウントのみ作った状態でまっさらなため、ユーザー作成からECR作成までやってみたいと思います
ユーザー作成
Identity and Access Management (IAM) から新規ユーザーを作成

ユーザーグループの設定画面
ユーザーグループがまだ存在しないので、作成をクリック

グループは以下のように設定
ポリシーはElasticConteinerRegistryのFullAccessを選択してみました

グループ作成後、ユーザー作成の画面に戻ってくるので、作成したグループを選択します

この次の画面でタグの設定になりますが、今回は何も設定せず次へ、確認画面の後、ユーザーが作成されます
ユーザー作成後、ユーザーID、シークレットキーが表示されるため両方ともメモしておきます(Docker ImageをPushするときの認証に利用します)

以上でユーザーの作成は終了です
Elastic Container Registryを作成
Amazon Elastic Container Registry のページにアクセス
画面右側に「リポジトリの作成 利用方法」というボタンがあるので、これをクリックするとリポジトリ作成画面に遷移できます。
リポジトリ名だけ設定し、画面下部のリポジトリ作成を実施しました

リポジトリが作成されました

Docker Imageを作成してECRにPushする
Push用イメージのビルド
マニュアルはこちら
https://ktor.io/docs/docker.html#manual
マニュアルを見ると、Docker Hub、Google Container RegistryにプッシュするときにはKtorにヘルパー関数的なものが準備されているそうですが、AWS用のものは見つかりませんでした(なんで?)
なので、手動でイメージをビルドし、プッシュします
プロジェクトルートにDockerfileを準備し、以下の内容を記載します
FROM gradle:7-jdk11 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle buildFatJar --no-daemon
FROM openjdk:11
EXPOSE 8080:8080
RUN mkdir /app
COPY --from=build /home/gradle/src/build/libs/*.jar /app/ktor-docker-sample.jar
ENTRYPOINT ["java","-jar","/app/ktor-docker-sample.jar"]
Macのターミナルでプロジェクトのルートディレクトリにcdコマンドで移動した後、以下のコマンドでイメージをビルドします
docker build -t kotlin-ktor-fargate .
認証情報の作成
ECRにイメージをプッシュする際に認証が必要となるため、事前に情報を作成しておきます
aws configure
対話式で設定を行うモードになるので、メモっておいたアクセスキー、シークレットアクセスキーを設定します

ECRにプッシュしてみる
マニュアルはこちら
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/docker-push-ecr-image.html
コマンドはこんな感じにしてみました
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin アカウントID.dkr.ecr.us-east-1.amazonaws.com
アカウントIDは画面右上のユーザー名をクリックすると確認できます

問題なければ、コマンド実行後に「Login Succeeded」が表示されます
次に以下のコマンドを実行し、タグ付とプッシュを行いました
docker tag プッシュ対象のイメージ アカウントID.dkr.ecr.us-east-1.amazonaws.com/kotlin-application:latest
docker push アカウントID.dkr.ecr.us-east-1.amazonaws.com/kotlin-application:latest
上記コマンドを実行すると、ECRにイメージがプッシュされたことが確認できるかと思います

Amazon Elastic Conteiner ServiceでWebアプリを稼働させる
ここまで来てやっと本題である「自作WebアプリをFargateで稼働させる」にたどり着きました・・・
以下の手順で設定していきます
Elastic Container Serviceの設定
Elastic Container Serviceのページにアクセスし、「今すぐ始める」をクリックします
下記のような設定画面になるため、customの設定ボタンをクリックします

コンテナ内では8080ポートでリクエストを受け付けているため、ポートマッピングの設定を行っています

下記画面のような状態で次へをクリック

サービスの定義の画面になります
以下のように設定して次へ

次のクラスターの設定はデフォルト設定で次へを選択しました
確認画面で作成を選択すると、色々と作成が始まる画面に切り替わります

Public IPを確認し、アクセスする
上記のジョブがすべて終わると「サービスの表示」がクリックできるようになるのでクリックします

遷移先の画面でタスクタブ内のタスクをクリック

ネットワーク内にパブリックIPがあるので、確認します

ブラウザから確認したパブリックIPにアクセスすれば、Hello World!の文字が表示されるはずです
8080ポートで待ち受けているため、そこだけ注意が必要です

ここまでの手順で、ひとまず自作のWebアプリがFargateを利用して公開できたことになります
お疲れさまでした!
後片付け
確認が取れたので後片付けを行います。(色々と課金が怖いので・・・)
赤枠内のボタンからクラスターの削除を行います

テキストボックス内にdelete meと入力して削除を行うと、削除が開始されます

ロググループの削除も行います
CloudWatch > ロググループから下記画面に遷移できます

ECRのレジストリも削除しておきます

以上で後片付けも終了です
以上
ということで、AWS全く知らないおじさんがFargateを利用して独自のWebアプリを動かしてみるお話でした
疲れた・・・ ブログ書きながら作業したら5時間くらいかかった・・・ しかも、アカウント作成までは一回練習した状態でそれだけ時間がかかりました。
一応動いたことは動いたけど、本番稼働に利用するにはまだまだ知識が足りない状態です
ただ、Ktor自体がマイクロサービスを意識しているのか、コンテナとかなり相性が良い印象を受けたので、今後なにかサービスを開発するときはKtor + Fargateの環境は全然アリだなと思いました