01Qué vas a lograr
El camino completo: Dockerfile → contenedor → reverse-proxy con TLS → dominio → logs limitados → healthcheck. Al terminar, tu app está en vivo con HTTPS y dominio propio, y sabés exactamente qué parte es del servidor, del DNS y del contenedor.
02Deploy en un comando
El kit trae deploy.sh: build, run con restart automático y logs limitados, y healthcheck.
./deploy.sh mi-app 8080
La clave anti-403
nginx corre como usuario no-root; si los archivos vienen con permisos 600, da 403. Esto lo evita:
RUN chmod -R a+rX /usr/share/nginx/html
--log-opt max-size=10m --log-opt max-file=3.03Dominio + TLS automático
Apuntá un registro A de tu dominio a la IP del servidor (DNS-only si usás Cloudflare, para el challenge). Luego, el bloque de Caddy:
tu-dominio.com, www.tu-dominio.com {
encode gzip
reverse_proxy 127.0.0.1:8080
}
El certificado Let's Encrypt se emite solo al primer hit. Verificá en vivo, no contra el pipeline:
curl -s -o /dev/null -w "%{http_code}\n" https://tu-dominio.com/
04Errores clásicos
| Síntoma | Causa | Solución |
|---|---|---|
| 403 en todo | permisos 600 | chmod -R a+rX |
| Cert no emite | DNS / puerto 80 | A correcto + DNS-only + 80/443 |
| Disco al 100% | logs sin límite | --log-opt max-size + truncar |
| Contenedor en loop | la app crashea | docker logs <nombre> |
| Redeploy tumba prod | sin rollback | imagen anterior / git revert |
05Llevátelo
Kit completo: deploy.sh, Dockerfile.example, Caddyfile.snippet, .env.example y el checklist de producción.