Apache Tomcat ist ein Open-Source-Servlet-Container für Java-Webanwendungen. Er implementiert Java Servlet, JSP und WebSocket-Technologien.
Warum Tomcat?
Vorteile
- Leichtgewichtig
- Einfache Konfiguration
- Große Community
- Aktive Entwicklung
- ProduktionsreifTomcat-Versionen
| Version | Java | Servlet | JSP | |---------|------|---------|-----| | Tomcat 10 | 11+ | 6.0 | 3.1 | | Tomcat 9 | 8+ | 4.0 | 2.3 | | Tomcat 8.5 | 7+ | 3.1 | 2.3 |
Voraussetzungen
Java installieren
# OpenJDK 17 (empfohlen)
apt update
apt install openjdk-17-jdk
# Version prüfen
java -version
# JAVA_HOME setzen
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> /etc/profile
source /etc/profileInstallation
Benutzer erstellen
useradd -r -m -d /opt/tomcat -s /bin/false tomcatTomcat herunterladen
cd /tmp
wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.18/bin/apache-tomcat-10.1.18.tar.gz
# Extrahieren
tar -xzf apache-tomcat-10.1.18.tar.gz
mv apache-tomcat-10.1.18/* /opt/tomcat/
# Berechtigungen
chown -R tomcat:tomcat /opt/tomcat
chmod +x /opt/tomcat/bin/*.shVerzeichnisstruktur
/opt/tomcat/
├── bin/ # Start-/Stop-Skripte
├── conf/ # Konfiguration
├── lib/ # Bibliotheken
├── logs/ # Log-Dateien
├── temp/ # Temporäre Dateien
├── webapps/ # Anwendungen
└── work/ # Kompilierte JSPsSystemd-Service
Service-Datei erstellen
# /etc/systemd/system/tomcat.service
[Unit]
Description=Apache Tomcat 10
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"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.targetService aktivieren
systemctl daemon-reload
systemctl enable --now tomcat
systemctl status tomcatKonfiguration
Server-Port ändern
<!-- /opt/tomcat/conf/server.xml -->
<!-- HTTP-Connector -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="150"
minSpareThreads="25" />
<!-- AJP-Connector (für Apache/Nginx) -->
<Connector port="8009" protocol="AJP/1.3"
redirectPort="8443"
secretRequired="false" />Manager-App aktivieren
<!-- /opt/tomcat/conf/tomcat-users.xml -->
<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="admin-gui"/>
<user username="admin" password="SicheresPasswort!"
roles="manager-gui,manager-script,admin-gui"/>
</tomcat-users>Remote-Zugriff auf Manager
<!-- /opt/tomcat/webapps/manager/META-INF/context.xml -->
<Context antiResourceLocking="false" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192\.168\.1\.\d+" />
</Context>Host-Manager (analog)
<!-- /opt/tomcat/webapps/host-manager/META-INF/context.xml -->
<Context antiResourceLocking="false" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|192\.168\.1\.\d+" />
</Context>Anwendung deployen
WAR-Datei kopieren
cp myapp.war /opt/tomcat/webapps/
chown tomcat:tomcat /opt/tomcat/webapps/myapp.war
# Automatisches Deployment
# Tomcat entpackt die WAR automatischÜber Manager-App
URL: http://server-ip:8080/manager/html
→ WAR file to deploy
→ Datei auswählen
→ DeployAnwendung entfernen
# Manuell
rm -rf /opt/tomcat/webapps/myapp
rm /opt/tomcat/webapps/myapp.war
# Oder über Manager-App
→ Applications → UndeployVirtual Hosts
Mehrere Hosts
<!-- /opt/tomcat/conf/server.xml -->
<Engine name="Catalina" defaultHost="localhost">
<!-- Standard-Host -->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
<!-- Zusätzlicher Host -->
<Host name="app.example.com" appBase="app-webapps"
unpackWARs="true" autoDeploy="true">
<Alias>www.app.example.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="app_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>Host-Verzeichnis erstellen
mkdir /opt/tomcat/app-webapps
chown tomcat:tomcat /opt/tomcat/app-webappsSSL/TLS einrichten
Keystore erstellen
keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 \
-keystore /opt/tomcat/conf/keystore.jks \
-validity 365SSL-Connector
<!-- /opt/tomcat/conf/server.xml -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/keystore.jks"
certificateKeystorePassword="passwort"
type="RSA" />
</SSLHostConfig>
</Connector>Let's Encrypt-Zertifikat
# Zertifikat in PKCS12 konvertieren
openssl pkcs12 -export \
-in /etc/letsencrypt/live/example.com/fullchain.pem \
-inkey /etc/letsencrypt/live/example.com/privkey.pem \
-out /opt/tomcat/conf/keystore.p12 \
-name tomcat \
-passout pass:passwort<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/keystore.p12"
certificateKeystorePassword="passwort"
certificateKeystoreType="PKCS12"
type="RSA" />
</SSLHostConfig>
</Connector>Nginx als Reverse Proxy
Nginx-Konfiguration
# /etc/nginx/sites-available/tomcat
upstream tomcat {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name app.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / {
proxy_pass http://tomcat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Tomcat für Proxy konfigurieren
<!-- /opt/tomcat/conf/server.xml -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
proxyName="app.example.com"
proxyPort="443"
scheme="https"
secure="true" />Apache mod_jk (AJP)
Apache-Modul installieren
apt install libapache2-mod-jkWorker-Konfiguration
# /etc/libapache2-mod-jk/workers.properties
worker.list=tomcat
worker.tomcat.type=ajp13
worker.tomcat.host=localhost
worker.tomcat.port=8009Apache Virtual Host
# /etc/apache2/sites-available/tomcat.conf
<VirtualHost *:80>
ServerName app.example.com
JkMount /* tomcat
# Statische Dateien direkt
JkUnMount /static/* tomcat
Alias /static /var/www/static
</VirtualHost>Performance-Tuning
JVM-Optionen
# /opt/tomcat/bin/setenv.sh
#!/bin/sh
CATALINA_OPTS="-Xms1024M -Xmx2048M"
CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC"
CATALINA_OPTS="$CATALINA_OPTS -XX:MaxGCPauseMillis=200"
CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
CATALINA_OPTS="$CATALINA_OPTS -XX:HeapDumpPath=/opt/tomcat/logs/"
export CATALINA_OPTSchmod +x /opt/tomcat/bin/setenv.shConnector-Tuning
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="25"
maxConnections="10000"
acceptCount="100"
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,application/json" />Session-Konfiguration
<!-- /opt/tomcat/conf/web.xml oder app/WEB-INF/web.xml -->
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>Sicherheit
Sicherheits-Checkliste
<!-- /opt/tomcat/conf/server.xml -->
<!-- 1. Server-Info verstecken -->
<Connector port="8080" ...
server="Apache" />
<!-- 2. Shutdown-Port deaktivieren -->
<Server port="-1" shutdown="SHUTDOWN">Error-Seiten
<!-- /opt/tomcat/conf/web.xml -->
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.html</location>
</error-page>Security Manager
# Aktivieren (optional, erhöht Sicherheit)
/opt/tomcat/bin/startup.sh -securityUnnötige Apps entfernen
# In Produktion entfernen
rm -rf /opt/tomcat/webapps/ROOT
rm -rf /opt/tomcat/webapps/docs
rm -rf /opt/tomcat/webapps/examples
# Manager-Apps nur bei Bedarf behaltenLogging
Logging-Konfiguration
# /opt/tomcat/conf/logging.properties
handlers = 1catalina.org.apache.juli.AsyncFileHandler, \
2localhost.org.apache.juli.AsyncFileHandler, \
java.util.logging.ConsoleHandler
1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
1catalina.org.apache.juli.AsyncFileHandler.maxDays = 30Access Log
<!-- /opt/tomcat/conf/server.xml -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D" />Log-Rotation
# /etc/logrotate.d/tomcat
/opt/tomcat/logs/catalina.out {
copytruncate
daily
rotate 7
compress
missingok
notifempty
}Monitoring
JMX aktivieren
# /opt/tomcat/bin/setenv.sh
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=9090"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"Server Status
URL: http://server-ip:8080/manager/statusPrometheus JMX Exporter
# Agent herunterladen
wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.19.0/jmx_prometheus_javaagent-0.19.0.jar \
-O /opt/tomcat/lib/jmx_exporter.jar# /opt/tomcat/conf/jmx_exporter.yml
rules:
- pattern: ".*"# setenv.sh
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/tomcat/lib/jmx_exporter.jar=9404:/opt/tomcat/conf/jmx_exporter.yml"Backup
Backup-Skript
#!/bin/bash
# /usr/local/bin/tomcat-backup.sh
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backup/tomcat"
TOMCAT_HOME="/opt/tomcat"
mkdir -p $BACKUP_DIR
# Tomcat stoppen (optional)
# systemctl stop tomcat
# Konfiguration und Apps sichern
tar -czf $BACKUP_DIR/tomcat-$DATE.tar.gz \
$TOMCAT_HOME/conf \
$TOMCAT_HOME/webapps
# Tomcat starten (falls gestoppt)
# systemctl start tomcat
# Alte Backups löschen
find $BACKUP_DIR -type f -mtime +30 -deleteTroubleshooting
Tomcat startet nicht
# Logs prüfen
tail -f /opt/tomcat/logs/catalina.out
# Port belegt?
netstat -tlnp | grep 8080
# Java-Version
java -versionOutOfMemoryError
# Heap erhöhen
# setenv.sh
CATALINA_OPTS="-Xms1024M -Xmx4096M"
# Heap-Dump analysieren
jmap -dump:live,format=b,file=heap.hprof $(pgrep -f tomcat)Deployment-Probleme
# WAR-Datei prüfen
jar -tvf myapp.war
# Berechtigungen
chown tomcat:tomcat /opt/tomcat/webapps/myapp.warZusammenfassung
| Verzeichnis | Inhalt | |-------------|--------| | conf/ | Konfiguration | | webapps/ | Anwendungen | | logs/ | Log-Dateien | | lib/ | Bibliotheken |
| Befehl | Funktion | |--------|----------| | startup.sh | Tomcat starten | | shutdown.sh | Tomcat stoppen | | catalina.sh run | Im Vordergrund starten |
Fazit
Apache Tomcat ist ein zuverlässiger Servlet-Container für Java-Anwendungen. Die Konfiguration über XML-Dateien ist flexibel, erfordert aber Einarbeitung. Für Produktivumgebungen empfiehlt sich ein Reverse Proxy (Nginx/Apache) vor Tomcat, SSL-Terminierung und angepasste JVM-Optionen. Entfernen Sie nicht benötigte Beispiel-Anwendungen und sichern Sie den Manager-Zugang.