Despliegue: servidores, Nginx, dominios y SSL
¿Qué es?
Desplegar es poner tu aplicación a correr en una máquina accesible desde internet, con un nombre legible (un dominio) y cifrado (SSL/HTTPS). Para lograrlo combinamos cuatro piezas: un servidor (una máquina virtual en la nube, lo que llaman VPS), un proxy inverso (Nginx, que recibe el tráfico de internet y lo pasa a tu contenedor), un dominio (que apunta a la IP del servidor) y un certificado SSL (que habilita el candado de HTTPS).
¿Cómo funciona?
Cuando alguien escribe https://mi-api.com en su navegador, ocurre esto en orden:
- El DNS traduce
mi-api.coma la IP de tu servidor. - La petición llega al servidor por el puerto 443 (HTTPS), donde escucha Nginx.
- Nginx termina el cifrado SSL y reenvía la petición a tu contenedor Docker, que escucha internamente en el puerto 8000.
- La API responde, Nginx vuelve a cifrar la respuesta y la devuelve al navegador.
Nginx actúa de portero: tu contenedor nunca queda expuesto directamente a internet. El certificado SSL lo emite gratis Let's Encrypt, y una herramienta llamada Certbot lo solicita y lo renueva automáticamente.
¿Para qué sirve?
Sirve para que tu herramienta deje de vivir solo en tu portátil y cualquiera pueda usarla, de forma segura y con una URL profesional. Es la culminación del despliegue: aquí toman forma todas las piezas anteriores. El servidor descarga la imagen que tu pipeline de CI/CD publicó, la corre con Docker Compose, y Nginx la expone con tu dominio y candado verde.
Pieza del despliegue que construye este módulo
Configuramos el servidor de producción completo: instalamos Docker, traemos la imagen del registro, la levantamos, ponemos Nginx como proxy inverso y emitimos el certificado SSL. Además, automatizamos el despliegue desde GitHub Actions vía SSH.
Paso 1: prepara el servidor (VPS Ubuntu)
# Conéctate por SSH (reemplaza con la IP de tu servidor)
ssh root@TU_IP_DEL_SERVIDOR
# Actualiza e instala Docker y Compose
apt update && apt upgrade -y
curl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin nginx certbot python3-certbot-nginx
# Crea un usuario sin privilegios para desplegar (no uses root para todo)
adduser deploy && usermod -aG docker deploy
Paso 2: trae y levanta la imagen
# Inicia sesión en el registro y descarga la imagen que publicó CI/CD
docker login ghcr.io -u TU_USUARIO
docker pull ghcr.io/tu-usuario/mi-api:latest
# docker-compose.prod.yml (en el servidor, carpeta /home/deploy/mi-api)
services:
api:
image: ghcr.io/tu-usuario/mi-api:latest
ports:
- "127.0.0.1:8000:8000" # solo accesible localmente; Nginx será la puerta
restart: unless-stopped
docker compose -f docker-compose.prod.yml up -d
Fíjate en 127.0.0.1:8000:8000. Sin ese 127.0.0.1, el puerto 8000 quedaría abierto a todo internet, saltándose Nginx y el SSL. Es un error de seguridad grave y muy común.
Paso 3: Nginx como proxy inverso
# /etc/nginx/sites-available/mi-api
server {
listen 80;
server_name mi-api.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
ln -s /etc/nginx/sites-available/mi-api /etc/nginx/sites-enabled/
nginx -t # verifica que la configuración no tenga errores
systemctl reload nginx
Paso 4: dominio y SSL
Primero, en el panel de tu proveedor de dominio, crea un registro A que apunte mi-api.com a la IP de tu servidor. Luego:
certbot --nginx -d mi-api.com # emite el certificado y reconfigura Nginx a HTTPS
Certbot edita tu configuración para redirigir HTTP a HTTPS y programa la renovación automática. Verifícala con certbot renew --dry-run.
Comprueba que la renovación automática quedó activa: systemctl status certbot.timer. Los certificados de Let's Encrypt duran 90 días; sin la renovación, tu sitio se caería al expirar.
Paso 5: despliegue automático desde CI/CD
Añade este job al final de tu cd.yml para que, tras publicar la imagen, el servidor la actualice solo:
desplegar:
needs: construir-y-publicar
runs-on: ubuntu-latest
steps:
- name: Desplegar por SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/deploy/mi-api
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
docker image prune -f
Tech English: reverse proxy = proxy inverso; VPS = servidor virtual privado; to provision = aprovisionar/preparar un servidor; DNS record = registro DNS; to issue a certificate = emitir un certificado.
Ejercicios
-
Despliegue end-to-end. Lleva la API a un VPS real (o uno local con IP), con Nginx y SSL, accesible en
https://tu-dominio. Documenta cada comando en unDESPLIEGUE.md. Se evalúa que la URL responda con candado válido y quecurl https://tu-dominio/saludodevuelva el JSON. -
Despliegue por push. Configura el job de despliegue por SSH con secretos. Haz un cambio trivial, súbelo a
mainy demuestra que el servidor sirve la nueva versión sin que tú entres por SSH manualmente. Se evalúa que el despliegue ocurra completamente automático tras el push.