
Preparing a Docker Compose Environment
Docker, the #1 choice for containerization in Java microservices applications, is one of the most-used tools in Java development today. But how developers deploy and orchestrate their Docker-based microservices can vary. Orchestrating via Kubernetes or a Docker Compose environment can each carry particular benefits.
In this article, we'll look at Docker Compose, environment variables, and provide a demonstration on how to set up your first Docker Compose environment.
Table of Contents
What Is Docker Compose?
Docker Compose is a powerful tool that allows developers to define and run multi-container Docker systems. As the name implies, it's dependent on Docker—a platform that delivers software packages in separate containers. A Docker Compose environment uses YAML files for configuring app services and allows developers to run concurrent commands on multiple containers.
Related Reading >> Docker Microservices in Java
Back to topPrepare a Docker Compose Environment
For this example, we are using an application called Petclinic, which uses an embedded H2 database. In some scenarios, Petclinic talks to the Supplements application over HTTP. Supplements uses MongoDB to fetch JSON data to send back to the Petclinic app, if requested.

For this task, building a custom Docker image is overkill. There are the stock images for Tomcat and MongoDB, which is a perfect fit for our demo. To configure all the pieces together and to escape command line horror, we will use Docker Compose.
Back to top1. Installing Docker Compose
With Docker Compose we need a docker-compose.yml file, which allows us to specify configuration in a declarative manner. Start with the minimal configuration for Tomcat:
petclinic:
image: tomcat
ports:
- "8000:8080"
This means we are declaring a petclinic
container instance that uses a tomcat
image. By executing the docker-compose up
command we are now able to start a container that hosts a Tomcat instance. By default, Tomcat starts on port 8080. By using the ports
attribute in the configuration we have exposed container’s port 8000 that points to Tomcat’s port 8080. Voila! Tomcat is running and is accessible at [container IP]:8000
2. Deploying the Web Application Into a Docker Container
Now, it would be quite cool to deploy a pre-built web application to a Tomcat instance running in that Docker container. Volumes are helpful in this situation, specified under the volumes
attribute in our configuration file. Using docker volumes is convenient when the artifact has to be updated frequently - this means we do not need to rebuild the image.
petclinic:
image: tomcat
ports:
- "8000:8080"
volumes:
- ./petclinic.war:/usr/local/tomcat/webapps/petclinic.war
The mapping is of course specific to this application. For instance, Tomcat’s webapp directory is located at /usr/local/tomcat/webapp. This is the path we need to use to be able to deploy our web application. The format for the mapping is [local path]:[remote path]. The assumption here is that the petclinic.war file is located in the same directory from which the docker-compose command is executed.
Back to top3. Run MongoDB in a Docker Container
Running MongoDB in a Docker container is even more trivial than running Tomcat:
db:
image: mongo
command: -nojournal
There is a stock image available which includes MongoDB. The db
instance of the container runs the MongoDB process with the default port exposed for our convenience.
4. Linking Docker Containers
The assumption is that every individual application will be deployed in its own instance of Tomcat, running in a dedicated container instance. The caveat here is that the containers have to be linked for the applications to be visible to each other. The links
attribute in docker-compose.yml is exactly how we can achieve this.
petclinic:
image: tomcat
ports:
- "8000:8080"
links:
- supplements
volumes:
- ./petclinic.war:/usr/local/tomcat/webapps/petclinic.war
environment:
- "JAVA_OPTS=-Dsupplements.host=supplements"
supplements:
image: tomcat
ports:
- "8888:8080"
links:
- db
volumes:
- ./supplements.war:/usr/local/tomcat/webapps/supplements.war
environment:
- "JAVA_OPTS=-Dmongo.host=db"
db:
image: mongo
command: -nojournal
The links
attribute declares that the the given container(s) can link to the other specified containers. In our case, petclinic
can link to supplements
, and supplements
can link to db
. The cool part is that the symbolic name (e.g. petclinic
) assigned to the container instances can be used for more than just linking containers; it will also be resolved as an argument. This is how we can use it to provide the additional configuration parameter to our web applications via environment variables.
5. Specifying Docker Compose Environment Variables
To pass additional environment variables, the environment
attribute is used in docker-compose.yml. For Tomcat, we can specify JAVA_OPTS
environment variable to pass any extra configuration parameters. In the example we’re passing the symbolic name of the linked container for the application to be able to access the linked resource via a network call:
environment:
- "JAVA_OPTS=-Dmongo.host=db"
It adds a requirement to the application to use the Docker Compose environment variable via System.getProperty.
Back to top6. Configuring XRebel
Volumes and environment configuration are the two elements that we need to configure a Java agent. This time we want to use XRebel to profile end-to-end transactions for the applications running in Docker. So we just need one more entry to specify the location of xrebel.jar file:
volumes:
- ./xrebel.jar:/xrebel.jar
And also add the -javaagent
VM argument to JAVA_OPTS
environment variable for both Tomcats:
- "JAVA_OPTS=-javaagent:/xrebel.jar -Dmongo.host=db"
So the full configuration for the Petclinic container will look like this:
version: "3.9"
services:
petclinic:
image: tomcat
ports:
- "8000:8080"
links:
- supplements
- db
volumes:
- ./xrebel.jar:/xrebel.jar
- ~/.xrebel/xrebel.lic:/root/.xrebel/xrebel.lic
- ./petclinic.war:/usr/local/tomcat/webapps/petclinic.war
environment:
- "JAVA_OPTS=-javaagent:/xrebel.jar -Dsupplements.host=supplements"
Back to topFinal Thoughts
Docker Compose is a wonderful tool that streamlines the process of setting up complex environments for production or for demo purposes. In this post we looked at how Docker Compose enables you to:
- Easily prepare a demo environment that can be shared with the team.
- Escape the need to build your own images, write Dockerfile, or tinker with Docker command line arguments.
Free Timesaver for Java Developers
While XRebel is no longer available to new users, its sister, JRebel, helps Java developers save hours of time by eliminating redeploys.
Click the button below to try JRebel free for 10 days. Or you can learn more about it first here.
Note: This post was originally published on April 11, 2016 and has been updated for accuracy and comprehensiveness.
Back to top