Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ship your Scala code often and easy with Docker

3,845 views

Published on

Presentation from flatMap(Oslo) 2015-04-28.

Published in: Technology
  • According to Docker's best practices, they recommend changing the entrypoint so that it runs in exec as opposed to shell bash command. That way you can easily pass arguments to your Scala application without having to override the entrypoint from command line. So the new entrypoint would be set up like this: entryPoint("java", "-jar", jarName)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Ship your Scala code often and easy with Docker

  1. 1. Ship your Scala code often and easy with Docker Marcus Lönnberg marcus@lonnberg.nu github.com/marcuslonnberg @lonnbergm
  2. 2. e-bokföring
  3. 3. Agenda • Intro to Docker • Building Docker images with sbt • Manage Docker containers with Scala • Docker.at(SpeedLedger)
  4. 4. Platform Open source Client - server REST API Immutable images Container virtualization
  5. 5. Traditional VMs Docker
  6. 6. Docker image Dockerfile Container
  7. 7. Docker image Dockerfile Container > docker build --tag=myimage > docker run myimage
  8. 8. Live demo
  9. 9. Building and shipping Docker images Machine 1 Dockerfile + files Machine x > docker pull myimage > docker run myimage Registry > docker build --tag=myimage > docker push myimage Machine xMachine x
  10. 10. Building Docker images from sbt
  11. 11. Manually building a Scala application as a Docker image 1. Produce a fat JAR 2. Define a Dockerfile 3. Build a Docker image
  12. 12. 0. Current sbt build name := "fancy-service"
 organization := "demo"
 
 libraryDependencies ++= Seq(
 "com.typesafe.akka" %% "akka-actor" % "2.3.9",
 "io.spray" %% "spray-routing" % “1.3.3”, ...
 ) build.sbt
  13. 13. 1. sbt-assembly gives us a fat JAR project/plugins.sbt > sbt assembly … [info] Packaging out/fancy-service.jar ... … [success] Total time: 6 s addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.13.0")
  14. 14. 2. Define a Dockerfile FROM ubuntu RUN apt-get update RUN apt-get install -y openjdk-8-jre-headless COPY fancy-service.jar /app/fancy-service.jar WORKDIR /app ENTRYPOINT java -jar fancy-service.jar EXPOSE 8080 Dockerfile
  15. 15. 2. Define a Dockerfile FROM ubuntu RUN apt-get update RUN apt-get install -y openjdk-8 COPY fancy-service.jar WORKDIR /app ENTRYPOINT java -jar fancy-service.jar EXPOSE 8080 Dockerfile FROM java:8-jre WORKDIR /app EXPOSE 8080 ENTRYPOINT java -jar fancy-service.jar COPY fancy-service.jar /app/fancy-service.jar good
  16. 16. 3. Building a Docker image > docker build -t demo/fancy-service . Sending build context to Docker daemon Step 0 : FROM java:8-jre ---> 028f36974b77 Step 1 : WORKDIR /app ---> fb8108515091 Step 2 : EXPOSE 8080 ---> 9512be4df795 Step 3 : ENTRYPOINT java -jar fancy-service.jar ---> 839dd75f5a96 Step 4 : COPY fancy-service.jar /app/fancy-service.jar ---> 948eb875c3b1 Removing intermediate container f9eeb9406fc7 Successfully built 948eb875c3b1
  17. 17. sbt-docker
  18. 18. sbt-docker addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.1.0") project/plugins.sbt enablePlugins(DockerPlugin) build.sbt
  19. 19. Dockerfile DSL def jarFile: File def jarName: String
 
 new Dockerfile {
 from("java:8-jre")
 workDir("/app")
 expose(8080)
 entryPointRaw(s"java -jar $jarName")
 copy(jarFile, s"/app/$jarName")
 }
  20. 20. Putting it all together docker <<= docker.dependsOn(assembly)
 
 dockerfile in docker := {
 val jarFile = (assemblyOutputPath in assembly).value
 val jarName = name.value + ".jar" 
 new Dockerfile {
 from("java:8-jre")
 workDir("/app")
 expose(8080)
 entryPointRaw(s"java -jar $jarName")
 copy(jarFile, s"/app/$jarName")
 }
 } build.sbt
  21. 21. Let’s build an image > sbt docker … [info] Packaging out/fancy-service.jar ... … [info] Step 0 : FROM java:8-jre [info] ---> 028f36974b77 … [info] Successfully built 30c376822ced [info] Tagging image 30c376822ced with name: demo/fancy-service:0.1-SNAPSHOT [info] Tagging image 30c376822ced with name: demo/fancy-service:latest [success] Total time: 20 s
  22. 22. Image names imageNames in docker := Seq(
 ImageName("demo/fancy-service:" + version.value),
 ImageName("demo/fancy-service:latest")
 ) build.sbt
  23. 23. Immutable Dockerfile def jarFile: File def jarName: String
 
 Dockerfile.empty
 .from("java:8-jre")
 .workDir("/app")
 .expose(8080)
 .entryPointRaw(s"java -jar $jarName")
 .copy(jarFile, s"/app/$jarName")
  24. 24. Build options buildOptions in docker := BuildOptions(
 cache = true,
 removeIntermediateContainers = BuildOptions.Remove.OnSuccess,
 pullBaseImage = BuildOptions.Pull.Always
 ) build.sbt
  25. 25. sbt-docker • Define Dockerfiles with a DSL • Dynamically name your images • Push images to a registry github.com/marcuslonnberg/sbt-docker
  26. 26. Manage Docker containers from Scala
  27. 27. REST API
  28. 28. REST API
  29. 29. scala-docker
  30. 30. Live coding
  31. 31. Docker.at(SpeedLedger)
  32. 32. Build pipeline Dev machine Build server Test Production Registry git repo > git push > sbt dockerBuildAndPush > docker pull image Dev machine
  33. 33. Tagging Docker images with git imageNames in docker := Seq(
 ImageName("demo/fancy-service:" + git.gitHeadCommit.value.get),
 ImageName("demo/fancy-service:" + git.gitCurrentBranch.value)
 )
  34. 34. Labels with build info val labels = Map(
 "build.commitId" -> git.gitHeadCommit.value.get,
 "build.branch" -> git.gitCurrentBranch.value,
 "build.appName" -> name.value,
 "build.buildTime" -> Platform.currentTime.toString
 )
 
 new Dockerfile {
 …
 label(labels)
 …
 } Docker >= 1.6
  35. 35. Internal sbt plugin • Adds common libraries • Generates build info • Configures logging • Adds monitoring • Sets good runtime properties • Defines a Dockerfile template
  36. 36. What we have learned • Order instructions in Dockerfiles for fast builds • Docker is very easy to use except for networking and 
 file persistence • Define own base images but use official when ones exist • Building tools around Docker is easy and fun
  37. 37. Links • github.com/marcuslonnberg/sbt-docker • github.com/marcuslonnberg/scala-docker • github.com/sbt/sbt-assembly • github.com/sbt/sbt-native-packager
  38. 38. Thank you! marcus@lonnberg.nu github.com/marcuslonnberg @lonnbergm

×