Objetivos de aprendizaje
Después de leer este artículo podrás:
- Generar el JAR (Spring Boot) o la carpeta publicada (.NET) listos para producción
- Configurar puerto y dirección leyendo variables de entorno
- Verificar el deploy y corregir los errores más comunes de puerto y memoria
En esta página
- ¿Qué necesitas antes de hospedar?
- ¿Cómo crear y compilar la API en Java con Spring Boot?
- ¿Cómo crear y publicar la API en .NET?
- ¿Por qué la API escucha en 0.0.0.0 y lee el puerto del entorno?
- ¿Cómo verificar que el deploy funcionó?
- ¿Cuáles son los errores más comunes?
- Cómo hacerlo en Square Cloud
- Preguntas frecuentes
Una API Java o .NET suele funcionar en tu máquina porque tiene el JDK o el SDK, el puerto libre y las variables correctas. En producción cambian tres cosas: en lugar del código fuente, envías un artefacto compilado; el puerto viene del entorno; y el proceso debe aceptar conexiones desde fuera del contenedor.
Esta guía usa Spring Boot para Java y una Minimal API de ASP.NET Core para .NET. El camino es el mismo en ambos: compilar, parametrizar el puerto, ejecutar en local como en producción, subir y verificar. Para la visión general de cualquier API, mira cómo hospedar una API.
¿Qué necesitas antes de hospedar?#
- Java: un JDK que cumpla el mínimo de tu versión de Spring Boot, según sus requisitos del sistema. Para un proyecto nuevo, usa una LTS actual de Java (calendario de soporte de Oracle). Para el build, una versión reciente de Maven o de Gradle; la misma página indica el mínimo de cada uno.
- .NET: el SDK de la LTS actual de .NET. La política de soporte de Microsoft muestra cuál es y hasta cuándo recibe correcciones cada versión.
- Un endpoint de salud (
/health) para probar el deploy sin depender de base de datos ni de autenticación. - Un lugar donde ejecutarla, con el runtime correspondiente. Si aún comparas opciones, mira VPS vs plataforma en la nube.
¿Cómo crear y compilar la API en Java con Spring Boot?#
Genera el proyecto en start.spring.io con la dependencia Spring Web. Esta es la clase principal, ya con el endpoint de salud:
package com.example.demo;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/health")
public Map<String, String> health() {
return Map.of("status", "ok");
}
}En src/main/resources/application.properties, deja el puerto configurable:
server.port=${PORT:8080}server.port=${PORT:8080}: lee la variablePORTy usa8080cuando no existe. La documentación de Spring Boot también aceptaSERVER_PORTdirectamente en el entorno, gracias al relaxed binding. El valor por defecto del framework es 8080.- Cierre: el graceful shutdown ya viene activado por defecto en Spring Boot: al recibir la señal de parada, el servidor termina las peticiones en curso antes de cerrarse. No necesita configuración extra.
Compila y ejecuta el JAR como lo harás en producción:
./mvnw -DskipTests package
PORT=9090 java -jar target/demo-0.0.1-SNAPSHOT.jar
curl http://localhost:9090/healthEl spring-boot-maven-plugin ya viene en el proyecto generado y empaqueta un JAR ejecutable con todo dentro (un fat JAR). Con Gradle el equivalente es ./gradlew bootJar. El nombre del archivo sale del artifactId y de la versión. Renómbralo a algo corto, como app.jar, antes de subirlo: así es más fácil indicar el archivo principal.
¿Cómo crear y publicar la API en .NET?#
Crea el proyecto y reemplaza Program.cs:
dotnet new web -n MiApi
cd MiApivar builder = WebApplication.CreateBuilder(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
builder.WebHost.UseUrls($"http://0.0.0.0:{port}");
var app = builder.Build();
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));
app.Run();ASP.NET Core no lee la variable PORT por sí solo, por eso el código se encarga de leerla. Kestrel escucha solo en localhost por defecto, y 0.0.0.0 hace que acepte conexiones desde fuera del contenedor. La alternativa sin código es definir ASPNETCORE_URLS=http://0.0.0.0:8080 en el entorno.
Publica en modo Release y prueba la carpeta de salida:
dotnet publish -c Release -o out
PORT=9090 dotnet out/MiApi.dll
curl http://localhost:9090/healthLo que sube al servidor es el contenido de la carpeta out: la DLL principal, las dependencias y los archivos .json de configuración. No envíes las carpetas bin y obj.
¿Por qué la API escucha en 0.0.0.0 y lee el puerto del entorno?#
En un contenedor o en una plataforma de hosting, quien decide el puerto y la dirección de entrada es el servidor, no tu código. Escuchar en localhost (127.0.0.1) solo acepta conexiones desde dentro del propio contenedor, así que el proxy que está delante nunca llega a tu proceso. Fijar el puerto en el código funciona hasta que el servidor pide otro. Por eso los dos ejemplos traen un valor por defecto para desarrollo y aceptan el cambio por variable de entorno. Para profundizar, mira qué son las variables de entorno.
Los secretos, como la cadena de conexión y las claves de API, siguen la misma regla: vienen del entorno, nunca del repositorio. En Spring Boot, DB_URL se usa como ${DB_URL} en application.properties. En .NET, builder.Configuration["DB_URL"] ya lee variables de entorno.
¿Cómo verificar que el deploy funcionó?#
- Logs: busca la línea de arranque, con el puerto configurado. En Spring:
Tomcat started on port 8080. En .NET:Now listening on: http://0.0.0.0:8080. - Endpoint de salud:
curl -i https://tu-dominio/healthdebe devolver200y{"status":"ok"}. - Reinicio: reinicia la aplicación y confirma que vuelve sola y que los logs no muestran peticiones cortadas a la mitad.
- Memoria: observa el consumo tras algunas peticiones. La JVM y el runtime de .NET reservan memoria más allá de lo que usa tu código, así que el primer valor medido suele ser mayor de lo esperado.
¿Cuáles son los errores más comunes?#
Port 8080 was already in use: otro proceso usa el puerto, o la plataforma espera otro. DefinePORTy confirma que el código lo lee.- La aplicación arranca, pero el sitio no abre: el servidor escucha en
localhost. En .NET, usa0.0.0.0enUseUrls. no main manifest attribute, in app.jar: el JAR no es ejecutable. Haz el build con elspring-boot-maven-plugin(obootJaren Gradle), no con el plugin de JAR por defecto.UnsupportedClassVersionError: el JAR se compiló con una versión de Java más nueva que la del runtime. Usa la misma versión en el build y en producción.The framework 'Microsoft.AspNetCore.App', version '10.0.0' (x64) was not found: el servidor no tiene el ASP.NET Core Runtime de esa versión, o tiene uno más antiguo que elTargetFrameworkdel proyecto.OutOfMemoryErroro proceso terminado por falta de RAM: la memoria asignada es menor que la necesaria. Aumenta la RAM de la aplicación antes de tocar flags de la JVM.
Antes de abrirla al público, revisa el checklist de producción de una API.
Cómo hacerlo en Square Cloud#
En Square Cloud el deploy es self-service: tú compilas, subes y controlas todo. Java y .NET están entre los diversos runtimes de la plataforma, junto a Node.js, Python y Go; compila el JAR con la misma versión de Java del runtime para no toparte con un UnsupportedClassVersionError. El deploy puede hacerse por ZIP en el panel, con la CLI, desde GitHub (un push dispara el deploy) o con la extensión de VS Code.
El archivo principal se define en el panel o en squarecloud.app, que guarda el nombre, el archivo principal, la memoria y la versión. El squarecloud.app es opcional: el panel lo genera en el deploy, y escribirlo en la raíz del proyecto es la alternativa. Las variables de entorno, como la cadena de conexión de la base de datos, se definen por aplicación, y el cambio se aplica en el siguiente reinicio, sin rebuild. La variable PORT la define la plataforma: la aplicación web escucha en 0.0.0.0 en ese puerto, como en los dos ejemplos. No hay paso de build en la plataforma, así que sube el JAR o la carpeta publicada, o compila en un CI externo.
La aplicación corre en un contenedor siempre encendido, sin modo de suspensión. Con el reinicio automático (activado por defecto en el deploy desde el panel), vuelve sola cuando el proceso termina con error. La RAM del plan es un pool compartido entre tus aplicaciones, con un mínimo de 512 MB para una aplicación web. Toda aplicación web recibe un subdominio *.squareweb.app con HTTPS, y el dominio personalizado está disponible desde el plan Standard.
Mira cómo hospedar APIs en la página de APIs, los runtimes en la página de runtimes y la API REST y los SDKs oficiales en SDKs.
Hosting de APIs
APIs en contenedores siempre encendidos, sin cold start
Preguntas frecuentes
¿Qué versión de Java usar para una API con Spring Boot?
Cada versión de Spring Boot exige una versión mínima de Java, indicada en la página de requisitos del sistema del proyecto. Para un proyecto nuevo, elige una LTS actual de Java y usa la misma versión en el build y en producción.
¿Qué versión de .NET usar en producción?
Usa la LTS actual de .NET, que tiene soporte durante más tiempo. Evita empezar un proyecto en una versión cerca del fin de su soporte: la política oficial de Microsoft indica las fechas de cada una.
¿Necesito Maven o el SDK de dotnet en el servidor?
No necesariamente. Puedes compilar en tu máquina o en el CI y enviar solo el JAR o la carpeta publicada. El servidor solo necesita el runtime (JRE o ASP.NET Core Runtime).
Mi API arranca pero no abre desde fuera. ¿Qué reviso?
Comprueba que escucha en 0.0.0.0 y no en localhost, y que el puerto es el que el servidor espera. Kestrel de ASP.NET Core escucha solo en localhost por defecto, y Spring Boot usa 8080 si no defines otro.
Más en APIs
Ver los 15 artículos- Cómo hospedar una APIHospedar una API es ejecutar su servidor HTTP las 24 horas en una dirección pública con HTTPS. Guía paso a paso con Node.js y Python, pruebas y errores comunes.
- Cómo hospedar una aplicación Node.jsPara hospedar una aplicación Node.js, prepara el package.json, lee el puerto y los secretos del entorno, elige una versión LTS y ejecútala con node. Paso a paso.
- Cómo hospedar FastAPI, Flask o DjangoPara hospedar FastAPI, Flask o Django, ejecuta la aplicación con un servidor de producción (Uvicorn o Gunicorn) en 0.0.0.0. Comandos, ajustes de Django y errores.
- Cómo hospedar una app o script de PythonPara hospedar una app o script de Python, fija la versión, aísla las dependencias en un venv, lee los secretos del entorno y maneja SIGTERM. Guía paso a paso.