Skip to content

Tomcat

Apache Tomcat chart for Kubernetes using the official docker.io/library/tomcat image. The chart supports immutable application images, mounted WARs, optional writable webapps, JMX, and modern ingress patterns.

Security Scan

Framework Score
MITRE + NSA + SOC2 95%

Security posture is strong. Remaining findings are documented product exceptions for opt-in NetworkPolicy ingress and egress boundaries.

Key Features

  • Official Tomcat image pinned to 11.0.24-jdk17-temurin-noble
  • Optional ROOT health webapp for deterministic probes and Helm tests
  • Copies image-baked webapps into writable runtime volume when needed
  • Writable webapps, logs, temp, and work volumes for non-root runtime
  • Ingress, Gateway API, dual-stack Service fields, NetworkPolicy, HPA, PDB, persistent webapps/logs, and JMX

Installation

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install tomcat helmforge/tomcat --namespace tomcat --create-namespace
helm install tomcat oci://ghcr.io/helmforgedev/helm/tomcat --namespace tomcat --create-namespace

Examples

Application probes through TCP:

webapps:
  defaultRoot:
    enabled: false
startupProbe:
  mode: tcp
livenessProbe:
  mode: tcp
readinessProbe:
  mode: tcp

JMX:

jmx:
  enabled: true
  hostname: tomcat.example.local

Operations

Prefer immutable Tomcat images or init containers that fetch versioned WAR artifacts. Enable JMX only on trusted networks and add authentication or TLS flags through jmx.extraOpts when exposing remote JMX.

Architecture

The chart deploys the official Tomcat image with a writable application layer for webapps, logs, temp, and work. This keeps the container security posture strict while still allowing Tomcat to unpack WARs and write runtime files.

Application delivery options:

  1. Bake WAR files or exploded applications into a custom Tomcat image.
  2. Mount WAR artifacts through an init container and shared volume.
  3. Use webapps.persistence for controlled mutable deployments.
  4. Disable the default ROOT health webapp when your application provides its own health endpoint.

The default ROOT application exists only to make probes and Helm tests deterministic on a fresh install.

Production Values

For production applications, disable the sample ROOT app, switch probes to an application-safe endpoint or TCP mode, and configure routing explicitly:

replicaCount: 2

webapps:
  defaultRoot:
    enabled: false
  copyImageContent:
    enabled: true

startupProbe:
  mode: tcp
livenessProbe:
  mode: tcp
readinessProbe:
  mode: tcp

gatewayAPI:
  enabled: true
  parentRefs:
    - name: public-gateway
      namespace: gateway-system
  hostnames:
    - tomcat.example.com

networkPolicy:
  enabled: true
  ingress:
    extraFrom:
      - namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: gateway-system
  egress:
    enabled: true
    extraTo:
      - ipBlock:
          cidr: 10.80.0.0/16

Deploying Applications

For immutable images, keep webapps.copyImageContent.enabled=true; the chart copies image-baked contents from /usr/local/tomcat/webapps into the writable volume only when that volume is empty.

For artifact-driven deployments, add an init container:

extraInitContainers:
  - name: fetch-war
    image: docker.io/curlimages/curl:8.17.0
    command:
      - sh
      - -ec
      - |
        curl -fsSL "$WAR_URL" -o /webapps/ROOT.war
    env:
      - name: WAR_URL
        value: https://artifacts.example.com/apps/myapp-1.2.3.war
    volumeMounts:
      - name: webapps
        mountPath: /webapps

Use persistent webapps only when applications are intentionally installed or mutated at runtime:

webapps:
  persistence:
    enabled: true
    size: 20Gi
logs:
  persistence:
    enabled: true
    size: 10Gi

Reverse Proxy Configuration

When Tomcat is behind an ingress controller or Gateway, configure connector proxy attributes so applications generate correct absolute URLs and redirects:

tomcat:
  serverXml: |
    <Server port="8005" shutdown="SHUTDOWN">
      <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1"
          proxyName="tomcat.example.com"
          proxyPort="443"
          scheme="https"
          secure="true" />
        <Engine name="Catalina" defaultHost="localhost">
          <Host name="localhost" appBase="webapps" />
        </Engine>
      </Service>
    </Server>

Use tomcat.existingServerXmlConfigMap when platform teams manage the full server configuration externally.

JMX

Remote JMX is opt-in and should stay on trusted networks:

jmx:
  enabled: true
  hostname: tomcat.example.local
  extraOpts: '-Dcom.sun.management.jmxremote.local.only=false'

networkPolicy:
  enabled: true
  ingress:
    extraFrom:
      - namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: monitoring

For authenticated or TLS-secured JMX, mount the required files with extraVolumes and append the JVM flags through jmx.extraOpts.

Validation

After deployment:

helm test tomcat -n tomcat
kubectl get pods -n tomcat -l app.kubernetes.io/name=tomcat
kubectl logs -n tomcat deploy/tomcat --since=10m
kubectl get events -n tomcat --sort-by=.lastTimestamp

If probes use HTTP paths, confirm the deployed application serves those paths before disabling the default ROOT health webapp.

Common Issues

Symptom Likely Cause Fix
Probe failures after deploying a WAR /health.jsp no longer exists Switch probes to TCP or configure app-specific probe paths.
Redirects use http:// behind TLS Connector proxy attributes missing Set proxyName, proxyPort, scheme, and secure.
Image-baked apps disappear Writable webapps volume hides image content Keep webapps.copyImageContent.enabled=true.
JMX cannot connect RMI hostname or NetworkPolicy is wrong Set jmx.hostname and allow monitoring namespace traffic.

Values

Parameter Default Description
replicaCount 1 Number of Tomcat pods when HPA is disabled.
image.repository docker.io/library/tomcat Official Tomcat image repository.
image.tag 11.0.24-jdk17-temurin-noble Tomcat image tag.
webapps.defaultRoot.enabled true Render minimal ROOT app for health checks.
webapps.copyImageContent.enabled true Copy image-baked webapps into writable volume.
webapps.persistence.enabled false Persist /usr/local/tomcat/webapps.
logs.persistence.enabled false Persist Tomcat logs.
jmx.enabled false Enable JMX remote settings and Service ports.
gatewayAPI.enabled false Render Gateway API HTTPRoute.
networkPolicy.enabled false Render NetworkPolicy.
networkPolicy.egress.extraTo [] Additional peers for built-in egress rules.
networkPolicy.egress.extraEgress [] Additional complete NetworkPolicy egress rules.