I heard about Docker a lot. In fact, all the microservices I developed in the past year are deployed using Docker. Having said that, my knowledge about Docker was somewhat limited to knowing what is Docker, and not how to use it – that was the task of one of our developers who is passionate about setting up things, unlike me who is passionate more about writing the code after things are already set up. Few days ago, I decided to fiddle with Docker myself and dip my toes into the practicalities of it. Here I am sharing my experience.
Generate and run Docker image
First, to generate your Docker image from your own Play App, navigate to the App root directory, and simply run the following in your command line, to generate Dockerfile and Docker assets:
$ sbt docker:publishLocal
It will generate docker directory under: target/
Navigate to target/docker/stage/, then by using the below command, you can generate your first Docker image (will be generated under target/docker/stage/ )
$ docker build -t flying-thots-docker-image .
To run your Docker image in the background, use the following command:
$ docker run -p 9000:9000 -d flying-thots-docker-image
To stop it, I usually get the container if from using:
$ docker ps
$ docker stop
Using different conf file
Let us be honest, the above is very trivial, and it is mentioned tons of times on the web. The challenges start when we come down to real life scenarios. One of the main scenarios in Play Apps, is to run on production with different configuration file – typically we call it prod.conf . With typical Play App, that is very easy by passing the path to the configurations file. For example:
$ flying-thots -Dconfig.file=prod/flying-thots/conf/prod.conf -Dplay.http.secret.key=hidemeonproduction
When you run it inside Docker, however, it becomes a bit tricky. The reason is that Docker image has its own file system, and inherently its own file paths. In order for you to access files on the host system from the container, you need to map these files. I only discovered this by accident while struggling with my App not running. This post gave me the hint Play Framework 2.4 docker image run error. I tried with that, but initially did not work. Then I found this post How to access a directory in hosts machine from inside a docker container?, which suggests that you need to use the absolute file path in your mapping for both sides – host and container.
A little bit more on mapping
The syntax of mapping configuration file on the host file system to Docker is like this:
Docker absolute file in my case starts from (root/target/docker/stage/). Hence, the path starts from /opt/…
Note that you could map directory or a file. However, be careful. If you map directory to existing one, it will override it. For example, I mapped conf directory from the host to /opt/docker/conf directory on the container. The conf directory on the host consisted only of prod.conf file, while the one on the container consisted of many other files. When I ran my image, it displayed many error messages related to these files being missing. Apparently, docker replaced conf dir completely with the conf dir from the host. Eventually, I decide to just map the prod.conf file only. However, I gave it a unique name so it does not overrid an existing file with the same name
Ultimately, this what worked for me:
$ docker run -p 9000:9000 -v /home/flyingthots/deployments/conf/application.conf:/opt/docker/conf/outside.conf flying-thots-docker-image -Dconfig.file=/opt/docker/conf/outside.conf -Dplay.http.secret.key="hidemeonproduction"
This blog post, goes through other options for getting application configuration into Docker container.
Disclaimer: The featured image is taken from devout.io