# Publicar una app con servidor

> Node, PHP/Laravel, Python, Go, Ruby o tu propio Dockerfile. Cómo construye Dilohost tu app, qué necesita para arrancar, discos persistentes y cómo hacer que cada publicación tarde poco.

Una app es cualquier proyecto que necesita un proceso en marcha: una API, una tienda con base de datos, un panel, un bot. Dilohost detecta el lenguaje, instala las dependencias, construye la app en un entorno aislado y la pone en línea con HTTPS. Tú solo le pides a tu agente que la publique.

## Antes de empezar

- La app tiene que **escuchar en el puerto de la variable `PORT`** (vale 8080) y en `0.0.0.0`, no en `localhost`.
- Si usa base de datos, créala antes o después y conéctala: ver [Bases de datos](/docs/datos/bases-de-datos). Las bases de datos no están en el plan Gratis.
- El plan Gratis admite **1 app con servidor** y no usa Dockerfile. Los demás límites, en [Planes y precios](/docs/cuenta/planes).

## Publicarla

<p class="prompt">Publica esta API de Node en Dilohost, en el proyecto «reservas», como app «api».</p>

El agente sube el código por la vía que mejor le vaya (ver [Formas de subir el código](/docs/publicar/subir-codigo)), Dilohost empieza a construir y el agente consulta el estado (`deploy.status`) cada 30-60 segundos hasta que la versión está **en línea** o **falla**. Al terminar te da la dirección:

```text
https://api-reservas-a1b2c3d.dilosite.es
```

> [!TIP]
> Antes de publicar algo grande, el agente puede leer la guía de Dilohost (`deploy.guide`): explica cómo preparar el código para que el build tarde poco. Las instrucciones del servidor le piden hacerlo.

## Qué se construye y cómo

Dilohost mira la carpeta raíz del proyecto:

| Si encuentra… | Hace… |
|---|---|
| Un `Dockerfile` | Construye la app con tu Dockerfile. En el plan Gratis el Dockerfile se ignora y la app se construye como si no lo tuviera. |
| `composer.json` o `index.php` (PHP, Laravel) | Usa su propio entorno de PHP ya preparado: más rápido que un Dockerfile. Ver abajo. |
| `package.json`, `requirements.txt`, `pyproject.toml`, `Pipfile`, `go.mod`, `Gemfile`, `Cargo.toml`, `deno.json`… | Detecta el lenguaje, instala las dependencias con su lockfile y ejecuta el build y el arranque que declare el proyecto. |
| Solo un `index.html` | Es una [web estática](/docs/publicar/webs-estaticas): no se construye. |

### PHP y Laravel

Para PHP lo mejor es publicar **sin Dockerfile**. Dilohost trae:

- PHP 8.4, o 8.5 si tu `composer.json` lo pide;
- extensiones ya compiladas: `pdo_pgsql`, `pdo_mysql`, `pgsql`, `mysqli`, `intl`, `zip`, `bcmath`, `gd`, `exif`, `pcntl`, `redis`, `opcache` y `sockets`, además de las de serie (`mbstring`, `curl`, `xml`, `dom`, `fileinfo`, `tokenizer`…);
- Composer y Node 24 para compilar los assets (npm, pnpm o yarn según tu lockfile).

Instala las dependencias, compila los assets y sirve la app en el puerto correcto. En Laravel, cachea la configuración al arrancar. Las colas y el programador van aparte, con [tareas y workers](/docs/publicar/tareas), no con supervisor dentro de la app.

### Si tu repositorio trae un Dockerfile de otro hosting

Muchos proyectos traen un Dockerfile pensado para otro servicio. En lugar de borrarlo, pide que se ignore:

<p class="prompt">Publica la tienda sin usar su Dockerfile.</p>

El agente publica con `dockerfile=false`. Dilohost lo recuerda para las siguientes publicaciones de esa app, también para los `git push`. Para volver a usarlo, `dockerfile=true`.

## Lo que necesita tu app para arrancar

