23 August 2017
Docker is one of the most popular container technologies in the IT world nowadays. It provides many benefits such as portability and component isolation along some other features. For more info: Docker
In this example we are going to dockerize a sample REST API which is built using Scala 2.11.11 and Play Framework 2.6.3.
Sample Play Docker app - how to run
Clone the project
git clone https://github.com/guilhebl/play-scala-rest-api-example
compile and run
sbt run
Check your app at localhost:9000
Sample JSON output (http://localhost:9000/v1/posts):
[
{
"id":"1",
"link":"/v1/posts/1",
"title":"title 1",
"body":"blog post 1"
},
{
"id":"2",
"link":"/v1/posts/2",
"title":"title 2",
"body":"blog post 2"
},
{
"id":"3",
"link":"/v1/posts/3",
"title":"title 3",
"body":"blog post 3"
},
{
"id":"4",
"link":"/v1/posts/4",
"title":"title 4",
"body":"blog post 4"
},
{
"id":"5",
"link":"/v1/posts/5",
"title":"title 5",
"body":"blog post 5"
}
]
How to run an app instance inside a Docker container
In order to dockerize your play rest api example run the following steps:
Generate secret key - since docker will host our production app we need to generate a secret key.
sbt playGenerateSecret
copy the secret key (for example: "YtvWptxIlpf@Q[_dPvE[Z6NLAh_KU0YlGvwnN7sV8DKSk>PSBNbzarVp8j?=;l/y")
Create a new prod dist
sbt dist
Generate a new local Docker image
sbt docker:publishLocal
Run the play app inside a docker container
- replace with your generated key
docker run -p 9000:9000 -e APPLICATION_SECRET="YtvWptxIlpf@Q[_dPvE[Z6NLAh_KU0YlGvwnN7sV8DKSk>PSBNbzarVp8j?=;l/y" play-scala-rest-api-example:1.0-SNAPSHOT
To check the running docker containers run:
docker ps -a
Output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d0bc5f7b2aa play-scala-rest-api-example:1.0-SNAPSHOT "bin/play-scala-re..." 20 seconds ago Up 19 seconds 0.0.0.0:9000->9000/tcp admiring_darwin
Misc commands
to clean the image using sbt-native-packager
sbt docker:clean
- In order to stop all running docker containers
docker stop $(docker ps -aq)
Docker configuration using sbt-native-packager
Add to build.sbt the sbt native docker configuration:
javaOptions in Universal ++= Seq(
// JVM memory tuning
"-J-Xmx1024m",
"-J-Xms128m",
// Since play uses separate pidfile we have to provide it with a proper path
// name of the pid file must be play.pid
s"-Dpidfile.path=/opt/docker/${packageName.value}/run/play.pid"
)
// use ++= to merge a sequence with an existing sequence dockerCommands ++= Seq( ExecCmd("RUN", "mkdir", s"/opt/docker/${packageName.value}"), ExecCmd("RUN", "mkdir", s"/opt/docker/${packageName.value}/run"), ExecCmd("RUN", "chown", "-R", "daemon:daemon", s"/opt/docker/${packageName.value}/") )
// exposing the play ports dockerExposedPorts in Docker := Seq(9000, 9443)
This will generate a
In our conf/application.conf file we need to change secret key to read from an ENV var:
play.http.secret.key=${?APPLICATION_SECRET}
This will generate a docker image based on openjdk In our conf/secure.conf we need to modify trusted proxies in order to load balance in cloud environments:
play {
http {
cookies.strict = true
session.secure = true
session.httpOnly = true
flash.secure = true
flash.httpOnly = true
forwarded.trustedProxies = ["::1", "127.0.0.1"]
}
i18n {
langCookieSecure = true
langCookieHttpOnly = true
}
filters {
csrf {
cookie.secure = true
}
hosts {
allowed = ["localhost:9443", "localhost:9000"]
}
hsts {
maxAge = 1 minute # don't interfere with other projects
secureHost = "localhost"
securePort = 9443
}
}
}