Saltar a contenido

3.7.-Servidor de aplicaciones con Tomcat

3.7. Servidor de aplicaciones con Tomcat

Idea principal

Tomcat proporciona el entorno en el que se ejecutan aplicaciones web Java. Prepararlo implica disponer de un programa de ejecución compatible, reconocer sus directorios, configurar el puerto y poner a disposición un paquete de aplicación como un archivo WAR.

Servidor de aplicaciones en una arquitectura web
El servidor web recibe la petición y coopera con el servidor de aplicaciones, que ejecuta la lógica y consulta otros servicios.

En la secuencia de la unidad, Tomcat se incorpora después de preparar el entorno y antes de ejecutar las pruebas formales. Aquí se aborda la instalación y configuración básica del servidor de aplicaciones; la cooperación detallada con Nginx y la administración avanzada se reservan para actividades posteriores.

Este documento desarrolla exclusivamente el criterio de evaluación siguiente:

Código Descripción
RA1 Implanta arquitecturas web analizando y aplicando criterios de funcionalidad.
CE d Se ha realizado la instalación y configuración básica de servidores de aplicaciones.

Qué deberías saber al terminar

Deberías poder:

  • explicar qué aporta un servidor de aplicaciones frente a un servidor web;
  • localizar el runtime, la configuración, las aplicaciones y los registros de Tomcat;
  • configurar el puerto básico y desplegar una aplicación WAR.

Mapa del tema

Estudiaremos la función de Tomcat, sus requisitos, la estructura de la instalación, la configuración del puerto y el despliegue de un WAR.

1. Qué aporta un servidor de aplicaciones

Un servidor web puede entregar archivos estáticos, pero una aplicación dinámica necesita ejecutar código, gestionar solicitudes, cargar componentes y aplicar reglas de sesión o seguridad. Tomcat implementa el contenedor de servlets: un servlet es una clase Java que recibe una petición y participa en la creación de la respuesta. Tomcat también proporciona el ciclo de vida necesario para ejecutar esas aplicaciones web Java.

Servidor de aplicaciones

Es el software que ofrece un entorno de ejecución y servicios para una aplicación del lado servidor, como gestión de solicitudes, ciclo de vida, configuración y acceso a componentes de la plataforma.

En este tema se utiliza «servidor de aplicaciones» en el sentido habitual del módulo: un servidor que ejecuta una aplicación web y le proporciona un contenedor web. Conviene hacer una precisión técnica: Tomcat es, en sentido estricto, un contenedor de servlets y JSP, no una plataforma Jakarta EE completa. Productos como WildFly ofrecen, además, servicios empresariales como EJB, JTA o JMS. Por tanto, una aplicación WAR que necesite esos servicios no se puede trasladar a Tomcat sin comprobar antes sus dependencias y su arquitectura.

Componente Responsabilidad principal Ejemplo
Servidor web HTTP, contenido estático y punto de entrada Nginx
Contenedor web Ciclo de vida de servlets, sesiones y aplicaciones WAR Tomcat
Plataforma empresarial Servicios Jakarta EE adicionales, como EJB o JTA WildFly

La tabla no implica que haya que instalar siempre los tres componentes. Una aplicación pequeña puede exponerse directamente mediante Tomcat; en una arquitectura con tráfico real suele colocarse Nginx delante para separar el acceso público del servicio que ejecuta la aplicación.

Tomcat puede recibir peticiones directamente durante una práctica o estar detrás de un servidor web como Nginx. En el segundo caso, Nginx suele ser el punto de entrada público y Tomcat queda en una red interna. Separar los papeles no significa que siempre sean necesarios dos equipos.

flowchart LR
  C["Cliente"] -->|"HTTP :80"| W["Nginx o servidor web"]
  W -->|"Red interna :8080"| T["Tomcat"]
  T --> WAR["Aplicación desplegada"]
  T --> LOG["logs y configuración"]

La petición no salta directamente desde el conector hasta una carpeta. Tomcat la hace pasar por una jerarquía de configuración. Esta vista simplificada ayuda a relacionar los nombres que aparecen después en server.xml:

flowchart TD
  C["Cliente"] --> CO["Connector HTTP :8080"]
  subgraph T["Tomcat"]
    SV["Service"] --> EN["Engine Catalina"]
    EN --> HO["Host localhost"]
    HO --> CT["Context /catalogo"]
    CT --> APP["Servlets y recursos de la aplicación"]
    CO --> SV
  end
  APP --> DB["Base de datos u otros servicios"]

