Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させる (JSUG勉強会 2019その9 Spring&AWS)
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Application Prototyping Solutions ArchitectFumihiko ShiroyamaSeptember 20, 2019Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させるJSUG 勉強会 2019 その9 Spring&AWS
View Slide
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.スライドURLhttp://bit.ly/2lW4MTT
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.⾃⼰紹介名前:⽩⼭ ⽂彦(しろやま ふみひこ)所属:アマゾン ウェブ サービス ジャパン株式会社アプリケーションプロトタイピングソリューションアーキテクト経歴:インフラエンジニア、バックエンド開発者モバイルアプリ開発者、クラウドアーキテクト趣味:⼦育て!、懸垂、⾃動テスト#
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.⾃動テスト⼤好きです!• Androidテスト全書という本を出しました• ⾃動テストの種類やカバーする範囲、モック(テストダブル)の考え⽅、CI/CDとの統合など、Androidに限らずJava/Kotlin開発全般に使える知識を解説しました☞テストコードは全編Kotlinで解説しています!
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Why Kotlin?
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.What’s Kotlin• いわゆる”AltJava”• 2011年に登場した⽐較的新しい⾔語• 完結で強⼒な記法• Null安全• Javaとの相互運⽤性が⾼い• JetBrains製でIntelliJとの相性も良い
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.public class Task {final long id;final String content;final boolean done;public Task(long id, String content, boolean done) {this.id = id;this.content = content;this.done = done;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Task task = (Task) o;return id == task.id &&done == task.done &&Objects.equals(content, task.content);}@Overridepublic int hashCode() {return Objects.hash(id, content, done);}@Overridepublic String toString() {return "Task{" +"id=" + id +", content='" + content + '\'' +", done=" + done +'}';}}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.data class Task(val id: Long,val content: String,val done: Boolean)データクラス
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.data class Task(val id: Long,val content: String,val done: Boolean)
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.fun hasItem(list: List, predicate: (item: Int) -> Boolean): Boolean {for (i in list) {if (predicate(i)) return true}return false}関数リテラル
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.fun hasItem(list: List, predicate: (item: Int) -> Boolean): Boolean {for (i in list) {if (predicate(i)) return true}return false}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.val isEven: (item: Int) -> Boolean = { it % 2 == 0 }hasItem(listOf(1, 2, 3), isEven)
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.hasItem(listOf(1, 2, 3), { it % 2 == 0 })
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.hasItem(listOf(1, 2, 3)) { it % 2 == 0 }
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.fun sum(nums: List): Int {tailrec fun go(nums: List, acc: Int): Int =if (nums.isEmpty()) accelse go(nums.drop(1), acc + nums.first())return go(nums, 0)}⾼階関数
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.fun sum(nums: List): Int {tailrec fun go(nums: List, acc: Int): Int =if (nums.isEmpty()) accelse go(nums.drop(1), acc + nums.first())return go(nums, 0)}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.fun sum(nums: List): Int {tailrec fun go(nums: List, acc: Int): Int =if (nums.isEmpty()) accelse go(nums.drop(1), acc + nums.first())return go(nums, 0)}☞末尾再帰最適化
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Null安全val nullable: String? = "foo"val str = nullable?.let { it.toUpperCase() } ?: "bar"
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.val nullable: String? = "foo"val str = nullable?.let { it.toUpperCase() } ?: "bar"
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.object Singleton {@JvmStaticfun staticFunc() {}}// from JavaSingleton.staticFunc();Java相互運⽤
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.data class Task @JvmOverloads constructor(val id: Long,val content: String,val done: Boolean = false)// from Javanew Task(1, "foo");new Task(2, "bar", true);
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Spring with Kotlin
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Spring Initializrhttps://start.spring.io/
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.interface Greeter {fun hello(name: String): String}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.@Componentclass JapaneseGreeter : Greeter {override fun hello(name: String): String = "こんにちは、$name!"}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.@RestControllerclass HelloController(val greeter: Greeter) {@GetMapping("hello")fun hello(@RequestParam("name") name: String): String = greeter.hello(name)}
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Docker化する
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Docker化するメリット• 簡単に捨てられる開発環境• ステートレスなアーキテクチャの強制• 本番運⽤を⾒据えられる
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.FROM amazoncorretto:8LABEL maintainer="Fumihiko Shiroyama "RUN mkdir /appWORKDIR /appCOPY ./build/libs/*.jar /app/app.jarENTRYPOINT [ "sh", "-c", "java -jar /app/app.jar"]Dockerfiledocker build -t spring-demo .docker container run --rm --name spring-test --net=web --env-file=default.env -d -p 8080:8080 spring-demo:latest
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.DBもDocker化しよう
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.XCTestのはじめ⽅% docker container run --rm --name mysql-test--net=web -e MYSQL_ROOT_PASSWORD=testtest \-d -p 3306:3306 mysql:latest \--character-set-server=utf8mb4--collation-server=utf8mb4_unicode_ci# prepare setup.sql% docker exec mysql-test mysql \-u root --password='testtest' -e"$(cat setup.sql)"
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.application.yml環境変数
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.interface SampleRepository : JpaRepository@Controller@RequestMapping("tasks")class TaskController(private val repository: SampleRepository) {@GetMapping("")fun index(model: Model): String {val tasks = repository.findAll()model.addAttribute("tasks", tasks)return "tasks/index"}}ORMはJPAを利⽤
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.DBに接続完了!
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.AWSにデプロイする
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.今回利⽤するコンポーネント• Amazon Aurora• Amazon Elastic Container Service• CodeStar
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon Aurora
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon Aurora• エディションはMySQL互換• 1つのライターと複数のリーダ• 書き込みエンドポイントと読み込みエンドポイントをメモ☞基本的なアクセス⽅法はこれまでと変わらない
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon Elastic Container Service
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECS• Amazon ECRにイメージの登録• タスクの作成• クラスタの作成• サービスの作成
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECR
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECR$(aws ecr get-login --no-include-email --region ap-northeast-1)docker build -t spring-demo .docker tag spring-demo:latest xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/spring-demo:latestdocker push xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/spring-demo:latest☝解説に従うだけ!
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECSの概念• Dockerコンテナを簡単にデプロイ・管理するためのマネージド・サービス• コントロールプレーンにはECS/EKSが選べる• データプレーンにはEC2/Fargateが選べる• Fargateを使うとリソースについて意識する必要がない
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECSの登場⼈物• タスク• Dockerコンテナと考えればよい。タスク定義から作る• サービス• 複数のタスクからなる。「APIサーバ」「HTTPサーバ」などの役割が1単位となる。• クラスタ• 複数のサービスを束ねたもの
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECS – クラスター
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECS – タスク
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECS – タスク☝環境変数にDB接続情報を格納
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Amazon ECS – サービス
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.まとめ• ローカルから段階的にDocker化することで簡単にECS化できた• Fargateは下回りを意識しなくてもコンテナが扱えて便利• サービスをALBに接続することでロードバランシングなども可能• CodeStar等のCI/CDツールと連携すると、コードチェックインを契機にビルド、ECRの作成、ECSへのデプロイなども⾃動化できる
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.ご清聴ありがとございました(
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.質疑応答
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.Appendix
© 2019, Amazon Web Services, Inc. or its Affiliates. All rights reserved.参考⽂献• ⻑澤太郎(2017)『Kotlin Web アプリケーション – 新しいサーバサイドプログラミング』リックテレコム.