| Requisito | Detalle |
|---|---|
| Puerto | Escuchar en `0.0.0.0` y en el puerto de la variable `PORT` (8080). Si tu app no puede leerla, indica su puerto al publicar (`port`). |
| Configuración | Por variables de entorno. Ver [Variables y secretos](/docs/publicar/variables). |
| Ficheros | El disco de la app se reinicia en cada versión. Escribe solo en `/tmp` o en un [disco persistente](#discos-persistentes). Para fotos y documentos de tus usuarios, mejor un [almacén de ficheros](/docs/datos/almacenamiento). |
| Base de datos | Conexión por variables (`DATABASE_URL`, `DB_*`) con TLS ya configurado. Ver [Bases de datos](/docs/datos/bases-de-datos). |

Si la versión nueva no arranca, la anterior sigue en línea y el agente te explica el motivo (por ejemplo, que la app no responde en el puerto de `PORT`). Ver [Diagnóstico](/docs/publicar/diagnostico).

## Discos persistentes

Si tu app guarda ficheros que deben sobrevivir a cada publicación (una base SQLite, subidas de usuarios…), pide un disco persistente al publicar:

<p class="prompt">Publica la app con un disco persistente en /app/storage.</p>

El agente publica con `volume_path` y, si quieres, `volume_size_mb` (512 MB por defecto). Lo que se escribe en esa ruta se conserva entre versiones.

Para ampliarlo:

<p class="prompt">Amplía el disco de la app «web» de la tienda a 2 GB.</p>

El agente usa `app.disk`. Los discos solo se amplían, nunca se encogen, y llegan como mucho a 20 GB cada uno. Se amplía sin reiniciar la app y se cobra por lo que ocupa de verdad, no por el tamaño reservado. Para más espacio, un almacén de ficheros.

> [!NOTE]
> Una app con disco persistente se actualiza parándose y arrancando con la versión nueva, así que en cada publicación hay unos segundos sin servicio. Sin disco persistente, la versión nueva arranca antes de retirar la anterior y no hay corte.

## Cuánto tarda un build

Cada build corre en un entorno aislado y seguro, donde descargar dependencias y empaquetar va bien, pero **compilar desde el código fuente e instalar paquetes del sistema cuesta varias veces más** que en tu ordenador.

- El **primer build** de una app es el más lento: tiene que descargarlo todo. Puede tardar varios minutos.
- Los **siguientes** reutilizan lo que no cambió y suelen tardar entre unos segundos y pocos minutos.
- Si un build va a ser lento por algo que se puede evitar, el estado de la publicación lo dice en `para_que_tarde_menos`, y el agente te lo cuenta.

### Para que tarde poco

- **PHP/Laravel:** sin Dockerfile (o `dockerfile=false`).
- **Node, Python, Go, Ruby:** sin Dockerfile, con tu lockfile (`package-lock.json`, `pnpm-lock.yaml`, `poetry.lock`…) y un script de build y otro de arranque.
- **Si necesitas Dockerfile:** nada de `docker-php-ext-install`, `pecl`, `./configure`, `make` ni largas listas de `apt-get install`. Parte de imágenes base que ya traigan lo necesario.
- **Ordena las capas:** primero los ficheros de dependencias y su instalación, después el código. Así un cambio de código no lo reinstala todo.
- Añade un **`.dockerignore`** (`node_modules`, `vendor`, `.git`, pruebas) y usa varias etapas para que la imagen final no lleve lo que solo sirve para compilar.

## Memoria y procesador

Cada app tiene un máximo de memoria y de procesador que depende de tu plan. Pregúntale a tu agente:

<p class="prompt">¿Cuánta memoria y CPU puede usar la app web de la tienda?</p>

El agente lo consulta con `app.resources`. Lo que la app gasta de verdad se mide cada hora y se descuenta de tu [crédito de uso](/docs/conceptos#credito-de-uso).

## Problemas frecuentes

| Qué pasa | Qué hacer |
|---|---|
| «La app no llega a responder en el puerto 8080» | Haz que escuche en `0.0.0.0` y en el puerto de `PORT`. |
| El build tarda mucho | Mira `para_que_tarde_menos` en el estado de la publicación y sigue los consejos de arriba. |
| La app pierde ficheros al publicar | Usa un disco persistente o un almacén de ficheros. |
| La app no conecta con la base de datos | Conéctala con `database.connection` e `inject_into`. Ver [Bases de datos](/docs/datos/bases-de-datos). |

Más casos en [Diagnóstico](/docs/publicar/diagnostico) y [Solución de problemas](/docs/ayuda/problemas).

## Relacionado

- [Formas de subir el código](/docs/publicar/subir-codigo)
- [Variables y secretos](/docs/publicar/variables)
- [Workers y tareas programadas](/docs/publicar/tareas)
- [Versiones y vuelta atrás](/docs/publicar/versiones)
