Cómo desplegar tus propias aplicaciones en una VPS usando Docker y Traefik
Esta guía muestra paso a paso cómo instalar y configurar un servidor web en una VPS desde cero. Así podrás ahorrar los costes de las herramientas de hosting tradicionales y obtener control total sobre tu entorno de despliegue.
Pasos para la instalación
- 1
Elección de la VPS y configuración base
Para montar toda la infraestructura necesitaba una base sólida, flexible y, sobre todo, con buena relación calidad‑precio. Después de comparar varias opciones, me decanté por Hetzner, un proveedor que destaca por ofrecer recursos potentes a un coste muy ajustado.
La VPS que elegí tiene la siguiente configuración:- 2 vCPU
- 4 GB de RAM
- 40 GB de disco local
Puede parecer una configuración modesta, pero es más que suficiente para el objetivo que tenía en mente: ejecutar varias aplicaciones web y APIs de forma simultánea utilizando contenedores Docker.
¿Por qué Hetzner?- Excelente relación calidad‑precio
- Buen rendimiento de CPU y disco
- Centros de datos en Europa con baja latencia
- Panel de control sencillo y eficaz
- Ideal para proyectos personales, side projects y entornos productivos pequeños/medianos
¿Por qué esta configuración es suficiente?Gracias al uso de Docker y Docker Compose, cada aplicación se ejecuta en su propio contenedor, lo que permite:
- Aislar servicios
- Optimizar el uso de recursos
- Escalar o añadir nuevas aplicaciones fácilmente
Además, con Traefik como reverse proxy, puedo exponer múltiples aplicaciones y APIs bajo diferentes dominios o subdominios sin necesidad de aumentar la complejidad del servidor.
- 2
Acceso a tu VPS mediante SSH
Antes de empezar a desplegar contenedores y servicios, es fundamental preparar correctamente el servidor. Una buena base evita problemas de seguridad, rendimiento y mantenimiento en el futuro.
Sistema operativoEn mi caso opté por Ubuntu Server LTS, una elección bastante común en servidores por varios motivos:
- Estabilidad y soporte a largo plazo
- Gran comunidad
- Excelente compatibilidad con Docker y herramientas modernas
Nada más crear la VPS, lo primero fue acceder por SSH como usuario root para realizar la configuración inicial.
Actualización del sistemaEl primer paso siempre es asegurarse de que el sistema está completamente actualizado:
apt update && apt upgrade -yCon esto nos aseguramos de tener los últimos parches de seguridad y versiones estables de los paquetes instalados.
Creación de un usuario no rootPor seguridad, es buena práctica no trabajar directamente con el usuario root. Así que creé un usuario nuevo y le asigné permisos de sudo:
adduser deployConfiguración de acceso SSHPara mejorar la seguridad del servidor, realicé varios ajustes en el acceso SSH:
- Acceso mediante clave pública/privada
- Desactivar el login directo de root
- Opcionalmente puedes cambiar el puerto SSH para mayor seguridad
Después de cualquier cambio, es necesario reiniciar el servicio:
systemctl restart sshFirewall (UFW)Para limitar el acceso únicamente a los servicios necesarios, configuré el firewall con UFW (Uncomplicated Firewall).
Primero permití los puertos básicos:
ufw allow OpenSSHY después activé el firewall:
ufw enableCon esto el servidor solo acepta tráfico por SSH y por los puertos HTTP/HTTPS, que más adelante usará Traefik.
Estado final del servidor- Actualizado y seguro
- Sin acceso root por SSH
- Protegido por firewall
- Listo para instalar Docker y empezar a desplegar aplicaciones
- 3
Instalación de Docker y Docker Compose
Con el servidor ya preparado y asegurado, el siguiente paso es instalar Docker y Docker Compose, que serán la base para ejecutar todas las aplicaciones y servicios de forma aislada y ordenada.
Instalación de DockerAunque Ubuntu incluye Docker en sus repositorios, preferí instalarlo desde el repositorio oficial de Docker para asegurarme de tener una versión más actualizada y estable.
1. Instalar paquetes necesarios:
2. Añadir la clave GPG oficial de Docker:apt install -y ca-certificates curl gnupg
3. Configurar el repositorio:install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg
4. Instalar Docker Engine:echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null
5. Comprobar la instalación:apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugindocker --version docker compose versionEjecutar Docker sin sudoPara evitar tener que usar sudo en cada comando de Docker, añadí mi usuario al grupo docker:
usermod -aG docker deployTras cerrar sesión y volver a entrar, ya es posible ejecutar Docker directamente con el usuario normal.
Instalación de Docker ComposeEn este caso utilicé Docker Compose V2, que viene integrado como plugin oficial de Docker. Esto permite usar el comando:
docker composesin necesidad de instalar binarios adicionales ni depender de versiones antiguas.
Verificación finalPara validar que todo estaba correctamente instalado, lancé un contenedor de prueba:
docker run hello-worldSi todo va bien, Docker descarga la imagen y muestra un mensaje de confirmación.
Base lista para Traefik y las aplicaciones- Ejecutar múltiples aplicaciones web
- Levantar APIs independientes
- Gestionar redes internas entre contenedores
- Integrar un reverse proxy como Traefik
- 4
Configuración de Traefik como reverse proxy
Con Docker funcionando correctamente, el siguiente paso clave es introducir Traefik como reverse proxy. Traefik se convierte en el punto único de entrada a todas las aplicaciones web y APIs que se ejecutan en el servidor.
Su gran ventaja frente a otras soluciones es que está pensado para entornos con contenedores, detectando automáticamente los servicios a través de Docker.
¿Por qué Traefik?Elegí Traefik principalmente por:
- Integración nativa con Docker
- Configuración dinámica basada en labels
- Soporte automático de HTTPS con Let’s Encrypt
- Gestión sencilla de múltiples dominios y subdominios
- Dashboard para monitorizar el estado del proxy
Red Docker compartidaAntes de levantar Traefik, creé una red Docker externa que será compartida por Traefik y todas las aplicaciones que quiera exponer públicamente:
docker network create traefikEsta red permite que Traefik enrute tráfico hacia contenedores definidos en distintos docker-compose.
Docker Compose de TraefikTraefik se ejecuta como un contenedor más, normalmente en su propio stack. Un docker-compose.yml simplificado sería:
services: traefik: image: traefik:v3.0 container_name: traefik restart: unless-stopped command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--api.dashboard=true" ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro networks: - traefik networks: traefik: external: trueCon esta configuración básica, Traefik ya es capaz de detectar contenedores Docker y enrutar tráfico HTTP y HTTPS.
Providers: Docker como fuente de verdadTraefik utiliza providers para descubrir servicios. En este caso, el provider principal es Docker:
- Traefik escucha los eventos de Docker
- Detecta contenedores con labels específicas
- Crea rutas dinámicamente sin reinicios
Esto elimina la necesidad de editar archivos de configuración cada vez que se añade una nueva aplicación.
Preparación para HTTPS automáticoTraefik permite gestionar certificados SSL automáticamente usando Let’s Encrypt. Para ello, solo es necesario:
- Definir un resolver ACME
- Configurar un email de contacto
- Persistir los certificados en un volumen
Esto permite que, al levantar una nueva aplicación con su dominio, Traefik genere y renueve automáticamente los certificados sin intervención manual.
- 5
Exponer una aplicación real con Traefik
Una vez Traefik está funcionando como reverse proxy, el siguiente paso es ponerlo a trabajar de verdad: exponer una aplicación web real utilizando Docker Compose y las labels de Traefik.
En este punto es donde todo empieza a encajar y se aprecia la potencia de esta arquitectura.
Estructura básica del proyectoCada aplicación vive en su propio directorio y tiene su propio docker-compose.yml. Por ejemplo:
/var/www/└── mi-app-web/└── docker-compose.ymlEsto permite desplegar, actualizar o eliminar aplicaciones de forma totalmente independiente.
Docker Compose de una aplicación webSupongamos una aplicación web sencilla (por ejemplo una API o un frontend). El docker-compose.yml podría ser algo como esto:
services: app: image: nginx:alpine container_name: mi_app_web restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.miapp.rule=Host(`miapp.midominio.com`)" - "traefik.http.routers.miapp.entrypoints=websecure" - "traefik.http.routers.miapp.tls.certresolver=letsencrypt" networks: - traefik networks: traefik: external: trueCon solo estas labels, Traefik:
- Detecta automáticamente el contenedor
- Asocia el dominio indicado
- Expone la aplicación por HTTPS
- Genera y renueva el certificado SSL
Labels: la clave de todoLas labels son el corazón de la configuración con Traefik. En ellas se define:
- Qué contenedores se exponen (traefik.enable=true)
- Qué dominio o regla de acceso se utiliza
- Por qué entrypoint entra el tráfico
- Qué resolver de certificados usar
Todo esto se hace sin tocar Traefik, simplemente declarando comportamiento desde la propia aplicación.
Despliegue de la aplicaciónLevantar la aplicación es tan simple como ejecutar:
docker compose up -dEn cuestión de segundos:
- Traefik detecta el nuevo servicio
- Se crea el router dinámicamente
- Let’s Encrypt emite el certificado
- La aplicación queda accesible públicamente
Escalabilidad y mantenimientoEste enfoque permite:
- Añadir nuevas aplicaciones sin modificar las existentes
- Usar distintos dominios y subdominios
- Reiniciar o actualizar servicios de forma aislada
- Mantener una arquitectura limpia y ordenada
Cada nuevo proyecto sigue exactamente el mismo patrón, lo que simplifica enormemente el mantenimiento a largo plazo.
- 6
Buenas prácticas y errores comunes
Después de montar la infraestructura y desplegar varias aplicaciones, hay una serie de buenas prácticas que marcan la diferencia entre un sistema que simplemente funciona y uno que es mantenible, seguro y escalable en el tiempo.
Buenas prácticasSeparar responsabilidades- Traefik debe vivir en su propio stack
- Cada aplicación debe tener su propio docker-compose.yml
- Evitar mezclar bases de datos, proxies y aplicaciones en el mismo stack
Esto facilita actualizaciones, reinicios y depuración.
Usar redes Docker externasCentralizar la exposición pública a través de una red externa (como traefik) permite:
- Mantener aisladas las redes internas
- Reducir la superficie de ataque
- Controlar exactamente qué servicios son accesibles desde fuera
No exponer contenedores innecesariosPor defecto, Traefik no expone ningún contenedor (exposedbydefault=false). Solo aquellos servicios que realmente necesitan acceso público deben llevar labels de Traefik.
Versionar los docker-composeGuardar los docker-compose.yml en un repositorio (Git) permite:
- Reproducir el entorno fácilmente
- Tener histórico de cambios
- Desplegar el servidor desde cero en minutos
Persistencia de datos- Bases de datos siempre con volúmenes
- Certificados de Traefik persistidos
Evitar perder información al recrear contenedores.
Errores comunesEjecutar todo como rootAunque Docker lo permita, no es buena idea trabajar siempre como root. Usar un usuario dedicado reduce riesgos y errores accidentales.
Exponer el dashboard sin protecciónEl dashboard de Traefik es muy útil, pero no debe quedar expuesto públicamente sin autenticación o restricciones de red.
No controlar logsSin una mínima estrategia de logs:
- Los errores pasan desapercibidos
- Es difícil depurar problemas
- Se pierde visibilidad del sistema
Al menos conviene revisar periódicamente los logs de Traefik y de las aplicaciones.
No planificar el crecimientoAunque la VPS sea suficiente al inicio, es importante:
- Vigilar consumo de CPU y RAM
- Saber cuándo escalar verticalmente
- Optimizar imágenes y servicios
- 7
Uso real en producción
Toda esta infraestructura no es solo un experimento o un laboratorio. La propia web que estás leyendo ahora mismo está desplegada exactamente de esta forma:
- Astro en el frontend
- .NET en el backend
- Contenedores Docker independientes
- Traefik gestionando dominios y certificados HTTPS
Cada parte vive en su propio stack, pero todas conviven en la misma VPS de forma ordenada, segura y eficiente.
Ventajas clave del enfoqueDespués de usar esta arquitectura de forma continuada, las principales ventajas son claras:
- Despliegues rápidos y reproducibles
- Aislamiento total entre aplicaciones
- Configuración mínima para nuevos proyectos
- HTTPS automático sin complicaciones
- Escalabilidad clara cuando sea necesaria
Conclusión finalMontar un servidor web moderno hoy en día no requiere infraestructuras complejas ni grandes inversiones. Con una VPS bien elegida, Docker, Traefik y una buena organización, es posible construir una plataforma sólida, flexible y preparada para crecer.
Esta arquitectura me permite centrarme en lo importante: desarrollar aplicaciones, sabiendo que la base sobre la que corren es estable, mantenible y fácil de evolucionar.
Si estás pensando en montar tu propio servidor para alojar varias aplicaciones y APIs, este enfoque es una opción más que recomendable.
Si te quedan dudas o quieres compartir tu experiencia, no dudes en dejar un comentario o contactarme directamente. ¡Feliz despliegue!