I would like to deploy an app written with Play Framework 2.5 on a Jelastic platform. I managed to use the Play2War plugin for Play but it doesn't support Play 2.5 yet.
The support of the platform recommended to use a Docker container or a VPS. I've never worked with Docker before. There is a SBT native packager plugin to provide a way to create automatically a Dockerfile with SBT. So here is my new plugins.sbt file:
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.11")
// Web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0")
addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.2")
// Play enhancer - this automatically generates getters/setters for public fields
// and rewrites accessors of these fields to use the getters/setters. Remove this
// plugin if you prefer not to have this feature, or disable on a per project
// basis using disablePlugins(PlayEnhancer) in your build.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0")
// Play Ebean support, to enable, uncomment this line, and enable in your build.sbt using
// enablePlugins(PlayEbean).
addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.0")
// Play Eclipse plugin
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
// Play native packager support for Docker
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.2.0-M8")
And here is my build.sbt file with Docker settings based on some examples:
import com.typesafe.sbt.packager.docker._
name := """VestaWeb"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean, DockerPlugin)
scalaVersion := "2.11.7"
// Configure Docker settings
maintainer in Docker := "eeproperty"
dockerRepository := Some("eeproperty")
dockerBaseImage := "frolvlad/alpine-oraclejdk8:latest"
dockerCommands := dockerCommands.value.flatMap {
case cmd@Cmd("FROM", _) => List(cmd, Cmd("RUN", "apk update && apk add bash"))
case other => List(other)
}
// Add dependencies from Maven
libraryDependencies ++= Seq(
filters,
javaCore,
javaJdbc,
cache,
javaWs,
"mysql" % "mysql-connector-java" % "5.1.28",
"com.stripe" % "stripe-java" % "2.10.0",
"com.typesafe.play" %% "play-mailer" % "5.0.0",
"it.innove" % "play2-pdf" % "1.5.1",
"com.google.api-client" % "google-api-client" % "1.22.0",
"org.apache.commons" % "commons-compress" % "1.12"
)
// Remove the documentation from the dist
sources in (Compile, doc) := Seq.empty
publishArtifact in (Compile, packageDoc) := false
// Disable strange behavior in local run
fork in run := false
The command:
activator docker:stage
produces this Dockerfile:
FROM frolvlad/alpine-oraclejdk8:latest
RUN apk update && apk add bash
MAINTAINER eeproperty
WORKDIR /opt/docker
ADD opt /opt
RUN ["chown", "-R", "daemon:daemon", "."]
USER daemon
ENTRYPOINT ["bin/vestaweb"]
CMD []
and a few other stuff like a docker/
folder.
The command:
activator docker:publish
publishes the Dockerfile (and maybe the other files???) to my Docker repository. I have no idea what Docker pushes to it and how it knows how to embbed the Play app in the Alpine Linux base image.
I added my repository to a Docker instance and Jelastic and I started it. I can log in to my root account via SSH but there is nothing related to my app in the container. Nothing appears when I try to open the Jelastic node in my browser.
Play Framework uses the port 9000 and Jelastic load from the port 80 by default. I guess I'll have to add an iptables
command to my Dockerfile to redirect the trafic from 80 to 9000.
I've read a LOT of tutorials on "Dockerize a Play app" but they never explain how to deploy the app, only how to run the container locally with activator docker:publishLocal
.
What point did I miss?
We have reproduced the issue with that docker. The docker works well at localhost but doesn't work well as Jelastic environment. The root cause is a bug JE-29972 (-nologin: this account is not available) when the user inside the docker has /sbin/nologin shell instead of /bin/bash.
As a workaround, we can suggest you change the /etc/passwd and replace daemon:x:2:2:daemon:/sbin:/sbin/nologin with daemon:x:2:2:daemon:/opt/docker:/bin/bash and restart your environment after the changes.
There is build.sbt file with Docker settings where the mentioned workaround is included:
import com.typesafe.sbt.packager.docker._
name := """test"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava, DockerPlugin)
scalaVersion := "2.11.7"
// Configure Docker settings
maintainer in Docker := "eeproperty"
dockerExposedPorts := Seq(9000)
dockerRepository := Some("eeproperty")
dockerBaseImage := "frolvlad/alpine-oraclejdk8:latest"
dockerCommands := dockerCommands.value.flatMap {
case cmd@Cmd("FROM", _) => List(cmd, Cmd("RUN", "apk update && apk --no-cache add bash shadow && usermod -s /bin/bash daemon && usermod -d /opt/docker/ daemon"))
case other => List(other)
}
libraryDependencies ++= Seq(
javaJdbc,
cache,
javaWs
)
sources in (Compile, doc) := Seq.empty
publishArtifact in (Compile, packageDoc) := false