Let's Play!
After my last post, it would be a good time to do a bit more of a technical story.
The goal will be to set up a Hello World application using the Play framework,
a front-end based on Angular running on a Docker image, deployed in your local running Kubernetes!
So let’s play!
Why Play?
Play has been around for quite some time now. It was built by web developers to make it more easy to develop web applications using either Java or Scala. Play is reactive(1) by default, uses the MVC architecture(2) and is built on Akka(3). Akka can be described as ‘the implementation of the Actor Model(4) on the JVM’. Play is a lightweight, stateless framework that provides all components you need for web applications and REST services. It’s easy to scale both horizontally and vertically. The framework integrates a http server, CSRF protection and i18n support, supports Ebeans, JPA, Slick and does hot reloading of your code. This makes it easy to directly see the results of your work. Besides all that, it’s just FUN to use! For more information about Play, just visit their site.
Why Angular?
Well, I could have chosen React, or the Scala based template engine that comes by default. For now I made the choice for Angular(5), since it provides the same MVC architecture as Play. Angular makes it easy to implement 2-way data binding and gives a rich and responsive experience. There is also a nice boilerplate to get you started using Angular and Play together. If you have read my last blog about containerization, I don’t think I have to explain the choice for Docker and Kubernetes :)
Let’s start
I’m working on a Macbook, so if you’re using Linux or Windows, some steps are (a bit) different.
Also, I assume you’ve got the OpenJDK version 11 and the latest version of Docker Desktop installed on your system.
You don’t have to install Kubernetes separately, since it comes as a first class citizen with Docker.
Install the Playframework
Installing Play is easy. Keep in mind that since version 2.3.0, the play command is replaced by sbt (Scala Build Tool). You don’t actually need sbt to run it, as you only need the Play JAR files to run it. In theory you could use any Java or Scala build tool to build a Play project. If you want to use the development experience Play can provide (routes, templates, IDE integration etc), I suggest you use sbt.
Using homebrew on your Mac, just open a terminal and type
brew install sbt@1
Or download it directly for your own platform.
Getting your boilerplate
To make your world even more easy, Play uses Giter8 (6) to generate files and templates published on Github. Giter8 can be called from sbt’s “new” command:
sbt new playframework/play-scala-seed.g8
For now I chose to use another starter from a nice tutorial written by Yohan Gomez (7) , so just do a
git clone https://github.com/yohangz/java-play-angular-seed.git
Let’s quickly check if your application is working: Cd into the folder and
sbt run
If everything went okay, you should see a nice page, pointing to your localhost. I like this setup since it separates the back-end (running on port 9000) from the front-end. If you want, you can import the project into your favourite IDE. For now that’s not part of our scope. Stop your program by pressing control-c, and let’s create our Docker image.
Creating the Docker image
First create the needed artifact by typing
sbt dist
This generates ./target/universal/java-play-angular-seed-1.0-SNAPSHOT.zip file.
Now create a folder where you want to build your deployment files for Docker, and create a subfolder called svc,
for example:
cd ~/Development/DockerDeployment && mkdir svc
unzip -d svc/ ./java-play-angular-seed/target/universal/java-play-angular-seed-1.0-SNAPSHOT.zip
mv svc/*/* svc/
rm svc/bin/*.bat
mv svc/bin/* svc/bin/start
rm -rf svc/java-play-angular-seed-1.0-SNAPSHOT/
Now create file called Dockerfile with the following contents:
FROM openjdk:11-jre
COPY svc /svc
EXPOSE 4200 9090
CMD /svc/bin/start -Dhttp.port=9444 -Dplay.crypto.secret=needstobeagoodsecretkey123
Now create your docker image from the folder that contains both the svc folder and your Dockerfile. Notice the period at the end of the line.
docker build -t play-hello .
Now check if your image is working by starting it up:
docker run -it -p 9444:9444 --rm play-hello
If everything is okay, you should be able to point your browser to localhost:9444 and see that nice page again you just have seen before.
Congratulations, you’re now running your own Playframework/Angular based application within a Docker image!
On to the next step, so in your terminal press control-c again to stop the image from running.
Pushing the Docker image to your own registry
Next step is to create your a local registry server. Easiest way is to use docker for that as well (8):
docker run -d -p 5000:5000 --restart always --name registry registry:2
Now tag your image to be pushed to the registry, and push it onto the registry:
docker tag play-hello localhost:5000/play-hello
docker push localhost:5000/play-hello
Let’s check if everything is okay:
curl http://localhost:5000/v2/_catalog
Now you should see something like this:
+ curl http://localhost:5000/v2/_catalog
{"repositories":["play-hello"]}
Deploying the Docker image to your Kubernetes cluster
Time to get it up and running in Kubernetes! Create the file deployment.yaml:
apiVersion: v1
kind: Service
metadata:
name: play-service
labels:
app: play-hello
spec:
selector:
app: play-hello
ports:
- protocol: TCP
port: 9444
name: tcp9444
targetPort: 9444
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: play-hello
spec:
replicas: 1
selector:
matchLabels:
app: play-hello
template:
metadata:
labels:
app: play-hello
spec:
containers:
- name: play-hello
image: localhost:5000/play-hello
imagePullPolicy: Always
ports:
- containerPort: 9444
Save the file and type:
kubectl apply -f deployment.yaml
Now we have to check the deployment and exposed nodeport, so we’re able to check if everything went as planned:
kubectl get services
The output will be something like:
NAME |
TYPE |
CLUSTER-IP |
EXTERNAL-IP |
PORT(S) |
AGE |
kubernetes |
ClusterIP |
10.96.0.1 |
<none> |
443/TCP |
8d |
play-service |
NodePort |
10.96.123.165 |
<none> |
9444:32743/TCP |
1d |
Now go to http://localhost:32743 and voila, your application is running on your local Kubernetes environment !