Introduction
I'm going to
- extend the official Dockerfile for Tomcat
- build a new image
- launch a container from the modified image
- deploy and test a RESTful Web Service onto this container
Apache Tomcat
A docker search shows me the most popular (and official) Docker Tomcat container:
$ sudo docker search tomcat [sudo] password for craig: NAME DESCRIPTION STARS OFFICIAL AUTOMATED tomcat Apache Tomcat is an open source implementa... 103 [OK] tutum/tomcat Tomcat image - listens in port 8080. For t... 38 [OK] consol/tomcat-7.0 Tomcat 7.0.57, 8080, "admin/admin" 12 [OK] consol/tomcat-8.0 Tomcat 8.0.15, 8080, "admin/admin" 9 [OK] consol/tomcat-6.0 Tomcat 6.0.43, 8080, "admin/admin" 6 [OK] consol/tomcat-4.1 Tomcat 4.1.40, 8080, "admin/admin" 4 [OK] consol/tomcat-5.0 Tomcat 5.0.30, 8080, "admin/admin" 4 [OK] consol/tomcat-5.5 Tomcat 5.5.36, 8080, "admin/admin" 4 [OK] consol/tomcat-3.3 Tomcat 3.3.2, 8080, "admin/admin" 4 [OK] readytalk/tomcat-native Debian backed Tomcat + Tomcat Native Library 3 [OK] malderhout/tomcat Tomcat7 with OpenJDK7 on CentOS7 3 [OK] dordoka/tomcat Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 ba... 3 [OK] meirwa/spring-boot-tomcat-mysql-app a sample spring-boot app using tomcat and ... 2 [OK] h2000/docker-tomcat-youtrack Dockerfile for youtrack to run under tomcat. 1 [OK] nicescale/tomcat Tomcat service for NiceScale. http://nices... 1 [OK] dmean/liferay-tomcat Debian + Liferay CE Tomcat 1 [OK] atomi/tomcat 0 [OK] mminke/apache-tomcat A Docker image which contains the Apache T... 0 [OK] ericogr/tomcat Tomcat 8.0.21, 8080, "docker/docker" 0 [OK] holmes/tomcat 0 [OK] paulkling/tomcat 0 [OK] dynamind/tomcat 0 [OK] fabric8/tomcat-8.0 runs Apache Tomcat 8.0 with jolokia enable... 0 [OK] learninglayers/tomcat 0 [OK] dmglab/tomcat CentOS 7 based tomcat installation 0 [OK]
The official site describes the supported tags:
I currently work with version 7, so I'll be using tomcat:7.
I'm new to Docker (at the time of this article) and hestitate to call out "best practices". What I'm abou to describe seems like a good practice, and I'll happily listen to any contrary opinion. For each Docker container I plan to launch, I prefer to create my own Dockerfile and extend the image. It's entirely possible that I won't ever extend the image, and will simply use it as-is. But building my own image from the target image seems like a logical way to use and extend the work of others in a consistent fashion.
In this case, I'm going to start by creating a simple Dockerfile with a single line:
FROM tomcat:7-jre7 MAINTAINER "Craig Trim <craigtrim@gmail.com>"
I'm going to build this image using this command:
$ sudo docker build -t craig/tomcat .
One advantage to this immediate extension is that I simplify my environment. Eventually, I'll be using containers for Eclipse, MySQL and other apps. I can give each a simplified namespace and image name. On a project, I might choose the project codename as the container namespace. I've also simplified the tag name. These are trivial changes, and it could be argued that the lack of precision obscures details that are important. I would suggest that on a large team with multiple developers this approach offers some advantages. A common namespace, with a simplified image name and tag, would make it eaiser to direct team members toward using official project images.
As an example, I offer this:
tomcat:7-jre7 | ns/tomcat |
mysql:5.6.23 | ns/mysql |
fgrehm/eclipse:v4.4.1 | ns/eclipse |
ns corresponds to a namespace every team member would understand. Launching a container becomes a matter of remembering the project codename (namespace) and the app name. Nothing else.
Running Tomcat
This command will run Tomcat and expose the container's port 8080 on the host's port of 8080:
$ sudo docker run -p 8080:8080 craig/tomcat
If I wanted to launch additional containers from this same image, I could just change
$ sudo docker run -p 8081:8080 craig/tomcat
I can test the running instance on my host:
Extending the Dockerfile
I'm going to extend the Dockerfile to support a configuration that will permit automated deployments from Maven.
I need to add a settings.xml file and update the tomcat-users.xml file. A simplified form of each file is given
tomcat-users.xml:
<?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="manager-gui"/> <role rolename="manager-gui"/> <role rolename="manager-script"/> <user username="craig" password="password" roles="manager,manager-gui,manager-script" /> </tomcat-users>
settings.xml:
<?xml version="1.0" encoding="UTF-8"?> <settings> <servers> <server> <id>TomcatServer</id> <username>craig</username> <password>password</password> </server> </servers> </settings>
I place each of these files in the same directory as my Dockerfile.
The Dockerfile is updated to this:
FROM tomcat:7-jre7 MAINTAINER "Craig Trim <craigtrim@gmail.com>" ADD settings.xml /usr/local/tomcat/conf/ ADD tomcat-users.xml /usr/local/tomcat/conf/
The configuration files are added to the correct directories when the image is built. Any container launched from this image will now contain these files.
Rebuilding the Image
The image is rebuilt in the same manner we initially built it:
$ sudo docker build -t craig/tomcat . Sending build context to Docker daemon 5.632 kB Sending build context to Docker daemon Step 0 : FROM tomcat:7-jre7 ---> 77eb038c09d1 Step 1 : MAINTAINER "Craig Trim <craigtrim@gmail.com>" ---> Using cache ---> cadc51a3054c Step 2 : ADD settings.xml /usr/local/tomcat/conf/ ---> Using cache ---> 5009ba884f1f Step 3 : ADD tomcat-users.xml /usr/local/tomcat/conf/ ---> Using cache ---> 33917c541bb5 Successfully built 33917c541bb5
We can view the history of image:
$ sudo docker history craig/tomcat IMAGE CREATED CREATED BY SIZE 33917c541bb5 4 hours ago /bin/sh -c #(nop) ADD file:c1d08c42d5808537b4 1.761 kB 5009ba884f1f 4 hours ago /bin/sh -c #(nop) ADD file:5dd8f0f6d0cd64de3c 212 B cadc51a3054c 4 hours ago /bin/sh -c #(nop) MAINTAINER "Craig Trim <cra 0 B 77eb038c09d1 3 weeks ago /bin/sh -c #(nop) CMD [catalina.sh run] 0 B a96609fc8364 3 weeks ago /bin/sh -c #(nop) EXPOSE map[8080/tcp:{}] 0 B ca99125fbf51 3 weeks ago /bin/sh -c curl -SL "$TOMCAT_TGZ_URL" -o tomc 13.63 MB e7ca14a4280a 3 weeks ago /bin/sh -c #(nop) ENV TOMCAT_TGZ_URL=https:// 0 B eac866e259d8 3 weeks ago /bin/sh -c #(nop) ENV TOMCAT_VERSION=7.0.59 0 B d391d657b53a 3 weeks ago /bin/sh -c #(nop) ENV TOMCAT_MAJOR=7 0 B 7b323fd1e0d3 3 weeks ago /bin/sh -c gpg --keyserver pool.sks-keyserver 113.9 kB 4412b8a11fb6 3 weeks ago /bin/sh -c #(nop) WORKDIR /usr/local/tomcat 0 B b4ec9d590927 3 weeks ago /bin/sh -c mkdir -p "$CATALINA_HOME" 0 B 681b802059fe 3 weeks ago /bin/sh -c #(nop) ENV PATH=/usr/local/tomcat/ 0 B 11b245da4142 3 weeks ago /bin/sh -c #(nop) ENV CATALINA_HOME=/usr/loca 0 B 44faa7b2809f 3 weeks ago /bin/sh -c apt-get update && apt-get install 164.5 MB 42c3653e1b26 3 weeks ago /bin/sh -c #(nop) ENV JAVA_DEBIAN_VERSION=7u7 0 B 45ff981e92b4 3 weeks ago /bin/sh -c #(nop) ENV JAVA_VERSION=7u75 0 B 5e9b188bc82c 3 weeks ago /bin/sh -c apt-get update && apt-get install 676 kB 1073b544a1cb 3 weeks ago /bin/sh -c apt-get update && apt-get install 44.34 MB 50ec2d202fe8 3 weeks ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B 3b3a4796eef1 3 weeks ago /bin/sh -c #(nop) ADD file:fb7c52fc8e65391715 122.8 MB 511136ea3c5a 21 months ago 0 B
The changes I have made are shown as occuring 4 hours ago. I can now launch a container from this modified image and proceed to test an automated deployment.
Deploying to Tomcat
This is properly the subject of another tutorial, but the best way to test our Tomcat installation is to deploy a WAR file.
I've created a simple JEE project using Maven with this structure:
$ tree . +-- pom.xml +-- src ¦ +-- main ¦ ¦ +-- java ¦ ¦ +-- com ¦ ¦ +-- trimc ¦ ¦ +-- blogger ¦ ¦ +-- samplewebapp ¦ ¦ +-- CorsFilter.java ¦ ¦ +-- TestREST.java ¦ +-- test ¦ +-- java ¦ +-- com ¦ +-- trimc ¦ +-- blogger ¦ +-- samplewebapp +-- target ¦ +-- classes ¦ ¦ +-- com ¦ ¦ +-- trimc ¦ ¦ +-- blogger ¦ ¦ +-- samplewebapp ¦ ¦ +-- CorsFilter.class ¦ ¦ +-- TestREST.class ¦ ¦ +-- TestREST$Result.class ¦ +-- generated-sources ¦ ¦ +-- annotations ¦ +-- m2e-wtp ¦ ¦ +-- web-resources ¦ ¦ +-- META-INF ¦ ¦ +-- MANIFEST.MF ¦ ¦ +-- maven ¦ ¦ +-- com.trimc.blogger.samplewebapp ¦ ¦ +-- trimc-samplewebapp ¦ ¦ +-- pom.properties ¦ ¦ +-- pom.xml ¦ +-- maven-archiver ¦ ¦ +-- pom.properties ¦ +-- maven-status ¦ ¦ +-- maven-compiler-plugin ¦ ¦ +-- compile ¦ ¦ ¦ +-- default-compile ¦ ¦ ¦ +-- createdFiles.lst ¦ ¦ ¦ +-- inputFiles.lst ¦ ¦ +-- testCompile ¦ ¦ +-- default-testCompile ¦ ¦ +-- inputFiles.lst ¦ +-- test-classes ¦ +-- trimc-samplewebapp-1.0.0 ¦ ¦ +-- META-INF ¦ ¦ ¦ +-- MANIFEST.MF ¦ ¦ +-- WEB-INF ¦ ¦ +-- classes ¦ ¦ ¦ +-- com ¦ ¦ ¦ +-- trimc ¦ ¦ ¦ +-- blogger ¦ ¦ ¦ +-- samplewebapp ¦ ¦ ¦ +-- App.class ¦ ¦ ¦ +-- CorsFilter.class ¦ ¦ ¦ +-- TestREST.class ¦ ¦ ¦ +-- TestREST$Result.class ¦ ¦ +-- lib ¦ ¦ ¦ +-- asm-3.1.jar ¦ ¦ ¦ +-- genson-1.2.jar ¦ ¦ ¦ +-- jersey-core-1.9.jar ¦ ¦ ¦ +-- jersey-server-1.9.jar ¦ ¦ +-- web.xml ¦ +-- trimc-samplewebapp-1.0.0.war +-- WebContent +-- META-INF ¦ +-- MANIFEST.MF +-- WEB-INF +-- lib +-- web.xml 48 directories, 26 files
This plugin (in pom.xml) specifies deployment information corresponding to both the exposed port and the username and password in the tomcat configuration files:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <url>http://localhost:8080/manager/text</url> <server>TomcatServer</server> <path>/sample</path> <username>craig</username> <password>password</password> </configuration> </plugin>
Using Maven to deploy to Tomcat:
$ mvn tomcat7:deploy [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Test Runtime 1.0.0 [INFO] ------------------------------------------------------------------------ [INFO] *** SNIP *** [INFO] --- tomcat7-maven-plugin:2.2:deploy (default-cli) @ sandbox-web2 --- [INFO] Deploying war to http://localhost:8080/test Uploading: http://localhost:8080/manager/text/deploy?path=%2Ftest Uploaded: http://localhost:8080/manager/text/deploy?path=%2Ftest (1352 KB at 18512.6 KB/sec) [INFO] tomcatManager status code:200, ReasonPhrase:OK [INFO] OK - Deployed application at context path /test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.495 s [INFO] Finished at: 2015-03-31T19:08:12-07:00 [INFO] Final Memory: 15M/506M [INFO] ------------------------------------------------------------------------
and the Tomcat log gives this:
Apr 01, 2015 2:08:12 AM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate INFO: Initiating Jersey application, version 'Jersey: 1.9 09/02/2011 11:17 AM' Apr 01, 2015 2:08:12 AM org.apache.catalina.startup.HostConfig deployWAR INFO: Deployment of web application archive /usr/local/tomcat/webapps/test.war has finished in 826 ms
and the all important echo output:
Conclusion
So what's the big deal?
Sure, we didn't have to install Tomcat; we launched a container that was built from an image described in a Dockerfile. That might come across as seeming more difficult than simply downloading Tomcat, unzipping it and running the startup script.
There's a few advantages that come to mind:
- Not every application is as easy to install as Tomcat
- Nearly every application requires additional configuration once installed
Using Docker in this capacity is similar to Vagrant/Puppet/Chef/Ansible/etc. We write a script that describes our environment and a build tool stands up the environment automatically. Docker has some clear advantages here -- it's much more lightweight than using a full-fleged VM. Using the entire VM stack for Tomcat may be overkill in many situations. Considering many developers work on laptops, it may not be possible to run multiple VMs successfully.
This brings up a third advantage of Docker: We can launch multiple containers from the same image. This is nowhere nearly as resource intensive as launching multiple VMs, and the startup time with Docker is nearly instantaneous.
References
- Web Application Links
- [GitHub] Sample REST Webapp
- Download the sample webapp used in this blog post.
- The WAR file is available here.
- [GitHub] Apache Tomcat Dockerfile
- [Blogger] Maven: a build automation tool
- [Blogger] An Introduction to JAX-RS (Java API for RESTful Web Services)
- [Blog] Bootstrapping WebSphere Liberty in Docker with confd
- An alternative to Apache Tomcat
- [Blog] Getting Started with Docker
This is awesome. Thank you. I'm new to webapp development and currently using Soring MVC in Eclupse. I want to eventually run everything in containers and this gets me pretty far. Thanks again.
ReplyDeleteI'm just getting started too. Let me know how it goes for you!
DeleteEric thank you for your post to introduce docker. I have two questions. First, Tomcat is a web container for java web apps, and multiple tomcat can be started on physical OS by assign different ports. So why you start tomcat in VM? Secondly, what can we benefit from running tomcat in docker? For the third advantage in your post, I don't agree with your opinion. The reason is the same as described in first question.
ReplyDelete1. May you please compile all this into a single script whereby, all you would need to do is ./run.sh
ReplyDelete2. Could you add mysql into the mix, and make your application pull data from a mysql database;
I am curious to see how you could add a mysql instance and set its password.
Docker is meant to replace these kinds of shell scripts. You'd have another docker for install script based off of a base mysql instance to accomplish the second goal, and they wouldn't be all part of one script.
DeleteWonderful post. Craig, you may want to add that once you have built it - sign in the terminal with your credentials and the push the image into the docker hub.
ReplyDelete$ docker login
$ docker push (image)
DCHQ is the way to go...
ReplyDeletevisit www.DCHQ.io to learn more
Simple as
1) Configure a VM running Ubuntu Server 14.04 TLS with only OpenSSH server installed.
VM1 Specs: 2 CPU / 12GB of RAM / 20GB Storage
This server will be your DCHQ Host.
2) Configure a second VM (or better yet baremetal server) with Ubuntu TLS 14.04 Server
This server will be your Docker Host
VM2 Specs: 16 cores / 64GB RAM / 100+ Storage
This server will host your docker containers (web servers, app servers, db servers, etc..)
Repeat step 2 to configure a additional Docker Hosts in a multi-node cluster.
Otherwise you can move on to step 3 to get started with DCHQ installation
3) Get DCHQ On-Premise version from here: http://dchq.co/dchq-on-premise.html
Registration required - basically your name and email so they can send you the link to the scripts, documentation, licesing file, templates, plug-ins , etc..
3) Follow the installation video here:
https://www.youtube.com/watch?v=39dTw8zYccg
Be sure to perform the specs depicted on the video on VM1 (step 1 above)
4) Once you have DCHQ On-Prem installed on VM1.
You can add VM2 as a host.
Click Manage > Hosts > Click the plus sign > Any Host/VM
Have fun !
Be sure to support DCHQ.io by purchasing Enterprise support from them, very affordable..
Let me know if you have any questions!
Rod
Hi Craig/All..
ReplyDeletewhen i run build command i am struck below:
27-Feb-2016 06:11:24.122 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
27-Feb-2016 06:11:24.133 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 5327 ms
please advise. Thank you!
Is there any way , I can go inside the Apache Tomcat running container and see the config files ?
ReplyDelete$ docker exec -it name bash
Deletewhere name is the name of the tomcat process you started. to get the name of your process:
$ docker ps
This comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteYour post helped me a lot in deploying my own docker container! Cheers!
ReplyDeletethanks for sharing.
ReplyDeleteHi Craig & All,
ReplyDeleteI followed steps, but I am having problem with accessing the 'Manager App' inspite of adding both settings.xml and tomcat-users.xml as indicated in the Dockerfile.
If I run the following commands, I can see the changes for settings.xml and tomcat-users.xml is applied.
docker run --rm craig/tomcat cat conf/tomcat-users.xml
docker run --rm craig/tomcat cat conf/settings.xml
I am still getting the error "403 Access Denied". It seems that the changes for tomcat-users.xml is not applied.
Any idea? I am guessing I overlooked something... but I could not figure out what.
Btw, I am pretty new to docker and I am planning to use docker.
TIA
Create manager.xml with following content and copy to /usr/local/tomcat/conf/Catalina/localhost/ folder
Deletethank you very much, very easy to understand, help me a lot to modify the tomcat files.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteSharing is caring, please do.
ReplyDelete
ReplyDeletewell! Thanks for providing the information
Docker Training
Docker Online Training
Nice and good article. It is very useful for me to learn and understand easily. Thanks for sharing your valuable information and time. Please keep updating Docker training
ReplyDeletewell! Thanks for providing the information
ReplyDeleteKubernetes Training in Hyderabad
Docker Online Training
Docker Training in Hyderabad
Thanks for Sharing such a good blog. You’re doing a great job. Keep posting like this useful info !!
ReplyDeleteBest Ethical Hacking Training in Chennai | Best Ethical Hacking Course in Chennai | Ethical Hacking Training with Placement | ceh Training in Chennai at TwinTech Solutions | Ethical Hacking Course | ceh Training | Ethical Hacking Training
Great article! Thanks for taking time to share this with us.
ReplyDeleteaws Training in Bangalore
python Training in Bangalore
hadoop Training in Bangalore
angular js Training in Bangalore
bigdata analytics Training in Bangalore
python Training in Bangalore
aws Training in Bangalore
This comment has been removed by the author.
ReplyDeleteNice Post. Home Elevators Dubai
ReplyDeleteThe article is so informative. This is more helpful for our
ReplyDeleteaws Training in Bangalore
python Training in Bangalore
hadoop Training in Bangalore
angular js Training in Bangalore
bigdata analytics Training in Bangalore
python Training in Bangalore
aws Training in Bangalore
Thanks for sharing such a useful post, I hope it’s useful to many individuals for developing their skills to get a good career.
ReplyDeleteDocker Training in Hyderabad
Kubernetes Training in Hyderabad
Docker and Kubernetes Training
Docker and Kubernetes Online Training
Thanks for sharing ...This is really nice..Appreciate your efforts in writing this...
ReplyDeleteAzure Training in chennai \ Windows Azure Training in chennai \ Microsoft Azure Training in chennai \ Azure Training Center in chennai \ Azure Training Institute in chennai \ Azure DevOps Training in Chennai \ Azure Training in Chennai OMR \ Azure Training in Chennai Velachery \ Azure Training Institute in Chennai \ Azure DevOps Training in Chennai \ Microsoft Azure Training in chennai BITA Academy \ Microsoft Azure Course in chennai \ Microsoft Azure Certification Course in chennai
ReplyDeleteThank you for excellent article.Great information
DevOps Online Training institute
DevOps Online Training in Hyderabad
The blog was absolutely fantastic! Lot of information is helpful in some or the other way. Keep updating the blog, looking forward for more content...Great job, keep it up
ReplyDeleteDevOps Training in Chennai | DevOps Training in anna nagar | DevOps Training in omr | DevOps Training in porur | DevOps Training in tambaram | DevOps Training in velachery
Thanks for posting such useful information. You have done a great job.
ReplyDeleteDocker and Kubernetes Training
Docker and Kubernetes Training in Hyderabad
Kubernetes Online Training
Docker Online Training
ReplyDeleteThanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information
DevOps Training in Bangalore | Certification | Online Training Course | DevOps Training in Hyderabad | Certification | Online Training Course | DevOps Training in Coimbatore | Certification | Online Training Course | DevOps Training in Online | Certification | Online Training Course
Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article. This article inspired me to read more. keep it up.
ReplyDeletepython training in bangalore
python training in hyderabad
python online training
python training
python flask training
python flask online training
python training in coimbatore
An overwhelming web journal I visit this blog, it's unfathomably amazing. Unusually, in this present blog's substance made inspiration driving truth and reasonable. The substance of data is enlightening.
ReplyDeleteFull Stack Course Chennai
Full Stack Training in Bangalore
Full Stack Course in Bangalore
Full Stack Training in Hyderabad
Full Stack Course in Hyderabad
Full Stack Training
Full Stack Course
Full Stack Online Training
Full Stack Online Course
Exchange Server online training
ReplyDeleteGoogle Cloud online training
IBM Intergration Bus online training
IBM Message Queue online training
This comment has been removed by the author.
ReplyDeletescala online training
ReplyDeleteazure devops online training
app v online training
UKSSC assistant accountant exam
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeletewordpress design services agency Need professional WordPress Web Design Services? We're experts in developing attractive mobile-friendly WordPress websites for businesses. Contact us today!
ReplyDeleteKacha Bella Dhoop Sticks
ReplyDeleteSri Krishna Premium Masala Bathi Incense Sticks
Deivathin Kural Complete Set
Mahabharata in telgu
ReplyDeleteKewda premium incense sticks
Mantra books
Thanks for sharing such an wonderful and informative blog with us.
ReplyDeleteDevOps course in Pune