Developer Blog

Deploying Play Framework to Elastic Beanstalk in Docker

| Comments

It is very easy to create a docker image of a scala play app using sbt, which can then be uploaded to AWS EC2 or Elastic Beanstalk

Using the command line:

1
 sbt docker:stage

This will generate a docker image in target/docker, with a file called ‘Dockerfile’ and a directory called ‘files’. In Dockerfile, you will need to append the following line: EXPOSE 9000. You may also want to add any parameters to the line ENTRYPOINT. For example, I added a parameter for loading the production configuration file.

Dockerfile

1
2
3
4
5
6
7
8
9
FROM dockerfile/java
MAINTAINER John Doe <john.doe@gmail.com>
ADD files /
WORKDIR /opt/docker
RUN ["chown", "-R", "daemon", "."]
USER daemon
ENTRYPOINT ["bin/myapp", "-Dconfig.resource=application.prod.conf"]
CMD []
EXPOSE 9000

You will also need to create a file called Dockerrun.aws.json. It goes at the same level as Dockerfile.

Dockerrun.aws.json

1
2
3
4
5
6
{
   "AWSEBDockerrunVersion": "1",
   "Ports": [{
       "ContainerPort": "9000"
   }]
}

Once those are created, you can zip the files and then upload it to elastic beanstalk. Caution, you must not zip the parent ‘docker’ directory. Dockerfile, Dockerrun.aws.json, and files need to be in the root. For example, in terminal, navigate to target/docker and run

1
zip -r docker.zip *

Automated Deployment with Jenkins

Best practice is to have a continuous integration server automatically deploy to a staging environment. Below is a bash script that can be used in Jenkins to automatically test, build and deploy to elastic beanstalk. It uses the git revision as the application version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cd app

# Run unit tests
activator test

# Build the docker image
sbt docker:stage

# Copy Dockerfile and Dockerrun.aws.json to target/docker
cd ../scripts/deployment
cp Dockerfile Dockerrun.aws.json ../../app/target/docker

# Zip the files
cd ../../app/target/docker
zip -r $GIT_COMMIT.zip *

# -- AWS --
# Upload the image
aws s3api put-object --bucket my_bucket --key $GIT_COMMIT --body $GIT_COMMIT.zip

# Create a new application version
aws elasticbeanstalk create-application-version --application-name "myapp" --version-label $GIT_COMMIT --source-bundle S3Bucket=my_bucket,S3Key=$GIT_COMMIT

# Deploy the image
aws elasticbeanstalk update-environment --environment-name myapp-env --version-label $GIT_COMMIT

Using Option in Scala

| Comments

There are many way to use Option in Scala. Per scala docs, the idiomatic way to use Option is to treat it as a collection that can have either a length of one of zero.

Let’s says we have a basic class, Author

Simple Option checking

1
2
case class Author(name:Option[String])
val author:Author = ...

The traditional way is to check if the name is defined. This way can be prone to error is you forget to add the “get” method

1
val authorName:String = if (author.name.isDefined) author.name.get else "name is empty"

A best way to check for a simple Option is GetOrElse

1
val authorName:String = author.name.getOrElse("name is empty")