Primeros pasos
Inicia sesión, sube tu primera aplicación y ponla en marcha.
1. Entra a tu panel
Tu instancia tiene su propia URL: https://panel-<tu-instancia>.urrahosting.cl.
Inicia sesión con el usuario y contraseña que te entregó el operador de tu
instancia (o los que definiste al desplegarla).
2. Prepara tu aplicación
Tu proyecto necesita, en la raíz, un Dockerfile que construya y arranque tu
aplicación escuchando en el puerto que la plataforma te asigna (variable de
entorno APP_PORT, ya inyectada automáticamente: no la definas tú mismo).
Antes de construir tu imagen, el panel valida el Dockerfile contra el
perfil de runtime de tu instancia:
- La imagen base de la etapa final debe coincidir con una de las permitidas para ese perfil (ver tabla abajo). En builds multi-stage, las etapas intermedias pueden usar otras imágenes; solo la etapa final se valida.
- Debes fijar un usuario no-root con
USERantes delCMD/ENTRYPOINTfinal (por ejemploUSER 10001:10001); el panel rechaza Dockerfiles que terminan corriendo comoroot. - No se permite
ADDcon URLs remotas niRUN --mount=type=ssh/type=secret.
| Perfil | Imágenes base permitidas |
|---|---|
| Python (WSGI/ASGI) | python:* |
| Node.js | node:* |
| Java (JRE) | eclipse-temurin:*, amazoncorretto:*, openjdk:* |
| C#/.NET (ASP.NET Core) | mcr.microsoft.com/dotnet/aspnet:*, mcr.microsoft.com/dotnet/runtime:* |
| PHP | php:* |
Ejemplo: Node.js
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
# Lee process.env.PORT o process.env.APP_PORT (se inyectan con el mismo
# valor) en tu server.js y escucha en ese puerto; la plataforma lo asigna,
# no lo fijes tú mismo.
USER 10001:10001
CMD ["node", "server.js"]
Ejemplo: Python (WSGI/ASGI)
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# APP_PORT lo inyecta la plataforma al iniciar el contenedor; la forma
# shell del CMD permite expandir $APP_PORT en tiempo de ejecución.
USER 10001:10001
CMD ["sh", "-c", "gunicorn --bind 0.0.0.0:$APP_PORT app:app"]
Ejemplo: Java (JRE)
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
COPY target/app.jar app.jar
USER 10001:10001
CMD ["sh", "-c", "java -jar app.jar --server.port=$APP_PORT"]
Ejemplo: C#/.NET (ASP.NET Core)
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY publish/ .
USER 10001:10001
CMD ["sh", "-c", "ASPNETCORE_URLS=http://+:$APP_PORT dotnet app.dll"]
Ejemplo: PHP (PHP-FPM + nginx)
El perfil PHP corre PHP-FPM detrás de nginx dentro del mismo contenedor.
A diferencia de los otros lenguajes, necesitas 4 archivos en tu repositorio:
el Dockerfile, una plantilla de configuración de nginx, el pool de
PHP-FPM y un script de arranque que levanta ambos procesos.
Estos archivos ya están pensados para las restricciones del contenedor
final: corre como usuario no-root desde el inicio (sin capacidad de hacer
setuid/setgid, así que nada intenta cambiar de usuario en tiempo de
ejecución), el sistema de archivos raíz es de solo lectura y solo /tmp es
escribible — por eso los logs van a /dev/stdout//dev/stderr y los
directorios temporales de nginx se crean bajo /tmp.
FROM php:8.3-fpm
RUN apt-get update \
&& apt-get install -y --no-install-recommends nginx \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
COPY nginx.conf.template /etc/nginx/nginx.conf.template
COPY www.conf /usr/local/etc/php-fpm.d/www.conf
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
USER 10001:10001
CMD ["/usr/local/bin/entrypoint.sh"]
nginx.conf.template (en la raíz de tu repo; __APP_PORT__ se reemplaza
por el puerto real al iniciar el contenedor):
worker_processes auto;
pid /tmp/nginx.pid;
error_log /dev/stderr warn;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /dev/stdout;
client_body_temp_path /tmp/nginx-client-body;
proxy_temp_path /tmp/nginx-proxy;
fastcgi_temp_path /tmp/nginx-fastcgi;
uwsgi_temp_path /tmp/nginx-uwsgi;
scgi_temp_path /tmp/nginx-scgi;
server {
listen __APP_PORT__;
root /app/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
}
www.conf (pool de PHP-FPM; sin las directivas user/group del pool por
defecto, porque el proceso ya arranca como no-root y no tiene permiso para
cambiar de usuario):
[www]
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
clear_env = no
catch_workers_output = yes
decorate_workers_output = no
entrypoint.sh (arranca PHP-FPM y nginx, y reenvía la señal de apagado a
ambos):
#!/bin/bash
mkdir -p /tmp/nginx-client-body /tmp/nginx-proxy /tmp/nginx-fastcgi /tmp/nginx-uwsgi /tmp/nginx-scgi
sed "s/__APP_PORT__/${APP_PORT}/" /etc/nginx/nginx.conf.template > /tmp/nginx.conf
php-fpm --nodaemonize &
FPM_PID=$!
nginx -c /tmp/nginx.conf -g "daemon off;" &
NGINX_PID=$!
# El contenedor recibe SIGQUIT al detenerse (heredado de la imagen base
# php:*-fpm) o SIGTERM/SIGINT; en los tres casos apagamos ambos procesos
# de forma ordenada antes de salir.
shutdown() {
kill -TERM "$NGINX_PID" "$FPM_PID" 2>/dev/null
wait "$NGINX_PID" 2>/dev/null
wait "$FPM_PID" 2>/dev/null
exit 0
}
trap shutdown TERM INT QUIT
wait -n "$NGINX_PID" "$FPM_PID"
shutdown
Recuerda dar permiso de ejecución al script en tu propio entorno antes de
subirlo (chmod +x entrypoint.sh) o, como en el Dockerfile de arriba,
dejar que el propio build lo haga con RUN chmod +x.
No incluyas un
docker-compose.ymlnicompose.ymlen tu proyecto: el panel lo rechaza automáticamente. Ver errores comunes.
3. Sube tu código o conecta un repositorio
En la pestaña Repositorio puedes:
- Conectar un repositorio Git (GitHub, GitLab o Bitbucket) y desplegar desde una rama específica.
- O subir un archivo comprimido con tu código directamente desde la pestaña Archivos.
4. Configura variables de entorno (opcional)
En la pestaña Entorno agrega las variables que tu aplicación necesite (claves de API, flags, etc.). Se guardan cifradas y se inyectan en el contenedor en el próximo despliegue.
5. Despliega
Dispara el build desde Repositorio o Software. El panel construye tu imagen, la levanta como candidato sin recibir tráfico todavía, espera a que pase el chequeo de salud y solo entonces la conecta a Traefik: si algo falla, tu versión anterior sigue sirviendo tráfico sin interrupción.
6. Verifica que quedó arriba
En Resumen verás el estado (en línea / fuera de línea), la salud del contenedor y el tiempo encendido. Si algo no arranca, revisa Consola para ver la salida de tu aplicación.
Siguiente paso: Despliegue en detalle.