Dockerized microservices with a datastore

October 17, 2016

I have created a sample repository where I experiment how to setup dockerized microservices with different datastores. In this blog post I will go through the sample using mysql datastore.

Below you can find the Dockerfile for the mysql-datastore image. Leveraging the official mysql image from Docker Hub and using couple of environment variables the mysql container is configured. MYSQL_RANDOM_ROOT_PASSWORD environment variable set to yes makes sure that a random password for the root user will be generated and printed to the standard output in the container. The user identified with MYSQL_USER will be granted superuser permissions for the database specified by the MYSQL_PASSWORD.

FROM mysql:5.7.15
MAINTAINER [email protected]

The sample contains another Dockerfile which sets up a simple Spring Boot app using the previous mysql service.

# The smallest Docker image with OracleJDK 8 (167MB)
FROM frolvlad/alpine-oraclejdk8:slim

# add bash and coreutils
RUN apk add --no-cache bash coreutils

MAINTAINER [email protected]

# We added a VOLUME pointing to "/tmp" because that is where a Spring Boot application creates working directories for
# Tomcat by default. The effect is to create a temporary file on your host under "/var/lib/docker" and link it to the
# container under "/tmp". This step is optional for the simple app that we wrote here, but can be necessary for other
# Spring Boot applications if they need to actually write in the filesystem.

# The project JAR file is ADDed to the container as "app.jar"
ADD mysql-sample-0.0.1-SNAPSHOT.jar app.jar

# script files related to check if the datastore is “ready”


# You can use a RUN command to "touch" the jar file so that it has a file modification time
# (Docker creates all container files in an "unmodified" state by default)
# This actually isn’t important for the simple app that we wrote, but any static content (e.g. "index.html")
# would require the file to have a modification time.
RUN bash -c 'touch /app.jar'

CMD ["./"]

I use the wait-for-it bash script to test and wait for the availability of the TCP host and port where the mysql service will be available.


# wait for 15 seconds until mysql is up
./ -t 15 mysql:3306

if [ $? -eq 0 ]
  # To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.
  java -jar app.jar

With the help of docker-mave-plugin the altfatterz/mysql-sample and altfatterz/mysql images are generated during maven package phase.

            <!-- bind docker commands to maven phases -->
                <!-- the contents of dockerDirectory will be copied into ${}/docker folder -->
            <!-- bind docker commands to maven phases -->
                <!-- Use the resources element to copy additional files, such as the service's jar file -->

And finally with Docker Compose I can start both services with a single command. Note here that the depends_on only guarantees the order of the service startup, in this case mysql-datastore will be started first. Docker Compose does not wait until a container is “ready”, that is why I needed to use the wait-for-it wrapper script.

version: '2'
    container_name: mysql-datastore
    image: altfatterz/mysql
    # expose 3306 port to host, handy to inspect the database from the host machine
      - "3306:3306"
    container_name: service-using-mysql-datastore
    image: altfatterz/mysql-sample
    # docker-compose will start services in dependency order. Here mysql service will be started before web
    # depends_on will not wait for mysql to be "ready" before starting "web". If you need a service to be ready see
      - mysql
    # open ports for tomcat and remote debugging
      - "8080:8080"
      - "8000:8000"
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql/db?autoReconnect=true&useSSL=false

After running docker-compose up you can see the followings

Creating mysql-datastore
Creating service-using-mysql-datastore
Attaching to mysql-datastore, service-using-mysql-datastore
mysql-datastore | Initializing database
mysql-datastore | 2016-10-17T20:07:14.424157Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
service-using-mysql-datastore | waiting 15 seconds for mysql:3306
mysql-datastore | Database initialized
mysql-datastore | MySQL init process in progress...
mysql-datastore | GENERATED ROOT PASSWORD: eeng4eeth3ahween2soh9raixaC1Eir0
mysql-datastore | MySQL init process done. Ready for start up.
mysql-datastore | Version: '5.7.15'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
service-using-mysql-datastore | mysql:3306 is available after 14 seconds
service-using-mysql-datastore |
service-using-mysql-datastore |   .   ____          _            __ _ _
service-using-mysql-datastore |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
service-using-mysql-datastore | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
service-using-mysql-datastore |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
service-using-mysql-datastore |   '  |____| .__|_| |_|_| |_\__, | / / / /
service-using-mysql-datastore |  =========|_|==============|___/=/_/_/_/
service-using-mysql-datastore |  :: Spring Boot ::        (v1.4.1.RELEASE)
service-using-mysql-datastore |
service-using-mysql-datastore | 2016-10-17 20:07:30.831  INFO 43 --- [           main] com.example.DemoApplication              : Starting DemoApplication v0.0.1-SNAPSHOT on a1e7526b0a91 with PID 43 (/app.jar started by root in /)

There are other samples using Riak and MongoDB in this repository and I am planning to add more in the future.