Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させる

Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させる

Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させる
(JSUG勉強会 2019その9 Spring&AWS)

3cca191bf3064fd059ea2c3d6022afbd?s=128

Fumihiko Shiroyama

September 20, 2019
Tweet

Transcript

  1. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Application Prototyping Solutions Architect Fumihiko Shiroyama September 20, 2019 Spring BootをKotlinで作成し Amazon Elastic Container Service (ECS) で稼働させる JSUG 勉強会 2019 その9 Spring&AWS
  2. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. スライドURL http://bit.ly/2lW4MTT
  3. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. ⾃⼰紹介 名前:⽩⼭ ⽂彦(しろやま ふみひこ) 所属:アマゾン ウェブ サービス ジャパン株式会社 アプリケーションプロトタイピングソリューションアーキテクト 経歴:インフラエンジニア、バックエンド開発者 モバイルアプリ開発者、クラウドアーキテクト 趣味:⼦育て!、懸垂、⾃動テスト#
  4. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. ⾃動テスト⼤好きです! • Androidテスト全書という本を出しました • ⾃動テストの種類やカバーする範囲、モック (テストダブル)の考え⽅、CI/CDとの統合 など、Androidに限らずJava/Kotlin開発全般 に使える知識を解説しました ☞テストコードは全編Kotlinで解説しています!
  5. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Why Kotlin?
  6. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. What’s Kotlin • いわゆる”AltJava” • 2011年に登場した⽐較的新しい⾔語 • 完結で強⼒な記法 • Null安全 • Javaとの相互運⽤性が⾼い • JetBrains製でIntelliJとの相性も良い
  7. © 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; } @Override public 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); } @Override public int hashCode() { return Objects.hash(id, content, done); } @Override public String toString() { return "Task{" + "id=" + id + ", content='" + content + '\'' + ", done=" + done + '}'; } }
  8. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. data class Task(val id: Long, val content: String, val done: Boolean) データクラス
  9. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. data class Task(val id: Long, val content: String, val done: Boolean)
  10. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. data class Task(val id: Long, val content: String, val done: Boolean)
  11. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. data class Task(val id: Long, val content: String, val done: Boolean)
  12. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun hasItem(list: List<Int>, predicate: (item: Int) -> Boolean): Boolean { for (i in list) { if (predicate(i)) return true } return false } 関数リテラル
  13. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun hasItem(list: List<Int>, predicate: (item: Int) -> Boolean): Boolean { for (i in list) { if (predicate(i)) return true } return false }
  14. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun hasItem(list: List<Int>, predicate: (item: Int) -> Boolean): Boolean { for (i in list) { if (predicate(i)) return true } return false }
  15. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun hasItem(list: List<Int>, predicate: (item: Int) -> Boolean): Boolean { for (i in list) { if (predicate(i)) return true } return false }
  16. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun hasItem(list: List<Int>, predicate: (item: Int) -> Boolean): Boolean { for (i in list) { if (predicate(i)) return true } return false }
  17. © 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)
  18. © 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)
  19. © 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)
  20. © 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)
  21. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. hasItem(listOf(1, 2, 3), { it % 2 == 0 })
  22. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. hasItem(listOf(1, 2, 3)) { it % 2 == 0 }
  23. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun sum(nums: List<Int>): Int { tailrec fun go(nums: List<Int>, acc: Int): Int = if (nums.isEmpty()) acc else go(nums.drop(1), acc + nums.first()) return go(nums, 0) } ⾼階関数
  24. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun sum(nums: List<Int>): Int { tailrec fun go(nums: List<Int>, acc: Int): Int = if (nums.isEmpty()) acc else go(nums.drop(1), acc + nums.first()) return go(nums, 0) }
  25. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun sum(nums: List<Int>): Int { tailrec fun go(nums: List<Int>, acc: Int): Int = if (nums.isEmpty()) acc else go(nums.drop(1), acc + nums.first()) return go(nums, 0) } ☞ 末尾再帰最適化
  26. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. fun sum(nums: List<Int>): Int { tailrec fun go(nums: List<Int>, acc: Int): Int = if (nums.isEmpty()) acc else go(nums.drop(1), acc + nums.first()) return go(nums, 0) }
  27. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Null安全 val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  28. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  29. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  30. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  31. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  32. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. val nullable: String? = "foo" val str = nullable?.let { it.toUpperCase() } ?: "bar"
  33. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. object Singleton { @JvmStatic fun staticFunc() { } } // from Java Singleton.staticFunc(); Java相互運⽤
  34. © 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 Java new Task(1, "foo"); new Task(2, "bar", true);
  35. © 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 Java new Task(1, "foo"); new Task(2, "bar", true);
  36. © 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 Java new Task(1, "foo"); new Task(2, "bar", true);
  37. © 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 Java new Task(1, "foo"); new Task(2, "bar", true);
  38. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Spring with Kotlin
  39. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Spring Initializr https://start.spring.io/
  40. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. interface Greeter { fun hello(name: String): String }
  41. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. @Component class JapaneseGreeter : Greeter { override fun hello(name: String): String = "こんにちは、$name!" }
  42. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. @RestController class HelloController(val greeter: Greeter) { @GetMapping("hello") fun hello(@RequestParam("name") name: String): String = greeter.hello(name) }
  43. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Docker化する
  44. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Docker化するメリット • 簡単に捨てられる開発環境 • ステートレスなアーキテクチャの強制 • 本番運⽤を⾒据えられる
  45. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. FROM amazoncorretto:8 LABEL maintainer="Fumihiko Shiroyama <shiroyaf@amazon.co.jp>" RUN mkdir /app WORKDIR /app COPY ./build/libs/*.jar /app/app.jar ENTRYPOINT [ "sh", "-c", "java -jar /app/app.jar"] Dockerfile docker build -t spring-demo . docker container run --rm --name spring-test --net=web --env-file=default.env -d -p 8080:8080 spring-demo:latest
  46. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. DBもDocker化しよう
  47. © 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)"
  48. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. application.yml 環境変数
  49. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. interface SampleRepository : JpaRepository<TaskEntity, String> @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を利⽤
  50. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. DBに接続完了!
  51. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. AWSにデプロイする
  52. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. 今回利⽤するコンポーネント • Amazon Aurora • Amazon Elastic Container Service • CodeStar
  53. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon Aurora
  54. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon Aurora • エディションはMySQL互換 • 1つのライターと複数のリーダ • 書き込みエンドポイントと読み込みエンドポイントをメモ ☞基本的なアクセス⽅法はこれまでと変わらない
  55. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon Elastic Container Service
  56. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS • Amazon ECRにイメージの登録 • タスクの作成 • クラスタの作成 • サービスの作成
  57. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECR
  58. © 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:latest docker push xxxxxx.dkr.ecr.ap-northeast- 1.amazonaws.com/spring-demo:latest ☝解説に従うだけ!
  59. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECSの概念 • Dockerコンテナを簡単にデプロイ・管理するためのマ ネージド・サービス • コントロールプレーンにはECS/EKSが選べる • データプレーンにはEC2/Fargateが選べる • Fargateを使うとリソースについて意識する必要がない
  60. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECSの登場⼈物 • タスク • Dockerコンテナと考えればよい。タスク定義から作る • サービス • 複数のタスクからなる。「APIサーバ」「HTTPサーバ」など の役割が1単位となる。 • クラスタ • 複数のサービスを束ねたもの
  61. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS – クラスター
  62. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS – タスク
  63. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS – タスク
  64. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS – タスク ☝環境変数にDB接続情報を格納
  65. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Amazon ECS – サービス
  66. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved.
  67. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. まとめ • ローカルから段階的にDocker化することで簡単にECS化できた • Fargateは下回りを意識しなくてもコンテナが扱えて便利 • サービスをALBに接続することでロードバランシングなども可能 • CodeStar等のCI/CDツールと連携すると、コードチェックインを契 機にビルド、ECRの作成、ECSへのデプロイなども⾃動化できる
  68. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. ご清聴ありがとございました(
  69. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. 質疑応答
  70. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. Appendix
  71. © 2019, Amazon Web Services, Inc. or its Affiliates. All

    rights reserved. 参考⽂献 • ⻑澤太郎(2017)『Kotlin Web アプリケーション – 新しいサーバ サイドプログラミング』リックテレコム.