Speaker Deck
Speaker Deck Pro
Sign in
Sign up
for free
Scala Kansai Summit 2017
s_edward
September 09, 2017
Technology
0
190
Scala Kansai Summit 2017
Scala on Docker
s_edward
September 09, 2017
Tweet
Share
More Decks by s_edward
See All by s_edward
takesection
1
66
takesection
0
25
takesection
1
59
takesection
3
260
takesection
1
130
takesection
2
300
takesection
1
37
takesection
0
180
takesection
0
140
Other Decks in Technology
See All in Technology
shomaekawa
3
1k
kenya888
1
110
sakon310
4
4.2k
sasakendayo
2
270
satoshirobatofujimoto
0
110
satoryu
0
2k
helayoty
0
110
ocise
0
110
minamizaki
0
530
sylph01
0
160
masakick
0
110
kakka
0
3.3k
Featured
See All Featured
cherdarchuk
71
260k
lara
172
9.5k
revolveconf
200
9.6k
maggiecrowley
8
400
mthomps
39
2.3k
skipperchong
7
660
chrislema
173
14k
tmm1
61
8.3k
nonsquared
81
3.3k
rmw
11
740
philhawksworth
192
8.8k
orderedlist
PRO
329
35k
Transcript
Scala on docker 20179݄9 ঙ࢘ ॏथ @takesection #scala_ks
AWS Amazon EC2 Amazon ECS AWS Lambda Amazon API Gateway*
Elastic Load Balancing Amazon Route 53 OS͔ΒΞϓϦέʔγϣϯ·ͰࣗલͰσ ϓϩΠɺӡ༻ DockerΠϝʔδΛ࣮ߦ ίʔυΛ࣮ߦ • ίʔυαΠζͷ੍ݶ • ίʔυͷ࣮ߦ࣌ؒͷ੍ݶ • API GatewayͷλΠϜΞτ࣌ؒͷ੍ݶ
Docker
• ΞϓϦέʔγϣϯΛσʔϞϯͱ࣮ͯ͠ߦ͢ΔΑ͏ͳΈ Λߟ͑ͳ͍͍ͯ͘ • ΞϓϦέʔγϣϯΛDockerΠϝʔδʹ͢ΕɺECSʹݶ ΒͣɺDockerΛಈ͔͢ڥ͑͋͞Εखܰʹىಈͯ֬͠ೝ Ͱ͖Δ • ෛՙ͕૿͑ͨͱ͖ʹEC2ΑΓߴʹΞϓϦέʔγϣϯͷ ΠϯελϯεΛ૿͢͜ͱ͕Ͱ͖Δ
AWS ECS
• Container Instances • Amazon EC2 Instances • Docker daemon
• Amazon ECS agent
• Clusters • Task Definitions • Tasks • Service •
Good for long-running applications and services
AWS ECR
• Docker Hub(https://hub.docker.com/)ͷସ • ࣾΞϓϦέʔγϣϯͷDockerΠϝʔδΛϗετͰ͖Δ
ಥવͰ͕͢…
None
sbt
• sbt ΛΠϯετʔϧ͓͚ͯ͠ɺScalaίϯύΠϥϏϧυ ࣌ʹͳ͚Εμϯϩʔυͯ͘͠ΕΔ • sbt JDK(Java 8)͕ඞཁ • MacLinuxͷ߹ɺsdkman(http://sdkman.io/)͕͑
Δ $ sdk install sbt
giter8 https://github.com/scala/scala-seed.g8 $ sbt new scala/scala-seed.g8 A minimal Scala project.
name [Scala Seed Project]: helloworld Template applied in ./helloworld
σΟϨΫτϦߏ helloworld/ build.sbt project/ build.properties Dependencies.scala src/ main/ scala/ resources/
test/ scala/ resources/
build.sbt import Dependencies._ lazy val root = (project in file(".")).
settings( inThisBuild(List( organization := "com.example", scalaVersion := "2.12.3", version := "0.1.0-SNAPSHOT" )), name := "Hello", libraryDependencies += scalaTest % Test )
Dependencies.scala import sbt._ object Dependencies { lazy val scalaTest =
"org.scalatest" %% "scalatest" % "3.0.3" }
ґଘϥΠϒϥϦ group-id % artifact-id % version ྫ: "com.typesafe.akka" % "akka-http_2.12"
% “10.0.9" or "com.typesafe.akka" %% “akka-http" % "10.0.9"
build.properties sbt.version=0.13.16
console • sbtͷίϚϯυϓϩϯϓτͰconsoleΛ࣮ߦ͢ΔͱɺScalaͷREPL(Read Eval Print Loop)͕ىಈ͢Δ • ґଘϥΠϒϥϦͷimportͰ͖ΔͷͰίʔυΛॻ͘લʹࢼ͍ͨ͠ͱ͖ศར $ sbt
> console scala> (1 to 5).foreach(println(_)) scala> :q > exit
sbt-assembly
• ΞϓϦέʔγϣϯͷJarͱґଘϥΠϒϥϦͷJarΛ݁߹͠ ͯɺ࣮ߦՄೳͳJar(fat JAR)Λੜ͢Δ
sbt-native-packager
• ScalaΞϓϦέʔγϣϯΛ࣮ߦ͢ΔDockerΠϝʔδΛ࡞ ɺϦϙδτϦͷpush·Ͱߦ͑Δ • ίϯύΠϧɺDockerfileͷੜΛߦ͏(stage) • ΠϝʔδੜͱϦϙδτϦʹpublish(publishLocal)
build.sbt import Dependencies._ lazy val root = (project in file(“.")).
enablePlugins(JavaAppPackaging, AshScriptPlugin, DockerPlugin). settings( inThisBuild(List( organization := "com.example", scalaVersion := "2.12.3", version := "0.1.0-SNAPSHOT" )), name := “Hello", dockerBaseImage := "java:8-jdk-alpine", libraryDependencies += scalaTest % Test )
project/plugins.sbt addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" %
"1.2.0") addSbtPlugin("com.pigumer.sbt.cloud" % "sbt-aws-cloudformation" % "5.0.5")
$ sbt > docker:stage > docker:publishLocal > exit $ docker
images REPOSITORY TAG IMAGE ID CREATED SIZE hello 0.1.0-SNAPSHOT f27cbbaf1038 6 seconds ago 156MB $ docker run —rm hello:0.1.0-SNAPSHOT hello ※ Docker for Mac Ͱ֬ೝ͍ͯ͠·͢ɻDocker for Mac Ҏ֎ະݕূɻ
Akka HTTP
• HTTPͷαʔόʔαΠυɺΫϥΠΞϯταΠυͷ࣮ • ؆୯ʹREST APIΛ࡞Ͱ͖Δ pathEndOrSingleSlash { get { complete("Hello
World") } ~ post { entity(as[Foo]) { foo => complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, foo.name)) } } }
Dependencies.scala import sbt._ object Dependencies { lazy val scalaTest =
"org.scalatest" %% "scalatest" % "3.0.3" // Akka-HTTP lazy val akkaHttpVersion = "10.0.5" lazy val akkaHttp = "com.typesafe.akka" %% "akka-http" % akkaHttpVersion lazy val helloDeps = Seq( akkaHttp, scalaTest % Test ) }
build.sbt import Dependencies._ lazy val root = (project in file(".")).
enablePlugins(JavaAppPackaging, AshScriptPlugin, DockerPlugin). settings( inThisBuild(List( organization := "com.github.takesection", scalaVersion := "2.12.3", version := "0.1.0-SNAPSHOT" )), name := "Akka HTTP", dockerBaseImage := "java:8-jdk-alpine", dockerExposedPorts := Seq(8080), libraryDependencies ++= helloDeps )
hello.scala package example import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.stream.ActorMaterializer import
akka.http.scaladsl.server.Directives._ import scala.concurrent.duration._ class Hello { def createActorSystem = ActorSystem("hello") def route = pathEndOrSingleSlash { complete("Hello World") } ~ path(IntNumber) { id ⇒ complete(s"$id") } }
object Hello extends Hello with App { implicit val system
= createActorSystem implicit val materializer = ActorMaterializer() implicit val executionContext = system.dispatcher implicit val timeout = 5 seconds val serverBinding = Http().bindAndHandle(handler = route, interface = "0.0.0.0", port = 8080 ) Runtime.getRuntime.addShutdownHook(new Thread { override def run() { serverBinding.flatMap(_.unbind()).onComplete(_ => system.terminate()) } }) }
࣮ߦ $ sbt > docker:stage > docker:publishLocal > exit $
docker run -d -p 8080:8080 --rm akka-http:0.1.0-SNAPSHOT $ curl http://localhost:8080/ $ curl http://localhost:8080/123
Akka HTTP • AWS API GatewayAWS Lambdaͷ੍ݶΛ͑ΔΑ͏ͳ ࣌ؒͷ͔͔Δॲཧɺෳࡶͳॲཧ͕ඞཁͳREST APIΛ࡞ ͍ͨ͠߹ʹ͍͍ͯΔ
• OAuth TokenCORSʹରԠ͢ΔͨΊͷϥΠϒϥϦ͕OSS Ͱެ։͞Ε͍ͯΔ
akka-stream
• Akka HTTPɺakka-actorͱakka-streamͷ্ʹ࡞ΕΒͯ ͍Δ • StreamɺSource͔ΒೖͬͯɺFlowΛ௨ΓɺSinkͰऴΘ Δ
Dependencies.scala import sbt._ object Dependencies { val akkaStreamVersion = "2.5.1"
lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.3" lazy val helloDeps = Seq( scalaTest % Test, "com.typesafe.akka" %% "akka-stream" % akkaStreamVersion ) }
build.sbt import Dependencies._ lazy val root = (project in file(".")).
enablePlugins(JavaAppPackaging, AshScriptPlugin, DockerPlugin). settings( inThisBuild(List( organization := "com.github.takesection", scalaVersion := "2.12.3", version := "0.1.0-SNAPSHOT" )), name := "Akka Stream", dockerBaseImage := "java:8-jdk-alpine", libraryDependencies ++= helloDeps )
hello.scala package example import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl._ import
scala.concurrent.Await import scala.concurrent.duration._ object Hello extends App { implicit val system = ActorSystem("Hello") implicit val materializer = ActorMaterializer() implicit val executionContext = system.dispatcher val flow = Source(1 to 5).via(Flow[Int].map(_ * 2)).runWith(Sink.seq[Int]) val results = Await.result(flow, 5 seconds) results.foreach(println(_)) sys.exit }
࣮ߦ $ sbt > docker:stage > docker:publishLocal > exit $
docker run --rm akka-stream:0.1.0-SNAPSHOT
akka-stream • KinesisSQSͷϝοηʔδͷΑ͏ͳඇಉظͷΠϕϯτΛτϦΨʔʹॲཧ Λߦ͏Α͏ͳΞϓϦέʔγϣϯʹ͍ͯΔ • alpakka( http://developer.lightbend.com/docs/alpakka/current/sqs.html ) Amazon SQS
Amazon Kinesis Amazon RDS Flow Source Flow Sink
Scala
• Option • Some͔NoneͱͳΔ Option(null) match { case Some(a) 㱺
??? case None 㱺 println("NONE") }
• Try • Tryͷ݁ՌɺSuccess͔FailureͱͳΔ • Either • Eitherͷ݁ՌɺLeft͔RightͱͳΔ • ίϨΫγϣϯҎ֎ͨͱ͑Option,
Try, Either, FutureͰ mapflatMap͕͑Δ
• head Seq(3,2,1).head Seq.empty[Int].headOption • intersectdiffͷΑ͏ͳू߹ԋࢉ (1 to 5).intersect(List(2, 4,
7)) (1.to(5)).diff(List(2, 3))
• ύλʔϯϚον Seq(Some(1), Some(2), None).foreach { case Some(n) 㱺 println(n.toString)
case None 㱺 println("NONE") }
• @tailrec @tailrec private def loop(list: Seq[Int]): Unit = list
match { case head +: tails 㱺 println(head) loop(tails) case Nil 㱺 () }
None
None
None
• Deploying Amazon EC2 Container Service (ECS) - Simple Cloud
Hosting on AWS( https://youtu.be/1wLMLwjCqN4 ) • Amazon ECS: Autoscaling for Containers( https:// youtu.be/YEvU6uIckDc )
https://github.com/takesection/scala-kansai-summit-2017