El connector acepta la comunicación; el engine, el host y el context ayudan a seleccionar la aplicación que debe atenderla. No es necesario memorizar toda la jerarquía para instalar Tomcat, pero sí identificar qué parte se está configurando cuando se cambia el puerto, el nombre de host o el contexto de una aplicación.

2. Requisitos y opciones de instalación

Tomcat necesita una versión compatible de Java. Llamamos runtime al programa que permite ejecutar la aplicación; en este caso es la máquina virtual de Java. La versión concreta depende de la versión de Tomcat y de la aplicación, así que se debe consultar la matriz de compatibilidad, una tabla que indica qué versiones pueden utilizarse juntas. Comprueba el runtime disponible con:

java --version

La compatibilidad no depende únicamente de que Java pueda iniciar el proceso. También debe coincidir la API de servlets con la que se compiló el WAR. Como regla orientativa, Tomcat 9 pertenece al ecosistema Java EE 8 y utiliza el espacio de nombres javax.servlet, mientras que Tomcat 10 y posteriores utilizan jakarta.servlet. Un WAR compilado para una familia no siempre puede ejecutarse en la otra sin migración. Ante un error de clases o de métodos al arrancar, comprueba primero esta combinación antes de modificar la aplicación.

En un servidor Linux se puede instalar el runtime con el gestor de paquetes y descargar Tomcat desde su distribución oficial. En esta unidad también se puede utilizar una imagen Docker para que la versión y los directorios queden declarados junto al resto del entorno:

docker pull tomcat:9.0
docker run --name tomcat-prueba --detach --publish 8080:8080 tomcat:9.0
docker ps

La etiqueta tomcat:9.0 selecciona la familia 9.0, pero una etiqueta puede recibir nuevas revisiones de la imagen. Para un ejercicio es suficiente si se registra la etiqueta y la fecha; para un despliegue reproducible conviene guardar también el resumen de imagen que se ha validado:

docker image inspect tomcat:9.0 --format '{{json .RepoDigests}}'

No se debe utilizar latest en una guía que deba repetirse durante el curso, porque puede cambiar de versión y dejar de ser compatible con el WAR. En una instalación local, el paquete Java, la distribución de Tomcat y su versión deben quedar anotados de la misma forma.

3. Estructura principal de Tomcat

En una instalación oficial descomprimida, CATALINA_HOME identifica el directorio que contiene los binarios y la instalación de Tomcat. CATALINA_BASE identifica los datos de una instancia concreta: configuración, aplicaciones, logs y archivos temporales. Cuando solo existe una instancia, ambas variables suelen apuntar al mismo lugar; separarlas permite ejecutar varias instancias con una misma instalación. En la imagen Docker habitual, el directorio es /usr/local/tomcat y las dos funciones se concentran normalmente allí.

Ruta Finalidad
bin/ Scripts de arranque, parada y utilidades
conf/ Configuración, incluido server.xml
lib/ Bibliotecas comunes del servidor
logs/ Registros de arranque y aplicaciones
webapps/ Aplicaciones desplegadas, como archivos WAR
work/ Archivos de trabajo generados por Tomcat
temp/ Archivos temporales

Además de las carpetas, identifica estos archivos antes de cambiar una configuración:

Archivo Para qué sirve
conf/server.xml Estructura del servidor y conectores, incluido el puerto
conf/context.xml Valores por defecto de los contextos de aplicación
conf/web.xml Configuración web por defecto de las aplicaciones
conf/tomcat-users.xml Usuarios y roles de los realms basados en fichero
bin/catalina.sh Arranque, parada y operaciones de la instancia

Una aplicación también puede aportar su propio WEB-INF/web.xml y un contexto específico, por lo que no conviene resolver todos los problemas editando el server.xml. La configuración global, la de la aplicación y la generada deben mantenerse diferenciadas.

En un contenedor se pueden consultar las rutas sin modificar la imagen:

docker exec tomcat-prueba ls -la /usr/local/tomcat
docker exec tomcat-prueba ls -la /usr/local/tomcat/webapps
docker logs tomcat-prueba

Los directorios logs, work y temp contienen información generada. No conviene editarlos manualmente ni confundirlos con la configuración que se debe versionar.

4. Configurar el puerto de escucha

