This guide will walk you through how to run Tomcat with Zing in a Docker container on CentOS.
Details:
- Uses CentOS 7 image
- Use wget & tar to install Tomcat/Zing
- Shows 2 ways to install Zing: via RPM & via TAR (ie if you want to install Zing from a local repo)
- Setup Environment variables
- Update JAVA_HOME to Zing
- Installs Tomcat 9.0.37
- Creates Tomcat user (& optional: admin user)
- Uses startup.sh to run catalina.sh
1. Why Zing?
If you are experiencing spikes in latency, uneven throughput, poor performance, long warm-up with any application that runs on a JVM (Java app, Apache Cassandra, Solr/ElasticSearch, Spark, etc), take a look at Zing.
Zing is a drop-in replacement for your JVMs — meaning, no code changes required, based on OpenJDK source code, certified Java SE compliance.
Benefits of using Zing include:
- Pauseless Garbage Collector (C4) to eliminate Stop-The-World pauses
- Advanced JIT Compiler (Falcon) for improved performance
- Warm-up elimination (ReadyNow) so first transactions are as fast as 1000th
2. Install Docker Desktop
Since I’m setting this up from my Mac, I install Docker Desktop for Mac. This will let you build Dockerized apps locally.
3. Create Dockerfile
Inside any directory of your choice, create a file called “Dockerfile”
For this example, save Dockerfile into directory called: “tomcat” (or update last step to use your dir name)
4. Dockerfile Content
The Dockerfile below includes the following:
4.1 Use centos7 image
Why start with “FROM”? Per Docker’s documentation: "FROM
instruction initializes a new build stage and sets the Base Image for subsequent instructions. As such, a valid Dockerfile
must start with a FROM
instruction. The image can be any valid image – it is especially easy to start by pulling an image from the Public Repositories.”
Label contains metadata for your image. It’s a list of <key> = <value> pair(s).
# Centos based container with Zing and Tomcat
FROM centos:centos7
LABEL maintainer=”cgeorge@azul.com”
4.2 Install prepare infrastructure
RUN yum -y update && \
yum -y install wget && \
yum -y install tar
4.3 Prepare environment
ARG ZING_DIR=ZVM20.10.0.0
ARG ZING_PACK=zing20.10.0.0–6-sa-jdk8.0.271-linux_x64.tar.gzENV JAVA_HOME /opt/zing/zing-jdk8
ENV CATALINA_HOME /opt/tomcat
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/scripts
4.4. Install Zing
To use a different version of Zing: https://www.azul.com/software-downloads-and-documents/
4.4.1 If using TAR
RUN curl -O https://cdn.azul.com/zing-zvm/${ZING_DIR}/${ZING_PACK} && \
mkdir -p ${JAVA_HOME} && \
tar zxf ${ZING_PACK} -C ${JAVA_HOME} — strip-components 1 && \
rm -f ${ZING_PACK}
**Change JAVA_HOME as TAR uses different directory than RPM**
ENV JAVA_HOME /opt/zing
4.4.2 If using RPM
RUN rpm — import http://repos.azul.com/azul-repo.key
RUN curl -o /etc/yum.repos.d/zing.repo http://repos.azul.com/zing/rhel/zing.repo
RUN yum install -y zing-jdk1.8.0${ZING_VERSION}
4.5 Set alternatives
WORKDIR $JAVA_HOME
RUN alternatives — install /usr/bin/java java $JAVA_HOME/bin/java 1
RUN alternatives — install /usr/bin/jar jar $JAVA_HOME/bin/jar 1
RUN alternatives — install /usr/bin/javac javac $JAVA_HOME/bin/javac 1
RUN echo “JAVA_HOME=/opt/zing” >> /etc/environment
4.6 Install Tomcat
To use a different version of Tomcat or if you get a 404:Not found error, you can select a different location: https://tomcat.apache.org/download-90.cgi
# Install Tomcat
ENV TOMCAT_MAJOR 9
ENV TOMCAT_VERSION 9.0.39RUN curl -O https://archive.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz — no-verbose && \
mkdir ${CATALINA_HOME} && \
tar zxf apache-tomcat-${TOMCAT_VERSION}.tar.gz -C ${CATALINA_HOME} — strip-components 1 && \
rm -f apache-tomcat-${TOMCAT_VERSION}.tar.gz
4.7 Change permission for catalina.sh
RUN chmod +x ${CATALINA_HOME}/bin/*sh
4.8 Optional: Create Tomcat admin user
ADD create_admin_user.sh $CATALINA_HOME/scripts/create_admin_user.sh
ADD tomcat.sh $CATALINA_HOME/scripts/tomcat.sh
RUN chmod +x $CATALINA_HOME/scripts/*.sh
4.9 Create Tomcat user
RUN groupadd -r tomcat && \
useradd -g tomcat -d ${CATALINA_HOME} -s /sbin/nologin -c “Tomcat user” tomcat && \
chown -R tomcat:tomcat ${CATALINA_HOME}
4.10 Set Variable
WORKDIR /opt/tomcat
4.11 Configure Tomcat & point it to startup.sh
EXPOSE 8080
COPY startup.sh /opt/startup.sh
RUN chmod +x /opt/startup.sh
ENTRYPOINT /opt/startup.sh
5. Create startup.sh
In the same directory as Dockerfile, create a file “startup.sh” and paste the following:
#!/bin/sh
# start Tomcat
$CATALINA_HOME/bin/catalina.sh run
6. Save Zing license
Still in the same directory, create a folder called “licenses” and save your Zing license as “license”
7. Build it and Run it
Last step is to build your image from your Dockerfile & a context (context is set of files at a specified location “PATH” or “URL”).
Here, I’m using “-t” and specifying a repo & tag (<username>/tomcat) to save the new image (if the build succeeds).
For non-Zing customers: you will need to pass the Zing License as a env parameter. This is passed as a parameter rather than included in the Dockerfile as the license has an expiration date and will need to be updated when it expires.
docker build -t <username>/tomcat .
docker run -p 80:8080 <username>/tomcat
— Or —
docker run — env ZING_LICENSE=”’cat <path to Zing license>’” -p 80:8080 <username>/tomcat
If port 80 is used by another application:
docker run — env ZING_LICENSE=”’cat <path to Zing license>’” -p 81:8080 <username>/tomcat
Open a browser and navigate to: http://localhost/
You should see the Tomcat default page:
Complete Dockerfile
Use the example below to create the Dockerfile to avoid formatting issues from the examples above.
# Centos based container with Java and Tomcat
FROM centos:centos7
LABEL maintainer="cgeorge@azul.com"# Prepare environment
ARG ZING_DIR=ZVM20.10.0.0
ARG ZING_PACK=zing20.10.0.0-4-ca-jdk8.0.271-linux_x64.tar.gz# CHANGE IF INSTALLING ZING w TAR
#ENV JAVA_HOME /opt/zing
ENV JAVA_HOME /opt/zing/zing-jdk8# Install prepare infrastructure
RUN yum -y update && \
yum -y install wget && \
yum -y install tar# Install Zing from yum repo
RUN rpm --import http://repos.azul.com/azul-repo.key
RUN curl -o /etc/yum.repos.d/zing.repo http://repos.azul.com/zing/rhel/zing.repo
RUN yum install -y zing-jdk1.8.0${ZING_VERSION}# Install Zing from tar pack
#RUN curl -O https://cdn.azul.com/zing-zvm/${ZING_DIR}/${ZING_PACK}
#RUN mkdir -p ${JAVA_HOME}
#RUN tar zxf ${ZING_PACK} -C ${JAVA_HOME} --strip-components 1
#RUN rm -f ${ZING_PACK}WORKDIR /opt/zing
RUN alternatives --install /usr/bin/java java /opt/zing/bin/java 1
RUN alternatives --install /usr/bin/jar jar /opt/zing/bin/jar 1
RUN alternatives --install /usr/bin/javac javac /opt/zing/bin/javac 1
RUN echo "JAVA_HOME=/opt/zing" >> /etc/environment# Instead of passing the license as a parameter, you can save it in same directory as Dockfile
#ADD ./license /etc/zing/ENV CATALINA_HOME /opt/tomcat
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/scripts# Install Tomcat
ENV TOMCAT_MAJOR 9
ENV TOMCAT_VERSION 9.0.39RUN curl -O https://archive.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz --no-verbose && \
mkdir ${CATALINA_HOME} && \
tar zxf apache-tomcat-${TOMCAT_VERSION}.tar.gz -C ${CATALINA_HOME} --strip-components 1 && \
rm -f apache-tomcat-${TOMCAT_VERSION}.tar.gzRUN chmod +x ${CATALINA_HOME}/bin/*sh# Create Tomcat admin user
#ADD create_admin_user.sh $CATALINA_HOME/scripts/create_admin_user.sh
#ADD tomcat.sh $CATALINA_HOME/scripts/tomcat.sh
#RUN chmod +x $CATALINA_HOME/scripts/*.sh# Create tomcat user
#RUN groupadd -r tomcat && \
# useradd -g tomcat -d ${CATALINA_HOME} -s /sbin/nologin -c "Tomcat user" tomcat && \
# chown -R tomcat:tomcat ${CATALINA_HOME}WORKDIR /opt/tomcatEXPOSE 8080
COPY startup.sh /opt/startup.sh
RUN chmod +x /opt/startup.sh
ENTRYPOINT /opt/startup.shWORKDIR $CATALINA_HOME#CMD ["tomcat.sh"]
Next
How to get Tomcat started faster? Coming up (soon) in Part 2 of this article!