WildFly/JavaEE7 and MySQL linked on two Docker containers (Tech Tip #65)
Tech Tip #61 showed how to run Java EE 7 hands-on lab on WildFly Docker container. A couple of assumptions were made in that case:
- WildFly bundles H2 in-memory database. The Java EE 7 application uses the default database resource, which in case of WildFly, gets resolved to a JDBC connection to that in-memory database. This is a good way to start building your application but pretty soon you want to start using a real database, like MySQL.
- Typically, Application Server and Database may not be residing on the same host. This reduces the risk by avoiding a single point of failure. And so WildFly and MySQL would be on to separate host.
There is plethora of material available to show how to configure WildFly and MySQL on separate hosts. What are the design patterns, and anti-patterns, if you were to do that using Docker?
Lets take a look!
In simplified steps:
- Run the MySQL container as:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -d mysql
- Run the WildFly container, with MySQL JDBC resource pre-configured, as:
docker run --name mywildfly --link mysqldb:db -p 8080:8080 -d arungupta/wildfly-mysql-javaee7
- Find the IP address of the WildFly container:
sudo docker inspect -f '{{ .NetworkSettings.IPAddress }}' mywildfly
If you are on a Mac, then use
boot2docker ip
to find the IP address. - Access the application as:
curl http://<IP_ADDRESS>:8080/employees/index.html
to see the output as:
The application is a trivial Java EE 7 application that publishes a REST endpoint. Access it as:
curl http://localhost:8080/employees/resources/employees/
to see:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
If you are interested in nitty gritty, read further details.
Linking Containers
The first concept we need to understand is how Docker allows linking 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.
The magic switch to enable link is, intuitively, --link
. So for example, if MySQL and WildFly containers are run as shown above, then --link mysqldb:db
links the MySQL container named mysqldb
with an alias db
to the WildFly target container. This defines some environment variables, following the defined protocol, in the target container which can then be used to access information about the source container. For example, IP address, exposed ports, username, passwords, etc. The complete list of environment variables can be seen as:
[arun@localhost wildfly-mysql-javaee7]$ sudo docker run --name mywildfly --link mysqldb:db -p 8080:8080 -it arungupta/wildfly-mysql-javaee7 env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=4e0458981a82 TERM=xterm DB_PORT=tcp://172.17.0.24:3306 DB_PORT_3306_TCP=tcp://172.17.0.24:3306 DB_PORT_3306_TCP_ADDR=172.17.0.24 DB_PORT_3306_TCP_PORT=3306 DB_PORT_3306_TCP_PROTO=tcp DB_NAME=/mywildfly3/db DB_ENV_MYSQL_USER=mysql DB_ENV_MYSQL_PASSWORD=mysql DB_ENV_MYSQL_DATABASE=sample DB_ENV_MYSQL_ROOT_PASSWORD=supersecret DB_ENV_MYSQL_MAJOR=5.6 DB_ENV_MYSQL_VERSION=5.6.22 JAVA_HOME=/usr/lib/jvm/java WILDFLY_VERSION=8.2.0.Final JBOSS_HOME=/opt/jboss/wildfly HOME=/opt/jboss
So you can see there are DB_*
environment variables providing plenty of information about source container.
Linking only works if all the containers are running on the same host. A better solution will be shown in the subsequent blog, stay tuned.
Override default Docker command
Dockerfile for this image inherits from jboss/wildfly:latest and starts the WildFly container. Docker containers can only run one command but we need to install JDBC driver, create JDBC resource using the correct IP address and port, and deploy the WAR file. So we will override the command by inheriting from jboss/wildfly:latest and use a custom command. This command will do everything that we want to do, and then start WildFly as well.
The custom command does the following:
- Add MySQL module
- Add MySQL JDBC driver
- Add the JDBC data source using IP address and port of the linked MySQL container
- Deploy the WAR file
- Start WildFly container
Note, WildFly is starting with -b 0.0.0.0
that allows it to be bound to any IP address. Also, the command needs to run in foreground so that the container stays active.
Customizing security
Ideally, you’ll poke holes in the firewall to enable connection to specific host/ports. But these instructions were tried on Fedora 20 running in Virtual Box. So for convenience, the complete firewall was disabled as:
[arun@localhost wildfly-mysql-javaee7]$ sudo docker run --name mywildfly --link mysqldb:db -p 8080:8080 -it arungupta/wildfly-mysql-javaee7 env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=4e0458981a82 TERM=xterm DB_PORT=tcp://172.17.0.24:3306 DB_PORT_3306_TCP=tcp://172.17.0.24:3306 DB_PORT_3306_TCP_ADDR=172.17.0.24 DB_PORT_3306_TCP_PORT=3306 DB_PORT_3306_TCP_PROTO=tcp DB_NAME=/mywildfly3/db DB_ENV_MYSQL_USER=mysql DB_ENV_MYSQL_PASSWORD=mysql DB_ENV_MYSQL_DATABASE=sample DB_ENV_MYSQL_ROOT_PASSWORD=supersecret DB_ENV_MYSQL_MAJOR=5.6 DB_ENV_MYSQL_VERSION=5.6.22 JAVA_HOME=/usr/lib/jvm/java WILDFLY_VERSION=8.2.0.Final JBOSS_HOME=/opt/jboss/wildfly HOME=/opt/jboss
In addition, a Host-only adapter was added using Virtual Box settings and looks like:
That’s it, that should get you going to to use WildFly and MySQL on two separate containers.
Also verified the steps on boot2docker, and it worked seamlessly there too:
docker-images> docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -d mysql docker-images> docker-images> docker run --name mywildfly --link mysqldb:db -p 8080:8080 -d arungupta/wildfly-mysql-javaee7 Unable to find image 'arungupta/wildfly-mysql-javaee7' locally Pulling repository arungupta/wildfly-mysql-javaee7 791773b0e1de: Download complete 511136ea3c5a: Download complete 782cf93a8f16: Download complete 7d3f07f8de5f: Download complete 1ef0a50fe8b1: Download complete 20a1abe1d9bf: Download complete cd5bb934bb67: Download complete 379edb00ab07: Download complete 4d37cbbfc67d: Download complete 2ea8562cac7c: Download complete 7759146eab1a: Download complete b17a20d6f5f8: Download complete e02bdb6c4ed5: Download complete 72d585299bb5: Download complete 90832e1f0bb9: Download complete 2c3484b42034: Download complete 38fad13dea25: Download complete 656878d9a6c6: Download complete 6510de96c354: Download complete 0cc86be8ac93: Download complete cc4e21e8b0e7: Download complete Status: Downloaded newer image for arungupta/wildfly-mysql-javaee7:latest 8522df362e57f5b7a5324dba692559b971c7cfda4a687212c44b1118008a4c63 docker-images> curl http://192.168.59.103:8080/employees/index.html
docker-images> curl http://192.168.59.103:8080/employees/resources/employees/ 1Penny2Sheldon3Amy4Leonard5Bernadette6Raj7Howard8Priya
Source code for the image is at github.com/arun-gupta/docker-images/tree/master/wildfly-mysql-javaee7.
Enjoy!
Reference: | WildFly/JavaEE7 and MySQL linked on two Docker containers (Tech Tip #65) from our JCG partner Arun Gupta at the Miles to go 2.0 … blog. |