El conector HTTP habitual de Tomcat escucha en el puerto 8080. En una instalación local, el puerto se configura en conf/server.xml, dentro de un conector parecido a este:

<Connector port="8080"
           protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

redirectPort="8443" solo indica a qué puerto seguro se podría redirigir una petición que lo necesite; no activa HTTPS por sí mismo. Para servir HTTPS hay que configurar otro conector TLS, su certificado y sus claves de forma segura. Esa configuración pertenece a un escenario posterior y no es necesaria para comprobar la instalación HTTP básica.

El puerto del proceso y el puerto publicado por Docker son conceptos distintos. Con -p 8080:8080, el host publica el mismo número; también podría usarse -p 18080:8080 para acceder desde el host mediante 18080 mientras Tomcat continúa escuchando en 8080 dentro del contenedor.

Cuando Nginx y Tomcat comparten una red de Compose, normalmente solo se publica el puerto de Nginx. El servidor web se conecta a tomcat:8080 mediante el nombre del servicio.

Después de cambiar server.xml, reinicia Tomcat y comprueba ambos extremos del recorrido. En una instalación local puedes revisar el socket con ss; en Docker debes distinguir el puerto interno del mapeo del host:

ss -ltn | grep ':8080'
curl --include --max-time 10 http://localhost:8080/
docker port tomcat-prueba

Que exista un proceso escuchando no garantiza que una aplicación esté desplegada, pero sí permite separar un problema de red de un problema del WAR.

5. Desplegar una aplicación WAR

Un archivo WAR (Web Application Archive) contiene una aplicación web Java preparada para que Tomcat la cargue. Su nombre suele determinar el contexto inicial: catalogo.war puede quedar accesible bajo /catalogo, aunque la aplicación puede definir otros ajustes.

Su estructura mínima puede representarse así:

catalogo.war
├── index.html o recursos públicos
├── WEB-INF/
│   ├── web.xml
│   ├── classes/       # clases compiladas
│   └── lib/           # dependencias de la aplicación
└── META-INF/
    └── context.xml    # configuración opcional del contexto

WEB-INF no se sirve directamente al cliente. Tomcat lo utiliza para cargar clases, dependencias y configuración. El nombre del archivo es una convención útil, no una garantía absoluta: un descriptor de contexto puede cambiar la ruta de acceso. Para revisar un WAR sin desplegarlo se puede inspeccionar su contenido:

jar tf catalogo.war | sed -n '1,40p'

Para una prueba con un contenedor se puede copiar el artefacto al directorio de despliegue:

docker cp catalogo.war tomcat-prueba:/usr/local/tomcat/webapps/
docker logs -f tomcat-prueba

Tomcat detecta el WAR y prepara la aplicación según su configuración. En un entorno reproducible es preferible construir una imagen o declarar el montaje de forma explícita, en lugar de copiar archivos sin registrar el procedimiento.

Por ejemplo, una imagen mínima deja el artefacto y su versión asociados al proceso de construcción:

FROM tomcat:9.0
COPY catalogo.war /usr/local/tomcat/webapps/catalogo.war

El procedimiento de copia sirve para una comprobación rápida; la imagen es más adecuada para repetir el despliegue. En ambos casos, el contexto esperado sería http://localhost:8080/catalogo/. Si el archivo se llamase ROOT.war, la ruta sería /, por lo que conviene elegir el nombre de forma consciente.

La aplicación debe ser compatible con la versión de Java y con la versión de Tomcat elegida. Si el WAR usa una API distinta, el arranque puede fallar aunque el servidor esté correctamente instalado.

No todos los WAR se despliegan automáticamente: esa conducta depende de la configuración del Host, de opciones como deployOnStartup y de los permisos del proceso. Por eso la evidencia debe combinar el archivo presente, el log de despliegue y una petición HTTP a la ruta del contexto.

5.1. Ciclo de vida y configuración básica

En una instalación gestionada por el sistema, el ciclo de vida puede utilizar systemctl; en un contenedor se gestiona el proceso mediante Docker:

docker start tomcat-prueba
docker stop tomcat-prueba
docker restart tomcat-prueba
docker inspect tomcat-prueba

Una comprobación básica del despliegue puede documentarse con una secuencia pequeña y repetible:

docker exec tomcat-prueba test -f /usr/local/tomcat/webapps/catalogo.war
curl --include --max-time 10 http://localhost:8080/catalogo/
docker logs --since=5m tomcat-prueba

