Docker makes use of Linux Kernel features like control groups and namespaces to create isolated execution spaces (containers) on the top of the host operating system.
It allows to isolate deployed applications by assigning the container holding the application with its own resources (network, filesystem, etc).
Let’s think how we ship cargo through the seas. We put the cargo in the container, typically in layers from the back to the front, then we close the container and ship it through the seas over a boat. At the destination, our cargo looks pretty much the same as when it was during departure.
Build once, run everywhere
But How does this differs from a virtual machine? Their biggest goal is pretty much the same: isolation. The most basic difference is that containers share the underlying operating system whilst virtual machines run over hypervisors that are all about emulating virtual hardware. This makes containers a lot more reliable in terms of stability and performance.
What we are going to do?
We are going to cover how to deploy Cassandra DB and a Spring Boot application through Docker containers and how to make them communicate with each other. The full code for the Spring Boot using Cassandra project can be accessed in this GitHub repository.
This post will not cover the Docker installation process as there are already plenty of information around. Please follow the official documentation and let’s just assume you have it installed.
Let’s just play around with Docker for a while. Docker provides the ability of building images of the container with our software on it. The image build is instructed as stated in a file named Dockerfile.
The beauty of Docker images is that they are not only a way of making your application portable, but they can be also used as building blocks for more complex application stacks.
So let’s see an example:
That Dockerfile is counting on a local Ruby source file named hello.rb. We can create it with the following contents:
Now we just need to build our image and run our application.
For details on all Dockerfile commands please check the official documentation.
To be able to deploy Cassandra we will need to understand the steps it requires to deploy a Cassandra DB on any machine, and translate them into Dockerfile commands:
- Install Java (Cassandra requires Java 8 to work)
- Add the necessary groups and users
- Download and install Cassandra
- Apply the necessary post-installation configurations
- Expose cassandra ports
- Define how it will startup
Our Dockerfile will look like:
To be able to deploy a Cassandra cluster remotely, we need to change some default configurations. For that, a file config_cassandra.sh reads the current container IP and replaces it in the necessary Cassandra configuration fields.
It will only run when the container starts, as it is declared under a ENTRYPOINT command.
Building and Running it
To run it we just need to run the following command:
We just defined the name and the port mapping followed by the name of the image that we just created. You can use the flag -d with the run command to run in the background.
Containerizing Spring Boot application
Let’s say we have a simple spring boot application that provides the means to retrieve a list of users from a Cassandra table named “person” that belongs to the “sampleks” keyspace. Please check the implementation details here as the focus of this post is how we add it to Docker and allow it to communicate with the containerized Cassandra instance.
For adding this spring boot application into Docker, we need first to create the Dockerfile in the root path of our application, as below.
Building and Running it
If you are using Maven as in the example, it’s easier to build the image if we include the following plugin in our application’s POM. It allows to build the docker image out of a maven project.
Then we just need to use it integrated with Maven.
As we need our application to access our Cassandra DB, we need to make Spring Boot know about the existance of Cassandra DB. For that we need to link the containers.
The link has the form container-name:alias. The alias is used as a prefix to create environment variables associated with the target container. In this case a lot of variables will be created in Boot container with a reference to information about the remote container.
One of those variables is the Cassandra host address. So to short the example, let’s trick our spring boot application to use it when it’s defined. For that, our application.properties file shall be defined as follows:
Because of the way Spring Boot loads properties, if a system variable with the name DB_PORT_9042_TCP_ADDR is defined, it will be used instead of localhost.
Assuming everything went fine, you can just open your browser on port docker-ip:8080 and you will see a list of users. By this point you will just see an empty page because there’s no data in the database.
This was intentional for the example. We will be connecting to our cassandra instance and running CQL to insert data directly. To connect to our container and navigate inside it we will need to execute the following command:
Now you can refresh your browser’s page and then you should be able to see John and Anna there.
Docker is a powerful tool for isolating your application in the hosting environment. You can build it once, and ship it to everywhere and it is expected to have a consistent behaviour.
It’s also very useful for testing in isolation. You can build entire clusters and have them dedicated just for you without the need to request more machines or environments.
This post meant to be an introduction on how to deploy two containers that communicate with each other.
We covered several topics that can make us achieve container deployment with custom configuration, linking containers, and accessing them as if they were any other remote machine.
You can access the full example with the corresponding instructions in this GitHub repository.
subscribe via RSS