Dockerize a Spring Boot Application

This post will cover the basic concepts of Docker and Docker Compose and how it can be applied to setup the Spring Boot Application created in part one of the series.

What is Docker?

Docker allows an application and all its dependencies to be packaged in a Container that will always run the same regardless of the environment it's deployed in. The term "dependencies" here refers to the components an application needs to run, like Java, OS packages or libraries like ImageMagick, any other files or folders, basically anything that can installed on a server. The big difference between Docker and a Virtual Machine is that Docker Containers share the host operating system kernel, therefore it's lightweight, starts quickly and makes efficient use of RAM.

Docker Concepts

Docker Image

A Docker Image acts as a blueprint or template for a Docker Container. For example docker run ubuntu will create a newDocker Container based on the ubuntuDocker Image. The container does not modify the image in any way unless changes are explicitly committed. New images can easily be created by inheriting from existing images, online repositories like Docker Hub makes it easy to share and find images created by the community.

Dockerfile

The preferred way to create a Docker Image is with a script known as a Dockerfile. Alternatively the required changes can be made through running a shell on a container and then committing it to an image. Dockerfiles have the advantage of providing the ability to automate image creation and the syntax is simple, clear and self explanatory. The below example will create an image based on ubuntu and will run the echo "Hello docker!" command when a container is created from this image.

#Sample Dockerfile
FROM ubuntu
CMD "echo" "Hello docker!"

Docker Container

A Docker Containeris a running instance of a Docker Image and there can be many running instances of the same image. A Docker Volume can be used to persist changes to the file system in a Docker Container. Every time a docker run <image> command is run a new container is created from the given image. Docker Containers that expose ports can be mapped to a port on the host where the Docker Daemon is running with docker run -p 8080:80 <name|id>.

Docker Volumes

Changes an application makes to the filesystem (like writing log or database files) will not persist beyond the lifecycle of a Docker Container unless these files are written to a mounted Volume. A Volume remains available after a Docker Container that uses it is destroyed.

docker volume inspect <name|id> will show the mount point of the Volume. On OSX this mount point will reference a folder in the VirtualBox VM started by Docker Machine and not a local folder.

Docker Daemon

This is the process that manages Docker Containers. Since Docker makes use of Linux kernel features the Docker Daemon has to run on a virtual machine when using OSX. The Docker Machine utility can be used to setup a virtual machine on OSX. It also configures the OSX terminal (or iTerm) with environment variables that tells the docker cli where the Docker Daemon is running.

Docker Image Repository

Image Repositories act as the github of Docker Images. Images can be pushed and pulled from these repositories and both public and private repositories exist.

Docker Compose

Docker Composeis a tool that simplifies the configuration of multi Container applications. A single yaml file can be used to define all the required Containers, configure the networking between them, and the Volumes for persistence. A docker-compose up command will build and start all the containers defined in the docker-compose.yml file.

The configuration has two parts volumes and services. The volumes section shows the data Volumes required by the application to persist data. Launching the application will prompt for these Volumes to be created if they do not exist. The services section defines all the components of the application. The options defined for each service include, ports that need to be forwarded from the host, volumes that need to be mounted, and links that define dependencies between the services. Docker Compose maintains a complete reference of all the available options.

Links are by far the most interesting option, it exposes the dependency under a host name with the same name as the service. For example, the web service can connect to the db link by using mongodb://db.

fluentd - Collect all application logs and push it into Elasticsearch.

elasticsearch - Store application logs.

kibana - Provide an interface into the log data stored in Elasticsearch

The combination of fluentd, elasticsearch and kibana act as an alternative to Splunk.

Conclusion

“But it works on my machine”— Confused Developer

Docker is a powerful tool that will reduce issues caused by differences in development and production environments, by defining Docker Images that can be shared between the environments. Furthermore I believe it can be used as a tool to standardize development environments across team members and reduce the time new recruits need to get up and running.