In this article by Giancarlo Inductivo, author of the book Play Framework Cookbook Second Edition, we will see deploy a Play 2 web application using CoreOS and Docker. CoreOS is a new, lightweight operating system ideal for modern application stacks. Together with Docker, a software container management system, this forms a formidable deployment environment for Play 2 web applications that boasts of simplified deployments, isolation of processes, ease in scalability, and so on.
(For more resources related to this topic, see here.)
For this recipe, we will utilize the popular cloud IaaS, Digital Ocean. Ensure that you sign up for an account here:
https://cloud.digitalocean.com/registrations/new
This recipe also requires Docker to be installed in the developer’s machine. Refer to the official Docker documentation regarding installation:
https://docs.docker.com/installation/
How to do it…
- Create a new Digital Ocean droplet using CoreOS as the base operating system. Ensure that you use a droplet with at least 1 GB of RAM for the recipe to work. note that Digital Ocean does not have a free tier and are all paid instances:
- Ensure that you select the appropriate droplet region:
- Select CoreOS 607.0.0 and specify a SSH key to use. Visit the following link if you need more information regarding SSH key generation:
https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys–2: - Once the Droplet is created, make a special note of the Droplet’s IP address which we will use to log in to the Droplet:
- Next, create a Docker.com account at https://hub.docker.com/account/signup/
- Create a new repository to house the play2-deploy-73 docker image that we will use for deployment:
- Create a new Play 2 webapp using the activator template, computer-database-scala, and change into the project root:
activator new play2-deploy-73 computer-database-scala && cd play2-deploy-73
- Edit conf/application.conf to enable automatic database evolutions:
applyEvolutions.default=true
- Edit build.sbt to specify Docker settings for the web app:
import NativePackagerKeys._ import com.typesafe.sbt.SbtNativePackager._ name := """play2-deploy-73""" version := "0.0.1-SNAPSHOT" scalaVersion := "2.11.4" maintainer := "<YOUR_DOCKERHUB_USERNAME HERE>" dockerExposedPorts in Docker := Seq(9000) dockerRepository := Some("YOUR_DOCKERHUB_USERNAME HERE ") libraryDependencies ++= Seq( jdbc, anorm, "org.webjars" % "jquery" % "2.1.1", "org.webjars" % "bootstrap" % "3.3.1" ) lazy val root = (project in file(".")).enablePlugins(PlayScala)
- Next, we build the Docker image and publish it to Docker Hub:
$ activator clean docker:stage docker:publish .. [info] Step 0 : FROM dockerfile/java [info] ---> 68987d7b6df0 [info] Step 1 : MAINTAINER ginduc [info] ---> Using cache [info] ---> 9f856752af9e [info] Step 2 : EXPOSE 9000 [info] ---> Using cache [info] ---> 834eb5a7daec [info] Step 3 : ADD files / [info] ---> c3c67f0db512 [info] Removing intermediate container 3b8d9c18545e [info] Step 4 : WORKDIR /opt/docker [info] ---> Running in 1b150e98f4db [info] ---> ae6716cd4643 [info] Removing intermediate container 1b150e98f4db [info] Step 5 : RUN chown -R daemon . [info] ---> Running in 9299421b321e [info] ---> 8e15664b6012 [info] Removing intermediate container 9299421b321e [info] Step 6 : USER daemon [info] ---> Running in ea44f3cc8e11 [info] ---> 5fd0c8a22cc7 [info] Removing intermediate container ea44f3cc8e11 [info] Step 7 : ENTRYPOINT bin/play2-deploy-73 [info] ---> Running in 7905c6e2d155 [info] ---> 47fded583dd7 [info] Removing intermediate container 7905c6e2d155 [info] Step 8 : CMD [info] ---> Running in b807e6360631 [info] ---> c3e1999cfbfd [info] Removing intermediate container b807e6360631 [info] Successfully built c3e1999cfbfd [info] Built image ginduc/play2-deploy-73:0.0.2-SNAPSHOT [info] The push refers to a repository [ginduc/play2-deploy-73] (len: 1) [info] Sending image list [info] Pushing repository ginduc/play2-deploy-73 (1 tags) [info] Pushing tag for rev [c3e1999cfbfd] on {https://cdn-
registry-1.docker.io/v1/repositories/ginduc/play2-deploy-73/tags/0.0.2-SNAPSHOT} [info] Published image ginduc/play2-deploy-73:0.0.2-SNAPSHOT - Once the Docker image has been published, log in to the Digital Ocean droplet using SSH to pull the uploaded docker image. You will need to use the core user for your CoreOS Droplet:
ssh core@<DROPLET_IP_ADDRESS HERE> core@play2-deploy-73 ~ $ docker pull
<YOUR_DOCKERHUB_USERNAME HERE>/play2-deploy-73:0.0.1-SNAPSHOT Pulling repository ginduc/play2-deploy-73 6045dfea237d: Download complete 511136ea3c5a: Download complete f3c84ac3a053: Download complete a1a958a24818: Download complete 709d157e1738: Download complete d68e2305f8ed: Download complete b87155bee962: Download complete 2097f889870b: Download complete 5d2fb9a140e9: Download complete c5bdb4623fac: Download complete 68987d7b6df0: Download complete 9f856752af9e: Download complete 834eb5a7daec: Download complete fae5f7dab7bb: Download complete ee5ccc9a9477: Download complete 74b51b6dcfe7: Download complete 41791a2546ab: Download complete 8096c6beaae7: Download complete Status: Downloaded newer image for
<YOUR_DOCKERHUB_USERNAME HERE>/play2-deploy-73:0.0.2-SNAPSHOT - We are now ready to run our Docker image using the following docker command:
core@play2-deploy-73 ~ $ docker run -p 9000:9000
<YOUR_DOCKERHUB_USERNAME_HERE>/play2-deploy-73:0.0.1-SNAPSHOT - Using a web browser, access the computer-database webapp using the IP address we made note of in an earlier step of this recipe (http://192.241.239.43:9000/computers):
How it works…
In this recipe, we deployed a Play 2 web application by packaging it as a Docker image and then installing and running the same Docker image in a Digital Ocean Droplet. Firstly, we will need an account on DigitalOcean.com and Docker.com.
Once our accounts are ready and verified, we create a CoreOS-based droplet. CoreOS has Docker installed by default, so all we need to install in the droplet is the Play 2 web app Docker image.
The Play 2 web app Docker image is based on the activator template, computer-database-scala, which we named play2-deploy-73.
We make two modifications to the boilerplate code. The first modification in conf/application.conf:
applyEvolutions.default=true
This setting enables database evolutions by default. The other modification is to be made in build.sbt. We import the required packages that contain the Docker-specific settings:
import NativePackagerKeys._ import com.typesafe.sbt.SbtNativePackager._
The next settings are to specify the repository maintainer, the exposed Docker ports, and the Docker repository in Docker.com; in this case, supply your own Docker Hub username as the maintainer and Docker repository values:
maintainer := "<YOUR DOCKERHUB_USERNAME>" dockerExposedPorts in Docker := Seq(9000) dockerRepository := Some("<YOUR_DOCKERHUB_USERNAME>")
We can now build Docker images using the activator command, which will generate all the necessary files for building a Docker image:
activator clean docker:stage
Now, we will use the activator docker command to upload and publish to your specified Docker.com repository:
activator clean docker:publish
To install the Docker image in our Digital Ocean Droplet, we first log in to the droplet using the core user:
ssh core@<DROPLET_IP_ADDRESS>
We then use the docker command, docker pull, to download the play2-deploy-73 image from Docker.com, specifying the tag:
docker pull <YOUR_DOCKERHUB_USERNAME>/play2-deploy-73:0.0.1-SNAPSHOT
Finally, we can run the Docker image using the docker run command, exposing the container port 9000:
docker run -p 9000:9000 <YOUR_DOCKERHUB_USERNAME>/play2-deploy-73:0.0.1-SNAPSHOT
There’s more…
Refer to the following links for more information on Docker and Digital Ocean:
Summary
In this recipe, we deployed a Play 2 web application by packaging it as a Docker image and then installing and running the same Docker image in a Digital Ocean Droplet.
Resources for Article:
Further resources on this subject:
- Less with External Applications and Frameworks [article]
- SpriteKit Framework and Physics Simulation [article]
- Speeding Vagrant Development With Docker [article]