Introduction to Multi Docker Containers
Bhaskar S | 04/07/2017 |
Overview
In the article Introduction to Dockerfile, we demonstrated how one could build custom Docker images using Dockerfile.
Enterprise applications are typically multi-tier. For example, a web application consists of a business tier (hosted on an application server like Tomcat) and a backend data tier (hosted on a database server like MySQL).
To emulate the production application stack in development, a developer could run the business tier in one Docker container and the data tier in another Docker container. But, how would one "tie" these multiple containers together so as to emulate what is in production ???
In this article, we will demonstrate how to link 2 containers to emulate a simple web application using the docker run command.
Setup
For this multi-container demonstration, we will use the base Docker image mysql:5.7.17 for the data tier and the base Docker image tomcat:8.5.13-jre8 for the business tier.
Data Tier (MySQL)
For the MySQL based data tier, we expect to have a database called hellodb with the user-id admin and with credential s3cret.
In the database hellodb, we expect to have a single database table called user_count with 2 columns - a name column and a count column.
Let us assume the current directory is /home/alice.
Create a directory called mysql under the current directory and change to that directory. The current directory now would be /home/alice/mysql.
Create the following SQL script called mysql-setup.sql in the current directory. This SQL script will be used to setup and initialize the desired database table:
Next, create the following Dockerfile in the current directory. It will be used to build our MySQL based Docker container for the data tier:
Now, let us pull the base Docker image mysql:5.7.17 by executing the following command:
$ docker pull mysql:5.7.17
The following would be a typical output:
5.7.17: Pulling from library/mysql 6d827a3ef358: Pull complete ed0929eb7dfe: Pull complete 03f348dc3b9d: Pull complete fd337761ca76: Pull complete 7e6cc16d464a: Pull complete ca3d380bc018: Pull complete 3fe11378d5c0: Pull complete 2b5dfd325645: Pull complete b54281d17fbe: Pull complete 7eae4db8eea5: Pull complete 76cf68e17b09: Pull complete Digest: sha256:49b7d6d8d45f8c3300cba056e8cdf36c714d99e0b40f7005b9e6e75e64ecdf7c Status: Downloaded newer image for mysql:5.7.17
Finally, execute the following command to build the data tier Docker image using the Dockerfile we just created:
$ docker build -t mysql_hellodb .
The following would be a typical output:
Sending build context to Docker daemon 3.072 kB Step 1 : FROM mysql:5.7.17 ---> 9546ca122d3a Step 2 : ENV MYSQL_ROOT_PASSWORD "r00t" ---> Running in f5a6ae953c1c ---> a86039294085 Removing intermediate container f5a6ae953c1c Step 3 : ENV MYSQL_USER "admin" ---> Running in 548a10861cce ---> 8bbf1ea32ae9 Removing intermediate container 548a10861cce Step 4 : ENV MYSQL_PASSWORD "s3cret" ---> Running in 31ffb4126389 ---> 4a82db9e201e Removing intermediate container 31ffb4126389 Step 5 : ENV MYSQL_DATABASE "hellodb" ---> Running in 10eec68ec099 ---> 10cf7415e7b4 Removing intermediate container 10eec68ec099 Step 6 : LABEL Version "1.0" Author "Bhaskar.S" Email "bswamina@polarsparc.com" ---> Running in cbff3bb6a6c2 ---> 3db1dbc3f4fe Removing intermediate container cbff3bb6a6c2 Step 7 : ADD mysql-setup.sql /docker-entrypoint-initdb.d ---> fae9253e0f4d Removing intermediate container 795ca26199d4 Successfully built fae9253e0f4d
Business Tier (Tomcat)
For the Tomcat based business tier, we will deploy a simple servlet that will read and update a value from the user_count table in the hellodb database and display a single line result.
Change the current directory back to /home/alice.
Create a directory called tomcat under the current directory and change to that directory. The current directory now would be /home/alice/tomcat.
We will be leveraging Apache Maven for build and package management of our simple servlet project. Make sure Apache Maven is properly installed and setup on the host.
Execute the following command to setup the basic web application Maven project directory structure:
$ mvn archetype:generate -DgroupId="com.polarsparc" -DartifactId="hello" -Dversion="1.0" -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
The following is how the hello project directory structure would look after the above command completes:
Change to the directory hello/src/main and create an additional directory strucures as shown below:
$ cd hello/src/main
$ mkdir -p java/com/polarsparc
$ mkdir -p webapp/META-INF
$ cd ../../..
The following is how the hello project directory structure should look after executing the above commands:
First, create the following pom.xml file inside the hello project directory:
Second, create the following context.xml file in the hello/src/main/webapp/META-INF directory:
Third, update the web.xml file located in the hello/src/main/webapp/WEB-INF directory to look as follows:
Fourth, create the following log4j.properties file in the hello/src/main/resources directory:
Finally, create the following HelloServlet3.java file in the hello/src/main/java/com/polarsparc directory:
In the end, the following is how the hello project directory structure should look:
To build and package the Maven project, execute the following command in the hello directory:
$ mvn clean package
Once the above command finishes, one should find the helloworld3.jar file in the hello/target directory.
Next, create the following Dockerfile in the current directory. It will be used to build our Tomcat based Docker container for the business tier:
Now, let us pull the base Docker image tomcat:8.5.13-jre8 by executing the following command:
$ docker pull tomcat:8.5.13-jre8
The following would be a typical output:
8.5.13-jre8: Pulling from library/tomcat 6d827a3ef358: Already exists 2726297beaf1: Pull complete d6e483851652: Pull complete ef624abeb7b8: Pull complete 0e108ce2208d: Pull complete 6a77bcb48281: Pull complete 016fd08a71c8: Pull complete 97c72b1a17df: Pull complete b9f2ccd12a13: Pull complete 0e54b0c11e81: Pull complete 37da287a8961: Pull complete 6cef72a72237: Pull complete a675c4562932: Pull complete Digest: sha256:d6bc16eec9f85c5efdac8d3918dfd240ddf6151cd288ac45ae97458864c81dd9 Status: Downloaded newer image for tomcat:8.5.13-jre8
Finally, execute the following command to build the business tier Docker image using the Dockerfile we just created:
$ docker build -t tomcat_hellodb .
The following would be a typical output:
Sending build context to Docker daemon 4.467 MB Step 1 : FROM tomcat:8.5.13-jre8 ---> 40ab38c1ce33 Step 2 : LABEL Version "1.0" Author "Bhaskar.S" Email "bswamina@polarsparc.com" ---> Using cache ---> dc595ef8eb96 Step 3 : ADD helloworld3.war /usr/local/tomcat/webapps/ ---> 8c46aa7c76bd Removing intermediate container 54853c073930 Successfully built 8c46aa7c76bd
Change the current directory back to /home/alice.
Hands-on with Multi Docker Containers
In this section, we will demonstrate how one could link the multiple containers (data and business tier containers in our example) using the docker run command.
To list all the Docker Images on the local host, execute the following command:
$ docker images
The following could be a typical output:
REPOSITORY TAG IMAGE ID CREATED SIZE mysql_hellodb latest fae9253e0f4d 5 days ago 407 MB tomcat_hellodb latest 8c46aa7c76bd 5 days ago 368.2 MB tomcat 8.5.13-jre8 40ab38c1ce33 7 days ago 366.7 MB mysql 5.7.17 9546ca122d3a 8 days ago 407 MB ubuntu_flask latest 54f0fa012cd1 12 days ago 239.8 MB mycentos latest 91b1f32a62f3 13 days ago 273.3 MB centos latest 98d35105a391 3 weeks ago 192.5 MB ubuntu latest 0ef2e08ed3fa 5 weeks ago 130 MB ubuntu 14.04 7c09e61e9035 5 weeks ago 188 MB
Create a directory called data under the current directory. The current directory should be /home/alice.
First start the data tier, which is the MySQL based Docker image with the name mysql_hellodb, using the following command:
$ docker run -v /home/alice/data:/var/lib/mysql -d --name mysql mysql_hellodb
Notice the use of the command line options --name and -v in the command above.
The --name option is used to reference a container for networking (like a host name). The specified name mysql will be used below when we launch the business tier container.
The -v option mounts the directory /home/alice/data on the local host into the container at /var/lib/mysql. This allows the database data to be preserved for future runs.
The following would be a typical output:
7541f659e7a66914bdb04de1bccb9148707d12ded31a454a7adac34cbb3ade71
To list all the running Docker containers, execute the following command:
$ docker ps
The following would be a typical output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7541f659e7a6 mysql_hellodb "docker-entrypoint.sh" 14 seconds ago Up 12 seconds 3306/tcp mysql
Next start the business tier, which is the Tomcat based Docker image with the name tomcat_hellodb, using the following command:
$ docker run -d -p 8080:8080 --link mysql:db tomcat_hellodb
Notice the use of the command line option --link in the command above.
The --link option is what "ties" the data tier with the name mysql to the business tier container via the alias db. Refer to the file context.xml above and see how this alias is used in the database url jdbc:mysql://db:3306/hellodb?useSSL=false.
The following would be a typical output:
5c4c70f234cf66470f80720394be2e1c91c84fb9df5f06074ed76ab2156a0403
To list all the running Docker containers, execute the following command:
$ docker ps
The following would be a typical output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5c4c70f234cf tomcat_hellodb "catalina.sh run" 5 seconds ago Up 3 seconds 0.0.0.0:8080->8080/tcp nauseous_khorana 7541f659e7a6 mysql_hellodb "docker-entrypoint.sh" 9 minutes ago Up 9 minutes 3306/tcp mysql
Open a browser on the local host and access the URL http://localhost:8080/helloworld3/message. The following would be a typical view:
HOORAY !!! we have successfully demonstrated the use of multiple Docker containers.
To stop the business tier and data tier containers, execute the following command:
$ docker stop 5c4c70f234cf 7541f659e7a6
The following would be a typical output:
5c4c70f234cf 7541f659e7a6
To list all the running Docker containers (none should be running at this point), execute the following command:
$ docker ps
The following would be a typical output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
References