Antes de empezar. El backend está organizado por capas y su CI ya funciona. Hoy publicarás esa versión en memoria y comprobarás su respuesta desde una URL pública.
Antes de empezar · sin apuntes
- La API escucha en un puerto determinado del entorno local. ¿Qué elemento del sistema establece ese número?
- En producción no hay nadie mirando la consola. Si la aplicación no arranca, ¿dónde se lee el motivo?
- ¿Qué diferencia hay entre desplegar unos ficheros HTML y desplegar un programa que se ejecuta?
Se explica
25 minutos · explicación y demostración
Del JAR a un proceso accesible
Una web estática publica archivos; una aplicación Java necesita además un proceso en ejecución. El CI produce el JAR y el despliegue lo entrega al servicio. Un workflow verde no demuestra todavía que el proceso haya arrancado o responda en su ruta.
Puerto y configuración del runtime elegido
Este taller emplea App Service con publicación de tipo Código y runtime Java SE, no un contenedor personalizado. El entorno Java expone la variable SERVER_PORT, cuyo valor Spring Boot puede resolver; la configuración debe mantenerse compatible con ese entorno y el puerto efectivo debe verificarse en el registro del servicio. WEBSITES_PORT pertenece a la configuración de contenedores personalizados y no se añade aquí como solución genérica. Referencia oficial de App Service.
Entorno de aula
Antes de aprovisionar recursos conviene verificar la oferta y los límites que declara la suscripción. El plan F1, cuando esté disponible para la combinación seleccionada, impone cuotas y puede suspender la aplicación por inactividad. La primera respuesta puede tardar más que las siguientes. Utiliza el entorno de prácticas disponible conservando el mismo repositorio y artefacto.
Se trabaja
140 minutos · trabajo guiado sobre el producto compartido
Bloque A · Verificación del puerto de escucha
Abre application.properties y revisa si existe una propiedad server.port. En este taller puede escribirse server.port=${SERVER_PORT:8080}: usa el puerto del entorno cuando esté definido y 8080 en local. Conserva el resto de configuración. Arranca la API, anota el puerto de los logs y prueba una ruta conocida. Más adelante repetirás esa comprobación en el runtime Java SE del proveedor.
Bloque B · Crear el servicio en Azure
Todos a la vez, a la misma pantalla
En portal.azure.com, localiza App Services y selecciona Crear → Aplicación web.
| Campo | Valor |
|---|---|
| Suscripción | Azure for Students |
| Grupo de recursos | El mismo del portfolio, o uno nuevo |
| Nombre | Prefijo api- seguido de un identificador propio: forma parte de la URL pública |
| Publicar | Código |
| Pila del entorno de ejecución | La versión de Java registrada en la sesión 7, no la propuesta por defecto |
| Servidor web de Java | Java SE (servidor web integrado) |
| Sistema operativo | Linux |
| Región | West Europe |
| Plan de precios | F1 gratuito |
Revisar y crear. Al finalizar el aprovisionamiento, accede mediante Ir al recurso y abre la URL: el servicio devuelve la página predeterminada de App Service, dado que aún no se ha desplegado ningún artefacto.
Verificar el runtime. Confirma Código, Java SE y la misma versión de Java del pom. No añadas WEBSITES_PORT: no estamos publicando una imagen propia. Después del despliegue comprueba SERVER_PORT y el puerto de arranque en el registro del servicio. Si no coincide, revisa la propiedad server.port y los argumentos de arranque antes de cambiar otras opciones.
Bloque C · Conexión del servicio con el repositorio
Ejecución simultánea
- En el recurso, menú lateral → Centro de implementación (Deployment Center).
- Origen: GitHub. Autoriza el acceso si el portal lo solicita.
- Organización, repositorio
api-loquesea, ramamain. - Selecciona la identidad federada del entorno de prácticas y verifica que el workflow declara los permisos y la conexión previstos. Ante un fallo de configuración, la activación de la autenticación básica no constituye una solución: sustituye un mecanismo de credenciales efímeras por uno de credenciales permanentes y oculta el defecto en lugar de corregirlo.
- Guardar.
Es previsible que el centro de implementación intente escribir directamente sobre main y sea rechazado por la protección configurada en la UD1. El comportamiento esperado es precisamente ese. El workflow se prepara en una rama y se incorpora mediante pull request, como cualquier otro cambio; la desactivación de las reglas de protección para permitir esa escritura no es un procedimiento admisible. Las credenciales residen en Secrets o en la conexión federada, nunca en el propio archivo YAML.
Conviene contrastar esta configuración con la de la sesión 1. La plantilla de GitHub Pages no requería credencial alguna porque el sistema que despliega y el que aloja pertenecen al mismo proveedor, lo que permite emitir un token efímero de ámbito interno. Aquí intervienen dos proveedores distintos, de modo que resulta necesario acreditar la identidad de uno ante el otro: es el caso de credenciales al que se aludió entonces. Obtén el archivo generado y analízalo:
git switch main
git pull
Localiza en el archivo las dos diferencias respecto al del portfolio: existe una etapa de compilación previa al despliegue, y existen dos jobs, uno de construcción y otro de publicación, declarando el segundo una dependencia sobre el primero.
- ¿Qué comando de construcción usa el workflow que ha escrito Azure?
- ¿Qué se pasa del primer job al segundo, y por qué no se compila otra vez?
- ¿Cómo se llama el secreto que ha creado?
- ¿Qué versión de Java declara, y coincide con la del proyecto?
Dos workflows con responsabilidades diferenciadas
El workflow propio, ci.yml, se ejecuta sobre cada pull request y su función es impedir la integración de un cambio defectuoso. El generado por Azure se ejecuta una vez el cambio se ha incorporado a main y su función es publicar. La aparición de dos ejecuciones por cada cambio no indica un error de configuración: corresponde a la separación entre integración continua y despliegue continuo ya establecida en el portfolio.
Bloque D · Verificación del arranque y diagnóstico
Trabajo individual · práctica de diagnóstico en producción
Una vez el workflow concluya con éxito, accede a la URL de la API por la ruta que devuelve datos. Los dos resultados posibles requieren actuaciones distintas.
Si responde: repite la petición desde un dispositivo móvil con la red del operador y sin la red del centro. Esa comprobación acredita la accesibilidad pública efectiva del servicio.
Si no responde: no modifiques todavía la configuración. Accede al recurso en el portal, menú lateral → Flujo de registro (Log stream), y examina la salida que emite la aplicación. Corresponde a la salida de consola del entorno local, ahora en el entorno de producción.
| Salida observada en el registro | Diagnóstico |
|---|---|
| La aplicación arranca e indica el puerto | El proceso se ha iniciado correctamente: el defecto está en la ruta solicitada. Verifica la URL completa |
| Excepción durante el arranque | El defecto reside en el código o en la configuración: es el mismo error que se produciría en el entorno local |
| Ausencia de salida y error de aplicación en la URL | Revisa el artefacto, el comando de arranque, el runtime Java SE y las variables de entorno; habilita el registro si todavía no emite información |
El registro como primera herramienta de diagnóstico
La reacción habitual ante un servicio que no responde consiste en repetir el despliegue. Esa operación consume varios minutos y no aporta información diagnóstica; la consulta del registro requiere segundos y determina la causa con precisión. El principio aplicable —obtener evidencia antes de modificar el sistema— distingue la corrección fundamentada de la prueba por tanteo.
curl desde la terminal.Plan alternativo si el plan gratuito no da de sí
El plan F1 impone dos límites relevantes. El primero es 1 GB de memoria. El segundo son 60 minutos de CPU diarios, contabilizados por región y suscripción y compartidos entre todas las aplicaciones gratuitas de esa región: al agotarse, el servicio se detiene y responde con código 403 hasta la medianoche UTC. Una aplicación que entra en un ciclo de arranque y terminación consume esa cuota en pocas horas.
La alternativa es Azure Container Apps, que tiene franja mensual gratuita —180.000 segundos de vCPU, 360.000 de memoria y dos millones de peticiones— y que escala a cero: mientras nadie la usa no consume nada.
Los elementos que no varían son los determinantes: el repositorio, el flujo de integración, el CI, la resolución del puerto, la configuración de CORS y la coordinación entre ambos componentes son idénticos. La única diferencia consiste en desplegar una imagen de contenedor en lugar de un artefacto, imagen que Spring Boot construye mediante ./mvnw spring-boot:build-image sin necesidad de redactar un Dockerfile.
La elección de plataforma se acuerda en clase y para el conjunto del grupo; no procede modificarla de forma individual.
Cierre
15 minutos · comprobación del resultado
Antes de cerrar · sin mirar
- ¿Qué runtime se ha seleccionado y mediante qué procedimiento se verifica el puerto efectivo?
- ¿Por qué el workflow de la API tiene dos jobs y el del portfolio uno?
- La URL devuelve un error y el despliegue ha concluido con éxito. ¿Cuál es la primera actuación?
- ¿Por qué la primera petición del día tarda tanto?
Ver respuestas
1 · Java SE con publicación de código. Contrastamos SERVER_PORT, la configuración de Spring Boot y los logs; WEBSITES_PORT se reserva al caso de contenedores personalizados.
2 · Porque hay que construir antes de desplegar: un job produce el artefacto y el otro lo sube.
3 · Abrir el flujo de registro del servicio. Leer antes que tocar.
4 · Porque el plan gratuito duerme el servicio tras un rato sin uso y la primera petición lo despierta.
Antes de la sesión 9
- La API responde en su URL pública, comprobado fuera de la red del centro.
- Constan registradas la URL de la API y la ruta que devuelve la colección de datos.
- Consta un esquema de la interfaz del portfolio que mostrará esos datos.