La respuesta HTTP confirma el acceso al contexto, mientras que el registro permite saber si el error se produjo al cargar clases, al crear la aplicación o al atender la petición. La prueba formal de toda la cadena con Nginx se realiza en el punto 3.8. Pruebas de funcionamiento del despliegue.

Para una configuración básica documenta siempre:

  • versión de Java y de Tomcat;
  • directorio de instalación o imagen utilizada;
  • puerto interno y puerto publicado;
  • ubicación y formato del artefacto desplegado;
  • variables, montajes y red del servicio;
  • comandos de inicio, parada y consulta de registros.

Estas operaciones comprueban que la instalación se puede administrar. El plan de pruebas de accesibilidad, integración y recuperación se desarrolla en 3.8. Pruebas de funcionamiento del despliegue.

6. Buenas prácticas

  • Comprobar compatibilidad: relaciona versión de Java, Tomcat y aplicación antes de desplegar el WAR.
  • No exponer por defecto el backend: publica Tomcat solo cuando la práctica lo necesite y utiliza una red interna detrás de Nginx en escenarios reales.
  • Separar artefacto y datos: un WAR puede reemplazarse, pero los datos de la aplicación deben mantenerse en su almacenamiento adecuado.
  • Fijar versiones: registra la imagen o distribución exacta que se ha utilizado y revisa sus actualizaciones de seguridad.
  • Consultar los registros: ante un fallo de despliegue, lee el log antes de modificar varias configuraciones a la vez.
  • Ejecutar con privilegios mínimos: utiliza una cuenta de servicio sin permisos de administración y no expongas la aplicación de gestión de Tomcat fuera de la red autorizada.
  • Separar configuración y artefacto: versiona el procedimiento y los archivos de configuración, pero no incluyas contraseñas ni claves en el WAR, en la imagen o en el repositorio.

7. Errores frecuentes

Error frecuente Por qué ocurre Cómo evitarlo
Usar una versión incompatible de Java Se instala el runtime disponible sin comprobar la matriz Comprueba la compatibilidad de la aplicación y Tomcat
Confundir 8080 interno con el puerto del host Se mezclan proceso y publicación Documenta ambos valores por separado
Copiar el WAR a un directorio incorrecto Se desconoce CATALINA_HOME Localiza webapps y verifica el nombre del artefacto
Exponer Tomcat a Internet sin necesidad Se prueba con el navegador y se olvida el proxy Publica solo el servidor web en el escenario final
Editar archivos generados en work o temp Se confunden resultados con configuración Cambia conf o el proceso de construcción
Tratar Tomcat como una plataforma Jakarta EE completa Se mezclan Tomcat y WildFly como si ofrecieran los mismos servicios Comprueba si el WAR necesita EJB, JTA, JMS u otros servicios empresariales
Mezclar javax.* y jakarta.* Se cambia de Tomcat 9 a Tomcat 10 sin revisar la API Alinea servidor, dependencias y compilación del WAR
Pensar que redirectPort activa HTTPS Se interpreta el atributo como una configuración TLS completa Configura un conector TLS y certificados en un ejercicio específico
Confundir el nombre del WAR con cualquier URL Se olvida que el contexto puede declararse de otra forma Verifica el contexto efectivo y prueba la URL resultante

8. Resumen

En este tema has aprendido que:

  • Tomcat proporciona un entorno para ejecutar aplicaciones web Java;
  • necesita un runtime compatible y una configuración básica de puerto;
  • conf, webapps, logs, work y lib cumplen funciones diferentes;
  • Tomcat es un contenedor web y no sustituye automáticamente a una plataforma Jakarta EE completa;
  • un WAR tiene una estructura y un contexto que deben ser compatibles con el servidor;
  • el despliegue se valida combinando archivos, logs y una petición HTTP.

Idea clave

Preparar Tomcat significa dejar identificado el runtime, la versión del servidor, el puerto, el artefacto y el ciclo de vida; sin esos datos, el despliegue no se puede repetir ni diagnosticar.

9. Para seguir practicando

Bibliografía y fuentes

Presentación

La presentación acompaña este apunte con el recorrido de instalación, estructura, configuración del puerto y despliegue de un WAR.

También puede consultarse la presentación publicada sobre servidores de aplicaciones, que amplía los servicios del servidor y su integración con el servidor web.