Cross-posted from www.voxxed.com/blog/2015/03/9-docker-recipes-for-java-ee-applications/
So, you’d like to start using Docker for Java EE applications?
A typical Java EE application consists of an application server, such as WildFly, and a database, such as MySQL. In addition, you might have a separate front-end tier, say Apache, for load balancing a number of application server. A caching layer, such as Infinispan, may be used to improve overall application performance. Messaging system, such as ActiveMQ, may be used for processing queues. Both the caching and messaging components could be setup as a cluster for further scalability.
This Tech Tip will show some simple Docker recipes to configure your containers that use application server and database. Subsequent blog will cover more advanced recipes that will include front-end, caching, messaging, and clustering.
Lets get started!
Docker Recipe #1: Setup Docker using Docker Machine
If Docker is not already setup on your machine, then as a first step, you need to set it up. If you are on a recent version of Linux then you already have Docker. Or optionally can be installed as:
1
2
3
|
sudo apt-get install docker.io
|
On Mac and Windows, this means installing boot2docker which is a Tinycore Linux VM and comes with Docker host. Then you need to configure ssh keys and certificates.
Fortunately, this is extremely simplified using Docker Machine. It takes you from zero-to-Docker on a host with a single command. This host could be your laptop, in the cloud, or in your data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.
This recipe is explained in detail in Docker Machine to Setup Docker Host.
Docker Recipe #2: Application Server + In-memory Database
One of the cool features of Java EE 7 is the default database resource. This allows you to not worry about creating a JDBC resource in an application server-specific before your application is accessible. Any Java EE 7 compliant application server will map the default JDBC resource name (java:comp/DefaultDataSource
) to the application server-specific resource in the bundled database server.
For example, WildFly comes bundled with H2 in-memory database. This database is ready to be used as soon as WildFly is ready to accept your requests. This simplifies your development efforts and allows you to do a rapid prototyping. The default JDBC resource is mapped to
java:jboss/datasources/ExampleDS
which is then mapped to the JDBC URL of jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
.
In such a case, the Database server is another application running inside the Application server.
Here is the command that runs Java EE 7 application in WildFly:
1
2
3
|
docker run -it -p 8080:8080 arungupta/javaee7-hol
|
If you want to run a typical Java EE 7 application using WildFly and H2 in-memory database, then this Docker recipe is explained in detail in Java EE 7 Hands-on Lab on WildFly and Docker.
Docker Recipe #3: Two Containers on Same Host Using Linking
The previous recipe gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost after the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server.
To keep things simple, both the database server and application server can run on the same host.
Docker Container Links are used to link the two containers. Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container. In our case, target container (WildFly) can see information about source container (MySQL). The important part to understand here is that none of this information needs to be publicly exposed by the source container, and is only made available to the target container.
Here are the commands that start the MySQL and WildFly containers and link them:
1
2
3
4
|
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -d mysql
docker run --name mywildfly --link mysqldb:db -p 8080:8080 -d arungupta/wildfly-mysql-javaee7
|
WildFly and MySQL linked on two Docker containers explains how to set up this recipe.
Docker Recipe #4: Two Containers on Same Host Using Fig
The previous recipe require you to run the containers in a specific order. Running multi-container applications can quickly become challenging if each tier of your application is sitting in a container. Fig (deprecated in favor of Docker Compose) is a Docker Orchestration Tool that:
- Define multiple containers in a single configuration file
- Create dependencies between two containers by creating links between them
- Start containers in the right sequence
The entry point for Fig is a configuration file as shown:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
mysqldb:
image: mysql:latest
environment:
MYSQL_DATABASE: sample
MYSQL_USER: mysql
MYSQL_PASSWORD: mysql
MYSQL_ROOT_PASSWORD: supersecret
mywildfly:
image: arungupta/wildfly-mysql-javaee7
links:
- mysqldb:db
ports:
- 8080:8080
|
and all the containers can be started as:
1
2
3
|
fig up -d
|
Docker orchestration using Fig explains this recipe in detail.
Fig is only receiving updates. Its code base is used as basis for Docker Compose. This is explained in the next recipe.
Docker Recipe #5: Two Containers on Same Host Using Compose
Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running.
The application configuration file is the same format as from Fig. The containers can be started as:
1
2
3
|
docker-compose up -d
|
This recipe is explained in detail in Docker Compose to Orchestrate Containers.
Docker Recipe #6: Two Containers on Different Hosts using IP Address
In the previous recipe, the two containers are running on the same host. These two could easily communicate using Docker linking. But simple container linking does not allow cross-host communication.
Running containers on the same host means you cannot scale each tier, database or application server, independently. This is where you need to run each container on a separate host.
MySQL container can start as:
1
2
3
|
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 5306:3306 -d mysql
|
JDBC resource can be created as:
1
2
3
|
data-source add --name=mysqlDS --driver-name=mysql --jndi-name=java:jboss/datasources/ExampleMySQLDS --connection-url=jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/sample?useUnicode=true&characterEncoding=UTF-8 --user-name=mysql --password=mysql --use-ccm=false --max-pool-size=25 --blocking-timeout-wait-millis=5000 --enabled=true
|
And WildFly container can start as:
1
2
3
|
docker run --name mywildfly -e MYSQL_HOST=<IP_ADDRESS> -e MYSQL_PORT=5306 -p 8080:8080 -d arungupta/wildfly-mysql-javaee7
|
Complete details for this recipe is explained in Docker container linking across multiple hosts.
Docker Recipe #7: Two Containers on Different Hosts using Docker Swarm
Docker Swarm is native clustering for Docker. It turns a pool of Docker hosts into a single, virtual host. It picks-up where Docker Machine leaves off by optimizing host resource utilization and providing failover services. Specifically, Docker Swarm allows users to create resource pools of hosts running Docker daemons and then schedule Docker containers to run on top, automatically managing workload placement and maintaining cluster state.
More details about this recipe are coming in a subsequent blog.
Docker Recipe #8: Deploy Java EE Application from Eclipse
Last recipe will deal with how to deploy your existing applications to a Docker container.
Lets say you are using JBoss Tools as your development environment and WildFly as your application server.
There are a couple of ways by which these applications can be deployed:
- Use Docker volumes + Local deployment: Here a directory on your local machine is mounted as a Docker Volume. WildFly Docker container is started by mapping that directory to the deployment directory as:
123docker run -it -p 8080:8080 -v /Users/arungupta/tmp/deployments:/opt/jboss/wildfly/standalone/deployments/:rw jboss/wildfly - Use WildFly management API + Remote deployment: Start WildFly Docker container, and additionally expose the management port 9990 as:
123docker run -it -p 8080:8080 -p 9990:9990 arungupta/wildfly-management
This recipe is explained in detail at Deploy to WildFly and Docker from Eclipse.
Docker Recipe #9: Test Java EE Applications using Arquillian Cube
Arquillian Cube allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually. Cube uses Docker REST API to talk to the container. It uses the remote adapter API, for example WildFly in this case, to talk to the application server. Docker configuration is specified as part of the maven-surefire-plugin as:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<configuration>
<systemPropertyVariables>
<arquillian.launch>wildfly-docker</arquillian.launch>
<arq.container.wildfly-docker.configuration.username>admin</arq.container.wildfly-docker.configuration.username>
<arq.container.wildfly-docker.configuration.password>Admin#70365</arq.container.wildfly-docker.configuration.password>
<arq.extension.docker.serverVersion>1.15</arq.extension.docker.serverVersion>
<arq.extension.docker.serverUri>http://127.0.0.1:2375</arq.extension.docker.serverUri>
<arq.extension.docker.dockerContainers>
wildfly-docker:
image: arungupta/javaee7-samples-wildfly
exposedPorts: [8080/tcp, 9990/tcp]
await:
strategy: polling
sleepPollingTime: 50000
iterations: 5
portBindings: [8080/tcp, 9990/tcp]
</arq.extension.docker.dockerContainers>
</systemPropertyVariables>
</configuration>
|
Complete details about this recipe are available on Run Java EE Tests on Docker using Arquillian Cube.
What other recipes are you using to deploy your Java EE applications using Docker?
Enjoy!
The APT package name for Docker Recipe #1 should be docker.io and not docker-io.
sudo apt-get install docker.io
Thanks for the catch, updated.
Hello Arun,
Thanks for your great article. You used WildFly as application server for your examples but have you an idea when an official docker image will be available for JBoss EAP 6 ?
Thanks In advance.
Hello Arun,
Great article!
Can you tell me if it’s possible to use mysql in the same container of the wildfly without link containers?
Thanks
Guilherme,
Docker containers does one thing, and they do that well. So unless you start MySQL embedded within your application, it would not be possible to run MySQL and WildFly together in the same container.
Either way, using MySQL in the same container as WildFly is not a recommended design pattern as that creates a SPOF for your application.
Hi,
Could you able to config docker based wildfly cluster ?
Thanks
Hello Arun,
If we want to configure datasources, messaging in containers, is there an approach for this?
Because datasources, username and passwords differs with environment so I am confused on how to configure them differently each time the container is used in different environment.
Also storing passwords in plain text is not an option as its against the security principles.
Have you come across such situations?
Would be helpful if you could show a way.
These are typically configured using environment variables.
Sharing non-clear passwords is app-server specific and AFAIK Docker does not introduce any dependency there.
i think there is mistake in –link mysql:db instead it should be –link mysql:sample for the given example