Architectural Deep Dive into Apache Tomcat Containerization with Docker

Apache Tomcat, often referred to simply as Tomcat, is a cornerstone of Java-based web architecture. It serves as an open-source web server and servlet container developed and maintained by the Apache Software Foundation (ASF). At its core, Tomcat is engineered to implement the Java Servlet and JavaServer Pages (JSP) specifications defined by Oracle. By providing a "pure Java" HTTP web server environment, Tomcat allows Java code to execute within a standardized runtime, bridging the gap between low-level network requests and high-level Java application logic.

In its most basic configuration, Tomcat operates within a single operating system process. This process encapsulates a Java Virtual Machine (JVM), which manages the memory and execution of the Java bytecode. The concurrency model of Tomcat is designed such that every single HTTP request originating from a browser is processed within the Tomcat process but isolated in a separate thread. This multi-threaded approach ensures that the server can handle multiple simultaneous users without blocking the entire process, making it an efficient choice for enterprise-grade web applications.

The integration of Tomcat into Docker transforms it from a manually installed software package into a portable, immutable artifact. This containerization allows developers to package the specific version of the JVM, the Tomcat runtime, and the application code into a single image, ensuring that the environment remains consistent from a developer's local laptop to a production Service Fabric cluster or a Kubernetes pod.

Technical Specifications and Image Environment

The official Docker images for Tomcat are meticulously maintained and updated via pull requests to the docker-library/official-images GitHub repository. These images provide a standardized environment that adheres to the following internal directory structures and environment variables.

The default environment configuration within the official Tomcat image is structured as follows:

Environment Variable Value Description
CATALINA_BASE /usr/local/tomcat The directory where the Tomcat installation is located.
CATALINA_HOME /usr/local/tomcat The directory where the Tomcat binaries and libraries reside.
CATALINA_TMPDIR /usr/local/tomcat/temp The directory used for temporary files.
JRE_HOME /usr The location of the Java Runtime Environment.
CLASSPATH /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar The path used by the JVM to locate essential classes.

The configuration files required to tune the server, such as server.xml and web.xml, are located in the /usr/local/tomcat/conf/ directory. Understanding these paths is critical for administrators who need to mount external configuration files via Docker volumes to avoid rebuilding the image for every minor configuration change.

Image Tagging and Versioning Strategy

The availability of diverse tags on Docker Hub allows users to select specific versions of Tomcat and the underlying Java Runtime Environment (JRE) to match their application requirements. This flexibility is crucial for maintaining compatibility with older Java applications or leveraging the latest performance improvements in newer JREs.

The following table details the available tags and their associated architectures and sizes:

Tag Architecture Size
jre17-temurin-noble linux/amd64 103.66 MB
jre17-temurin-noble linux/arm/v7 97.95 MB
jre17-temurin-noble linux/arm64/v8 102.37 MB
9.0.117-jre25-temurin-noble linux/amd64 112.49 MB
9.0.117-jre25-temurin-noble linux/arm64/v8 110.69 MB
9.0.117-jre25-temurin-noble linux/ppc64le 116.91 MB
9.0.117-jre21-temurin-noble linux/amd64 108.45 MB
9.0.117-jre21-temurin-noble linux/arm64/v8 106.86 MB
9.0.117-jre21-temurin-noble linux/ppc64le 114.62 MB
9.0.117-jre17-temurin-noble linux/amd64 103.15 MB
9.0.117-jre17-temurin-noble linux/arm64/v8 97.4 MB
9.0.117-jre17-temurin-noble linux/ppc64le 101.87 MB

The use of Temurin JREs indicates a shift toward high-quality, open-source builds of the Java runtime. The "noble" suffix refers to the underlying Ubuntu distribution (Noble Numbat), providing a stable base OS for the container.

Deployment and Execution Workflows

Running a Tomcat container can range from a simple "hello world" test to a complex deployment within a microservices architecture.

Basic Execution

To launch the default Tomcat server using version 9.0, the following command is used:

docker run -it --rm tomcat:9.0

In this command, -it allows for interactive mode with a TTY, and --rm ensures the container is automatically removed after it stops, preventing the accumulation of dead containers on the host system. The default command executed within the container is CMD ["catalina.sh", "run"], which starts the Tomcat server in the foreground.

Port Mapping and External Access

By default, Tomcat listens on port 8080. Because Docker containers are isolated, this port is not accessible to the outside world unless explicitly mapped to a host port.

To access Tomcat on port 8888 of the host machine, use:

docker run -it --rm -p 8888:8080 tomcat:9.0

After running this, the server can be accessed via http://localhost:8888 or http://host-ip:8888. It is important to note that a 404 error will be returned upon first access. This is because, as of docker-library/tomcat#181, the upstream-provided example webapps are not enabled by default for security reasons.

Advanced Customization and Manager App Restoration

The Tomcat Manager application is a powerful tool for deploying and managing web applications via a GUI or script. However, for security reasons, the image maintainers keep these applications disabled and stored in a separate directory.

Restoring Default Webapps

The example applications are stored in /usr/local/tomcat/webapps.dist. To make them active, they must be moved to /usr/local/tomcat/webapps. This requires overriding the container's startup command.

Configuring User Access

Access to the manager requires a defined user in the tomcat-users.xml file. The user must be assigned the manager-gui and manager-script roles. A sample configuration is:

xml <tomcat-users> <role rolename="manager-gui"/> <role rolename="manager-script"/> <user username="tomcat" password="your-password" roles="manager-gui,manager-script"/> </tomcat-users>

Overcoming Localhost Restrictions

The manager application, by default, only accepts traffic from localhost. In a Docker context, localhost refers to the container's own loopback interface, not the host machine. To allow external access, a custom context.xml must be applied to the manager's META-INF directory.

Complete Restoration Command

To boot a Tomcat container with the manager app enabled and configured, the following complex command is used:

sudo docker run --name tomcat -it -p 8080:8080 -v /tmp/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml -v /tmp/context.xml:/tmp/context.xml tomcat:9.0 /bin/bash -c "mv /usr/local/tomcat/webapps /usr/local/tomcat/webapps2; mv /usr/local/tomcat/webapps.dist /usr/local/tomcat/webapps; cp /tmp/context.xml /usr/local/tomcat/webapps/manager/META-INF/context.xml; catalina.sh run"

This sequence of operations performs the following:
1. Maps the custom tomcat-users.xml and context.xml via volumes.
2. Renames the empty webapps folder to webapps2.
3. Promotes webapps.dist to the active webapps folder.
4. Copies the context.xml to the specific manager configuration path.
5. Executes catalina.sh run to start the server.

Once these steps are complete, the manager application is accessible at http://localhost:8080/manager/html.

Custom Image Construction and Service Fabric Integration

For production environments, such as an Azure Service Fabric cluster running Linux, it is necessary to build a custom image that includes the application code.

Building a Custom Dockerfile

A Dockerfile is created to define the application environment. A typical minimal Dockerfile for a Tomcat application looks like this:

dockerfile FROM library/tomcat EXPOSE 8080 COPY ./ApacheTomcat /usr/local/tomcat

In this configuration:
- FROM library/tomcat pulls the official base image.
- EXPOSE 8080 informs Docker that the container listens on port 8080.
- COPY ./ApacheTomcat /usr/local/tomcat transfers the local application files into the container's Tomcat directory.

The Build and Run Process

To create the image, the user must first authenticate with Docker and then execute the build command:

docker login
docker build . -t tomcattest

The -t flag tags the image as tomcattest. After the build, the image can be verified using:

docker images

The output will show the repository, tag, image ID, and size (for example, 194 MB). To verify the application locally before pushing it to a registry, the following command is used:

docker run -itd --name tomcat-site -p 8080:8080 tomcattest

The -itd flags run the container in detached mode, and --name tomcat-site provides a friendly identifier for management.

Conclusion

The containerization of Apache Tomcat via Docker provides a robust framework for deploying Java-based web applications with high consistency and scalability. By leveraging the official images, developers benefit from a pre-configured environment that implements the Java Servlet and JSP specifications, managed by a dedicated JVM process. However, the security-first approach of the current official images—which disables default webapps—requires administrators to manually intervene via shell commands and volume mappings to restore the Manager application.

The transition from basic docker run commands to the creation of custom Dockerfiles allows for the seamless integration of Tomcat into advanced orchestration platforms like Azure Service Fabric. The ability to select specific JRE versions (such as Temurin 17 or 21) and target multiple architectures (amd64, arm64, ppc64le) ensures that Java applications can be deployed across diverse hardware landscapes without modification. Ultimately, the success of a Tomcat Docker deployment relies on the correct mapping of ports, the strategic placement of configuration files in /usr/local/tomcat/conf/, and a clear understanding of the container's internal filesystem.

Sources

  1. Docker Hub - Tomcat
  2. Docker Hub - Tomcat Official
  3. Microsoft Learn - Service Fabric Tomcat
  4. Docker Hub - Tomcat Tags
  5. Octopus Blog - Deployable Tomcat Docker Containers

Related Posts