Let’s Play! - My Play Framework Learning Journey (9) - Deploy Play Application to Docker

Running Play Application in Docker

To create a local Docker image for the RESTful service, add the following to build.sbt:

name := "my-service"
version := "0.1.0-SNAPSHOT"

enablePlugins(JavaAppPackaging)
enablePlugins(DockerPlugin)

dockerBaseImage := "openjdk:8"
dockerEntrypoint := Seq("bin/<your-app>", "-Denv=dev", "-Duser.timezone=\\\"+08:00\\\"")

Explanation of the additional command line parameters to the Docker entry point.

  • -Denv=dev - needed for selecting DatabaseConfig, as described in this post
  • -Duser.timezone - required for Oracle database. If this is not defined, an exception will be thrown.

After that you can run (Docker must be installed in your local environment):

sbt docker:publishLocal

This will create a local image with tag “name:version” in your local Docker environment.

Dealing with Sensitive Information

No sensitive information such as encrypted password should be included in the Docker image produced. Such information should be passed in during run time. For more information on password decryption, refer to this post

One way is to use environment variables. Docker-compose allows environment variables to be kept in a file and passed in when the container is started. On the other hand, Play allows reading of properties from environment variables.

So in order to run the Docker image created with a database that requires user name and password, we can do:

  • Create another conf file called credentials-env.conf. In this file will map the configuration values to environment variables using Play’s ${?} notation. For example:
my_db {
  db {
    user = ${?MY_API_PLAY_USER}
    key = ${?MY_API_PLAY_KEY}
    iv = ${?MY_API_PLAY_IV}
    password = ${?MY_API_PLAY_PASSWORD}
  }
}
  • Include the credentials-env.conf file in application.conf. Since for running in non-Docker environment, you may need another set of credentials, we can define the inclusion order such that if present, credentials-env.conf will override credentials.conf file.
...
include "credentials"
include "credentials-env"
...
  • Create a file (e.g. “devsecrets.env”) containing the following environment variables. Take note of the need to use quotes for special characters if any in the Base64 encoded values.
MY_API_PLAY_USER=<user_name>
MY_API_PLAY_KEY='<key>'
MY_API_PLAY_IV='<iv>'
MY_API_PLAY_PASSWORD='<encrypted password>'

The keys should match those ${?} variable names in credentials-env.conf so that Play will substitute them with their values.

  • Create a docker-compose YAML file specifying published image and the env variable file name. Examples can be found in the project root folder.
my-api:
    image: my-api:0.1.0-SNAPSHOT
    ports:
        - "9000:9000"
    env_file:
        - ./conf/devsecrets.env
  • Start up the Docker service:
docker stack deploy --compose-file=docker-compose.yml my-api

Note: Credentials passed into Docker container in this way will still be visible from a Docker service inspect command output, but they will not be available inside the Docker image.

Additional References

Go Top
comments powered by Disqus