Cómo hospedar una API Java o .NET

Para hospedar una API Java o .NET, compila un JAR o una carpeta publicada con DLL y súbela a un servidor con el runtime. La API debe escuchar en 0.0.0.0, en el puerto definido por el entorno.

Actualizado el 6 min de lectura

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

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.

Java (Spring Boot)Maven/Gradle./mvnw packageapp.jarfat JAR.NET (ASP.NET Core)dotnet publish-c Release -o outout/MiApi.dllservidorRuntimeJRE oASP.NET Corelee PORT0.0.0.0:PORTacepta conexionesde fuera
Sube solo el artefacto compilado; en el servidor, el runtime lee PORT y la API escucha en 0.0.0.0, no en localhost.

¿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:

java
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:

properties
server.port=${PORT:8080}
  • server.port=${PORT:8080}: lee la variable PORT y usa 8080 cuando no existe. La documentación de Spring Boot también acepta SERVER_PORT directamente 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:

bash
./mvnw -DskipTests package
PORT=9090 java -jar target/demo-0.0.1-SNAPSHOT.jar
curl http://localhost:9090/health

El 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:

bash
dotnet new web -n MiApi
cd MiApi
csharp
var 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:

bash
dotnet publish -c Release -o out
PORT=9090 dotnet out/MiApi.dll
curl http://localhost:9090/health

Lo 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ó?#

  1. 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.
  2. Endpoint de salud: curl -i https://tu-dominio/health debe devolver 200 y {"status":"ok"}.
  3. Reinicio: reinicia la aplicación y confirma que vuelve sola y que los logs no muestran peticiones cortadas a la mitad.
  4. 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. Define PORT y confirma que el código lo lee.
  • La aplicación arranca, pero el sitio no abre: el servidor escucha en localhost. En .NET, usa 0.0.0.0 en UseUrls.
  • no main manifest attribute, in app.jar: el JAR no es ejecutable. Haz el build con el spring-boot-maven-plugin (o bootJar en 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 el TargetFramework del proyecto.
  • OutOfMemoryError o 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

Más información

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.

Siguiente artículoCómo hospedar un servidor WebSocket: conexiones largas, proxy y escaladoPara hospedar un servidor WebSocket, mantén el proceso siempre activo, pasa el Upgrade por el proxy, envía pings y planifica qué pasa con varias instancias.