In this blog we will create two docker container and link them together. We will first use mysql image and name that 'mysql', then containerize a simple java web application that links to the mysql container.
Lets begin with the mysql container, lets see the documentation https://hub.docker.com/_/mysql, how to start it.
$ docker run -d -p 3306:3306 --name mysql --rm -e MYSQL_ROOT_PASSWORD=redhat123 -e MYSQL_DATABASE=mydb -e MYSQL_USER=mydb_admin -e MYSQL_PASSWORD=redhat123 mysql:5.7.27
Lets also verify the database.
$ mysql -u mydb_admin -h 127.0.0.1 -p mydb
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.27 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [mydb]> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.001 sec)
MySQL [mydb]> exit
Bye
You can also run docker ps to check that the mysql container is up and running.
Now lets create our simple java web docker image. We begin by creating a new dockerwar/pom.xml, we use the template from http://magnus-k-karlsson.blogspot.com/2016/03/minimalistic-pom-for-java-ee-7.html, but change Java EE version to 8 and add mysql-connector-java dependency. Finally we strip the version from the build war file, by overriding <finalName>.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>se.magnuskkarlsson.example</groupId>
<artifactId>dockerwar</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputEncoding>UTF-8</project.build.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>
Then we create a simple static web page dockerwar/src/main/webapp/index.html
<!DOCTYPE html>
<html>
<head>
<title>Start Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
Now we need to write our Dockerfile. We will use wildfly for this. Lets open documentation and find latest tag - https://hub.docker.com/r/jboss/wildfly. Then we also need to understand a little more how the jboss wildfly docker image works, so lets open up the source code - https://github.com/jboss-dockerfiles/wildfly/blob/17.0.1.Final/Dockerfile.
FROM jboss/wildfly:17.0.1.Final
COPY target/dockerwar.war $JBOSS_HOME/standalone/deployments
Now lets test our docker image.
$ mvn clean install
$ docker build -t dockerwar:1.0.0 .
$ docker run -it -p 8080:8080 --name dockerwar --rm dockerwar:1.0.0
$ curl http://127.0.0.1:8080/dockerwar/
Now lets implement a super simple JDBC call from the java web app - src/main/webapp/mysql.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="java.sql.*"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>MYSQL</title>
</head>
<body>
<h1>MYSQL</h1>
<p>
<%
Class.forName("com.mysql.jdbc.Driver");
Connection connection = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://mysql:3306/mydb", "mydb_admin", "redhat123");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT 1");
while (resultSet.next()) {
out.println(resultSet.getString(1) + ", ");
}
} finally {
if (connection != null) {
try {
connection.close();
} catch (Exception IGNORE) {
}
}
}
%>
</p>
</body>
</html>
Then rebuild java web app och docker image.
$ mvn clean install
$ docker build -t dockerwar:1.0.0 .
But when we start the java web app, we run the docker container in background and add --link mysql.
$ docker run -d -p 8080:8080 --name dockerwar --rm --link mysql dockerwar:1.0.0
$ curl http://127.0.0.1:8080/dockerwar/mysql.jsp
So how does these linking work? Lets connect to the java web app docker container.
$ docker exec -it dockerwar bash
[jboss@8954c6a27efd ~]$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 mysql 625eb5301cf9
172.17.0.3 8954c6a27efd
We see that docker has added the mysql hostname to the /etc/hosts. We can also verify the IP by
$ docker inspect mysql | grep IP
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"IPAMConfig": null,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
And the docker container ID, by docker ps
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8954c6a27efd dockerwar:1.0.0 "/opt/jboss/wildfly/…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp dockerwar
625eb5301cf9 mysql:5.7.27 "docker-entrypoint.s…" 59 minutes ago Up 59 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql