Tomcat Installation and Initial Setup
Apache Tomcat is the leading WAS (Web Application Server) for running Java Servlets and JSP. This chapter covers everything you need in production: JDK environment setup, version differences across Tomcat releases, and the directory structure after installation.
JDK Environment Setup
Tomcat requires a Java runtime. The minimum Java version required differs by Tomcat version.
| Tomcat Version | Minimum Java | Servlet Spec | JSP Spec | Recommendation |
|---|---|---|---|---|
| Tomcat 9 | Java 8+ | 4.0 | 2.3 | Legacy systems |
| Tomcat 10 | Java 11+ | 5.0 | 3.0 | Jakarta EE migration |
| Tomcat 10.1 | Java 11+ | 6.0 | 3.1 | ** Recommended (stable)** |
| Tomcat 11 | Java 17+ | 6.1 | 4.0 | Latest features |
Important: From Tomcat 10, the
javax.*package namespace changed tojakarta.*. Code modifications are required when migrating from Tomcat 9 → 10.
Ubuntu — OpenJDK Installation
# Install OpenJDK 17 LTS (recommended for Tomcat 10.1+)
sudo apt update
sudo apt install -y openjdk-17-jdk
# Verify version
java -version
# openjdk version "17.0.x" ...
# Set JAVA_HOME (permanent)
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' | sudo tee -a /etc/environment
echo 'export PATH=$PATH:$JAVA_HOME/bin' | sudo tee -a /etc/environment
source /etc/environment
echo $JAVA_HOME
# /usr/lib/jvm/java-17-openjdk-amd64
CentOS/RHEL — OpenJDK Installation
# Install OpenJDK 17
sudo dnf install -y java-17-openjdk-devel
# Check JAVA_HOME
alternatives --list | grep java
# Create /etc/profile.d/java.sh
cat << 'EOF' | sudo tee /etc/profile.d/java.sh
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$PATH:$JAVA_HOME/bin
EOF
source /etc/profile.d/java.sh
Installing Tomcat on Ubuntu/Debian
Method 1: APT Package Manager (Quick)
sudo apt update
sudo apt install -y tomcat10
# Check service status
sudo systemctl status tomcat10
sudo systemctl enable tomcat10
sudo systemctl start tomcat10
# Verify on default port 8080
curl -I http://localhost:8080
# HTTP/1.1 200
Method 2: Official Distribution (Recommended — Version Control)
# Prepare installation directory
sudo mkdir -p /opt/tomcat
# Create dedicated user (security)
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
# Download Tomcat 10.1
TOMCAT_VERSION=10.1.20
cd /tmp
wget https://dlcdn.apache.org/tomcat/tomcat-10/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz
# Extract
sudo tar -xzf apache-tomcat-${TOMCAT_VERSION}.tar.gz -C /opt/tomcat/
sudo ln -s /opt/tomcat/apache-tomcat-${TOMCAT_VERSION} /opt/tomcat/latest
# Set ownership
sudo chown -R tomcat: /opt/tomcat/latest
sudo chmod +x /opt/tomcat/latest/bin/*.sh
# Register Systemd service
sudo tee /etc/systemd/system/tomcat.service << 'EOF'
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="CATALINA_PID=/opt/tomcat/latest/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/latest/bin/startup.sh
ExecStop=/opt/tomcat/latest/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable tomcat
sudo systemctl start tomcat
sudo systemctl status tomcat
Running Tomcat with Docker
# Official Tomcat 10.1 + JDK 17 image
docker run -d \
--name tomcat \
-p 8080:8080 \
tomcat:10.1-jdk17
# Enable default management page (development only)
docker exec -it tomcat bash -c \
"cp -r /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps/"
# Verify at http://localhost:8080
Docker Compose Example
# docker-compose.yml
version: '3.8'
services:
tomcat:
image: tomcat:10.1-jdk17
container_name: tomcat-app
ports:
- "8080:8080"
volumes:
- ./webapps:/usr/local/tomcat/webapps
- ./conf/server.xml:/usr/local/tomcat/conf/server.xml:ro
- ./logs:/usr/local/tomcat/logs
environment:
- CATALINA_OPTS=-Xms512m -Xmx1024m
restart: unless-stopped
Tomcat Directory Structure
Understanding the directory structure helps you quickly locate configuration files.
$CATALINA_HOME/
├── bin/ ← Execution scripts
│ ├── startup.sh # Start Tomcat
│ ├── shutdown.sh # Stop Tomcat
│ ├── catalina.sh # Core script (called by startup.sh)
│ └── setenv.sh # JVM option injection (create if missing)
│
├── conf/ ← Configuration files
│ ├── server.xml # Core config (connectors, hosts, contexts)
│ ├── web.xml # Global servlet configuration
│ ├── context.xml # Global context configuration
│ ├── tomcat-users.xml # Admin account configuration
│ └── logging.properties # Log configuration
│
├── webapps/ ← Deployment directory
│ ├── ROOT/ # http://host:8080/ default app
│ ├── manager/ # Tomcat manager web app
│ ├── host-manager/ # Virtual host manager web app
│ └── myapp.war # WAR file → auto-extracted
│
├── logs/ ← Log files
│ ├── catalina.out # Standard output (main log)
│ ├── catalina.YYYY-MM-DD.log # Daily log
│ ├── localhost.YYYY-MM-DD.log # Virtual host log
│ └── access_log.YYYY-MM-DD.txt # Access log
│
├── lib/ ← Shared libraries (common to all apps)
│ └── servlet-api.jar, jsp-api.jar, ...
│
├── temp/ ← Temporary files (JVM temp dir)
└── work/ ← JSP compile cache
└── Catalina/
└── localhost/
└── ROOT/ # JSP → Java → .class
setenv.sh — JVM Option Configuration
The recommended way to inject JVM options before Tomcat starts.
# Create $CATALINA_HOME/bin/setenv.sh
cat << 'EOF' | sudo tee /opt/tomcat/latest/bin/setenv.sh
#!/bin/bash
# JVM heap memory
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx2g"
# GC settings (Java 17 defaults to G1GC)
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxGCPauseMillis=200"
# GC log (for performance analysis)
export CATALINA_OPTS="$CATALINA_OPTS -Xlog:gc*:file=/opt/tomcat/latest/logs/gc.log:time,uptime:filecount=5,filesize=20m"
# Server mode
export CATALINA_OPTS="$CATALINA_OPTS -server"
# Timezone
export CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=Asia/Seoul"
# Encoding
export JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"
EOF
sudo chmod +x /opt/tomcat/latest/bin/setenv.sh
sudo chown tomcat: /opt/tomcat/latest/bin/setenv.sh
Service Management Commands
# Start / Stop / Restart / Status
sudo systemctl start tomcat
sudo systemctl stop tomcat
sudo systemctl restart tomcat
sudo systemctl status tomcat
# Real-time log monitoring
sudo tail -f /opt/tomcat/latest/logs/catalina.out
# Validate configuration
sudo -u tomcat /opt/tomcat/latest/bin/catalina.sh configtest
# Check port usage
sudo ss -tlnp | grep 8080
Firewall Configuration
# Ubuntu/Debian (ufw)
sudo ufw allow 8080/tcp
sudo ufw reload
# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Verifying Installation
# Check Tomcat version
/opt/tomcat/latest/bin/version.sh
# Example output
# Server version: Apache Tomcat/10.1.20
# JVM Version: 17.0.x
# Check HTTP response
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080
# 200
Summary
| Item | Details |
|---|---|
| Tomcat version | 10.1.x recommended (Java 11+), 11.x (Java 17+) |
| Java requirement | Tomcat 9: Java 8+, Tomcat 10+: Java 11+ |
| JVM option location | $CATALINA_HOME/bin/setenv.sh (recommended) |
| Key config files | conf/server.xml, conf/web.xml, conf/context.xml |
| Deployment directory | webapps/ (WAR auto-extraction) |
| Service management | systemctl start/stop/restart tomcat |