bolt Valebyte VPS desde $4/mes — NVMe, despliegue en 60s.

Obtener VPS arrow_forward
eco Principiante Tutorial/Cómo hacer

Dokploy en VPS: tu propio Vercel/Heroku para desplegar desde GitHub

calendar_month Sep 15, 2026 schedule 26 min de lectura visibility 32 vistas
Dokploy на VPS: свой Vercel/Heroku для деплоя из GitHub
info

¿Necesitas un servidor para esta guía? Ofrecemos servidores dedicados y VPS en más de 50 países con configuración instantánea.

¿Necesitas un VPS para esta guía?

Explore otras opciones de servidores dedicados en

Dokploy en VPS: tu propio Vercel/Heroku para desplegar desde GitHub

Resumen

Dokploy convierte un VPS común en tu propia plataforma de despliegue: conectas un repositorio de GitHub, configuras el dominio y las variables de entorno, y luego obtienes compilación automática, HTTPS y publicación de la aplicación después de cada push en la rama seleccionada.

  • Para proyectos pequeños basta con un VPS con 2 vCPU, 4 GB de RAM y un disco NVMe de 50–80 GB.
  • Dokploy se instala sobre Docker y Docker Swarm mediante un único comando oficial.
  • Para un funcionamiento estable se necesitan registros DNS para el panel y para cada aplicación publicada.
  • GitHub se puede conectar mediante GitHub App, webhook o una clave SSH para repositorios privados.
  • HTTPS normalmente lo proporciona el Traefik integrado mediante Let’s Encrypt; no hace falta instalar Caddy junto a Dokploy y puede generar conflictos en los puertos 80 y 443.
  • Es necesario hacer copias de seguridad no solo del código, sino también de la configuración de Dokploy, los Docker volumes, las bases de datos y los secretos.

Qué configuramos y por qué

Dokploy es un panel PaaS self-hosted para desplegar aplicaciones en tu propio servidor. Por su enfoque recuerda a Vercel, Heroku, Railway, Render o Coolify: el desarrollador no se conecta al servidor mediante SSH después de cada cambio, sino que hace push en GitHub. La plataforma obtiene el código, compila el contenedor, lo ejecuta, conecta el dominio y redirige el tráfico mediante HTTPS.

En esta guía se configurará un VPS con Dokploy, un nombre de dominio para el panel, la integración con GitHub y la primera aplicación. Como ejemplo se utiliza una aplicación típica de Node.js, aunque el principio es el mismo para Python, Go, PHP, Ruby, Next.js, NestJS, Django, FastAPI, Laravel, sitios estáticos y proyectos con Docker Compose.

Qué obtendrás como resultado

Después de la configuración tendrás un servidor donde podrás crear proyectos y servicios mediante la interfaz web de Dokploy. Cada servicio podrá compilarse desde un repositorio de GitHub, ejecutarse en un contenedor Docker y recibir environment variables, dominios, certificados TLS y registros. Para proyectos independientes se pueden iniciar PostgreSQL, Redis, MySQL, MongoDB o un stack de Docker Compose junto a la aplicación.

  • El panel de Dokploy estará disponible, por ejemplo, en https://deploy.example.com.
  • La aplicación se publicará automáticamente después de hacer push en la rama main.
  • Los secretos se almacenarán en la configuración del servicio y no en el repositorio.
  • El tráfico de los puertos 80 y 443 será gestionado por el reverse proxy integrado de Dokploy.
  • El despliegue se podrá revertir mediante el historial de despliegues o ejecutando de nuevo un commit anterior.
  • Los datos y la configuración se enviarán periódicamente a un almacenamiento externo de copias de seguridad.

Cómo funciona el despliegue

Dokploy utiliza Docker como entorno de ejecución y Docker Swarm como orquestador incluso en un solo servidor. Durante el despliegue, la plataforma obtiene el código fuente desde GitHub y después actúa de una de estas dos formas: compila una imagen según tu Dockerfile o aplica una compilación automática mediante Nixpacks. Tras una compilación correcta, el contenedor se conecta a la red interna y Traefik dirige las solicitudes hacia él según el nombre de dominio.

Para proyectos de producción es preferible guardar un Dockerfile propio en el repositorio. Esto hace que la compilación sea reproducible: la misma imagen se puede ejecutar localmente, en un servidor de staging y en production. El builder automático resulta práctico para prototipos, pero cuando hay bibliotecas de sistema no estándar, un monorepositorio, workers en segundo plano o una compilación compleja, un Dockerfile explícito es más fácil de mantener.

Plataforma self-hosted o managed

Criterio Managed PaaS Dokploy en VPS
Configuración inicial Mínima Hay que preparar el servidor, el DNS y las copias de seguridad
Control de la infraestructura Limitado por el plan y las reglas de la plataforma Control total sobre Docker, la red, los registros y los datos
Coste Aumenta con el número de servicios, el tráfico y las bases de datos Coste fijo del VPS hasta agotar los recursos
Acceso al servidor A menudo no existe o es limitado Hay acceso root y posibilidad de realizar diagnósticos
Actualizaciones y seguridad Responsabilidad principalmente del proveedor Responsabilidad del propietario del servidor
Escenario adecuado Puesta en marcha rápida sin administración Varios servicios, control de los datos y presupuesto predecible

Dokploy self-hosted resulta especialmente útil para un fundador en solitario, un equipo pequeño o una agencia que mantiene varias aplicaciones. Un solo servidor puede alojar el panel, la API, el frontend, un worker, PostgreSQL, Redis y varios entornos de staging. Al mismo tiempo, es importante no confundir la comodidad de un PaaS con la ausencia de operaciones: el servidor debe seguir actualizándose, monitorizándose y respaldándose.

Dokploy no sustituye la arquitectura de la aplicación. Si un VPS deja de funcionar, todos los servicios alojados en él estarán indisponibles. Para la primera etapa de production esto suele ser aceptable, pero la base de datos y la configuración deben contar con copias de seguridad externas desde el primer día.

Qué configuración de VPS se necesita para esta tarea

Dokploy por sí solo no requiere muchos recursos, pero en el servidor funcionan simultáneamente Docker, Docker Swarm, el reverse proxy, los compiladores de imágenes, los contenedores temporales y tus aplicaciones. El principal error al elegir un VPS es tener en cuenta únicamente la memoria de la propia aplicación y olvidar la compilación de imágenes Docker, la caché, la base de datos, los registros y el sistema de archivos.

Configuración mínima y recomendada

Escenario CPU RAM Disco NVMe Red Qué puede alojar
Entorno de pruebas 1 vCPU 2 GB 30–40 GB 100 Mbit/s El panel y una aplicación ligera sin una base de datos pesada
Production mínima 2 vCPU 4 GB 50–80 GB 100 Mbit/s o 1 Gbit/s El panel, 2–5 servicios pequeños, PostgreSQL o Redis
Varios servicios SaaS 4 vCPU 8 GB 160 GB NVMe 1 Gbit/s Varias aplicaciones, workers, staging y bases de datos
Compilación intensiva 8 vCPU 16 GB 300+ GB NVMe 1 Gbit/s Monorepositorios, SSR, compilaciones CI/CD frecuentes y varios entornos

Para el primer servidor de trabajo, un buen punto de partida son 2 vCPU, 4 GB de RAM, 80 GB de NVMe y una dirección IPv4 pública. Esta configuración es suficiente para Dokploy, un par de servicios de Node.js o Python, PostgreSQL con una carga moderada y Redis. Si la base de datos escribe datos activamente, el disco es más importante que el número nominal de núcleos: elige NVMe en lugar de un HDD lento.

Como opción neutral puedes contratar un VPS con las características indicadas y después aumentar la CPU, la RAM o el disco cuando aparezca una carga real. Antes de contratarlo, comprueba que el servidor tenga una IPv4 pública dedicada, acceso mediante SSH, posibilidad de configurar reverse DNS si es necesario y un límite suficiente de tráfico saliente.

Cuánto espacio se necesita realmente

Las imágenes Docker y la build cache consumen espacio en disco de forma casi imperceptible. Por ejemplo, una aplicación que ocupa 300 MB puede dejar entre 2 y 5 GB de capas antiguas, imágenes intermedias y caché después de varias actualizaciones. PostgreSQL, los archivos subidos por los usuarios, los registros y las copias de seguridad aumentan aún más la necesidad de espacio.

No llenes el disco del sistema por encima del 75–80 %. Cuando Docker o PostgreSQL no pueden escribir datos debido a que el disco está lleno, la aplicación puede empezar a devolver errores y la recuperación tardará más que una migración normal a un plan más grande. Como mínimo una vez por semana, comprueba df -h y docker system df.

Cuándo se necesita un dedicated en lugar de un VPS

Un VPS es adecuado para casi todos los primeros proyectos SaaS, paneles internos, landing pages, API y una base pequeña de clientes. Un servidor dedicated se vuelve conveniente cuando el rendimiento de las máquinas virtuales vecinas resulta inaceptable, se necesita una matriz NVMe local grande, existe una carga de CPU elevada y constante o la base de datos realiza un gran número de operaciones de escritura.

  • Necesitas un dedicated si PostgreSQL utiliza constantemente más de 8–12 vCPU o requiere cientos de gigabytes de datos rápidos.
  • Necesitas un dedicated si compilas imágenes Docker grandes decenas de veces al día y las compilaciones interfieren con el tráfico de production.
  • Necesitas un dedicated si en un mismo nodo funcionan decenas de clientes con una carga elevada.
  • Necesitas un dedicated si se requieren configuraciones RAID específicas, discos locales de respaldo o IOPS garantizados.
  • El VPS sigue siendo la mejor opción si es más importante la simplicidad del escalado y todavía no conoces el perfil real de carga.

Cómo elegir la ubicación

La ubicación del servidor influye en la latencia, los requisitos de almacenamiento de datos y el precio del tráfico. Si la audiencia se encuentra en Europa, un servidor en un centro de datos europeo normalmente ofrecerá una latencia de 20–80 ms. Para usuarios de una misma región, elige la ubicación más cercana, pero no guardes la única copia de seguridad en el mismo centro de datos: un incendio, un error de la cuenta o un incidente de red no deben destruir production y su copia al mismo tiempo.

Si la aplicación procesa datos personales, ten en cuenta los requisitos legales del país, los contratos con los clientes y las normas sobre transferencias transfronterizas de datos. En la parte técnica también son importantes la disponibilidad de IPv6, la protección contra DDoS, la velocidad del puerto y la posibilidad de ampliar el disco sin reinstalar el sistema operativo.

Preparación del servidor

Esquema: Preparación del servidor
Esquema: Preparación del servidor

A continuación se presupone un VPS nuevo con Ubuntu Server 24.04 LTS x86_64. En 2026, es una base estable y conveniente, con paquetes compatibles, un kernel actualizado y un largo periodo de actualizaciones de seguridad. Los comandos se ejecutan como root solo durante la primera conexión; posteriormente se utiliza un usuario independiente deploy con privilegios sudo.

Conéctese y actualice el sistema

Primero inicie sesión en el servidor mediante la dirección IP proporcionada por el proveedor. Si utiliza la contraseña de root, sustitúyala por una clave SSH antes de abrir el panel de Dokploy.

ssh root@SERVER_IP

El comando crea una sesión SSH con el servidor nuevo.

apt update && apt upgrade -y && apt autoremove -y

El comando instala todas las actualizaciones de seguridad disponibles y elimina las dependencias innecesarias.

timedatectl set-timezone Europe/Moscow

El comando establece la zona horaria; indique su región para que los registros, las tareas cron y la hora de despliegue sean comprensibles.

Cree un usuario para la administración

No trabaje constantemente como root. Un usuario independiente reduce el riesgo de eliminar accidentalmente archivos del sistema o ejecutar un comando peligroso de las instrucciones. Dokploy y Docker seguirán ejecutando contenedores con privilegios elevados a nivel del host, por lo que el acceso a sudo y Docker debe concederse únicamente a los administradores.

adduser deploy
usermod -aG sudo deploy

Los comandos crean el usuario deploy y lo añaden al grupo sudo.

mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
nano /home/deploy/.ssh/authorized_keys

Los comandos crean el directorio para las claves SSH. Pegue en el archivo la clave pública de su ordenador, normalmente el contenido del archivo ~/.ssh/id_ed25519.pub.

chown -R deploy:deploy /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

Los comandos asignan el propietario y permisos de acceso seguros a la clave.

No cierre la sesión actual de root hasta comprobar el nuevo acceso en una ventana independiente del terminal.

ssh deploy@SERVER_IP

El comando comprueba que el inicio de sesión con el nuevo usuario mediante la clave funciona correctamente.

Desactive el acceso mediante contraseña y root SSH

Después de comprobar que funciona correctamente, modifique la configuración de SSH. No realice este paso antes de añadir una clave funcional; de lo contrario, podría perder el acceso al servidor y tendría que utilizar VNC o rescue mode del proveedor.

sudo nano /etc/ssh/sshd_config.d/99-hardening.conf

El comando abre un archivo de configuración independiente de SSH sin modificar el archivo estándar del paquete.

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3

Estos parámetros prohíben el acceso de root y la autenticación mediante contraseña, dejando únicamente las claves SSH.

sudo sshd -t && sudo systemctl restart ssh

El comando comprueba primero la sintaxis de la configuración y después reinicia SSH solo si no hay errores.

Instale las utilidades básicas y la protección contra ataques de fuerza bruta

sudo apt install -y ca-certificates curl gnupg git jq unzip vim htop \
  ufw fail2ban dnsutils rsync cron

El comando instala utilidades para descargar paquetes, trabajar con Git, realizar comprobaciones DNS, crear copias de seguridad, supervisar el sistema y gestionar el firewall.

sudo systemctl enable --now fail2ban

El comando activa Fail2ban, que supervisa los intentos de inicio de sesión sospechosos y bloquea temporalmente las direcciones IP.

Configure el firewall antes de instalar Dokploy

Dokploy debe aceptar tráfico web en los puertos 80 y 443. El puerto 22 es necesario para SSH. Inicialmente, el panel suele estar disponible en el puerto 3000, por lo que durante el primer acceso puede abrirlo únicamente para su IP pública. Si la IP cambia, abra temporalmente el puerto 3000 para todos, cree la cuenta y después cierre el puerto una vez configurados el dominio y HTTPS.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from YOUR_PUBLIC_IP to any port 3000 proto tcp
sudo ufw enable

Los comandos deniegan por defecto todo el tráfico entrante y solo abren SSH, HTTP, HTTPS y el acceso al panel desde su IP.

sudo ufw status numbered

El comando muestra las reglas activas y permite comprobar que el firewall no haya bloqueado los puertos necesarios.

Para un solo nodo, Docker Swarm normalmente no requiere abrir al exterior los puertos de comunicación entre nodos. Si posteriormente añade nodos worker, entre los nodos de confianza serán necesarios TCP 2377, TCP/UDP 7946 y UDP 4789. No los abra a todo internet: limite las reglas a las direcciones IP del clúster o a la red privada.

Prepare el DNS antes de la instalación

Cree un registro DNS de tipo A para el panel, por ejemplo deploy.example.com, que apunte a la IPv4 del servidor. Para las aplicaciones puede crear registros A independientes, por ejemplo api.example.com y app.example.com. Si el proveedor de DNS admite wildcard, resulta práctico crear el registro .apps.example.com, aunque no es obligatorio para el primer inicio.

dig +short deploy.example.com A

El comando comprueba que el nombre de dominio ya devuelve la IP pública de su VPS.

No active el proxy de CDN antes de emitir el primer certificado si no comprende sus modos TLS. HTTPS se rompe con especial frecuencia cuando la CDN se conecta al origin mediante HTTP. Primero obtenga un certificado funcional directamente a través de Dokploy y, si es necesario, active después el proxy externo en el modo de cifrado completo.

Instalación del software — paso a paso

Esquema: Instalación del software — paso a paso
Esquema: Instalación del software — paso a paso

El instalador oficial de Dokploy despliega los componentes necesarios de Docker, inicializa Docker Swarm y pone en marcha los servicios del panel. En la práctica, Dokploy evoluciona rápidamente, por lo que antes de una instalación en producción conviene leer la salida del script y registrar la fecha de instalación en el registro de cambios. No ejecute comandos curl no verificados como root en un servidor que ya tenga servicios críticos en funcionamiento.

Compruebe los recursos y la ausencia de conflictos

free -h
df -h /
nproc
sudo ss -ltnp | grep -E ':(80|443|3000)\s' || true

Los comandos muestran la cantidad de memoria, el espacio libre, el número de CPU y los procesos que ya ocupan los puertos 80, 443 o 3000.

Si en el servidor ya funcionan Nginx, Apache, Caddy, Traefik u otra Docker PaaS, no instale Dokploy encima sin un plan de migración. El ingress integrado de Dokploy debe poder escuchar en los puertos 80 y 443. El conflicto de puertos es una de las causas más frecuentes de inaccesibilidad del panel y las aplicaciones.

Instale Dokploy con el script oficial

curl -sSL https://dokploy.com/install.sh -o /tmp/dokploy-install.sh
less /tmp/dokploy-install.sh

Los comandos descargan el install script oficial en un archivo temporal y permiten revisarlo antes de ejecutarlo.

sudo sh /tmp/dokploy-install.sh

El comando ejecuta el instalador oficial de Dokploy, que instala los componentes de Docker y despliega la plataforma.

En un Ubuntu nuevo, el instalador suele completar el despliegue en unos minutos. No reinicie el VPS durante la instalación ni interrumpa el proceso. Si el sistema informa de un conflicto con los paquetes de Docker, elimine primero las instalaciones de prueba antiguas de Docker, Docker Compose o el reverse proxy en conflicto, después de guardar previamente los datos necesarios.

Compruebe Docker y Docker Swarm

sudo docker version
sudo docker info --format '{{.ServerVersion}}'
sudo docker node ls

Los comandos confirman el funcionamiento de Docker Engine, muestran la versión del daemon y comprueban que el servidor actual sea un nodo manager activo de Swarm.

En 2026, utilice una versión actual y compatible de Docker Engine procedente del canal oficial de instalación y una versión stable actual de Dokploy. No utilice instrucciones obsoletas que propongan Docker Engine 20.x o archivos compose antiguos sin comprobarlos: pueden entrar en conflicto con los paquetes modernos de Ubuntu y los requisitos de Dokploy.

sudo docker service ls
sudo docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'

Los comandos muestran los servicios de Docker Swarm y los contenedores de Dokploy en ejecución.

Abra el panel por primera vez

Después de la instalación, abra en el navegador http://SERVER_IP:3000 o http://deploy.example.com:3000 si el DNS ya se ha actualizado. En el primer acceso, cree un administrador con una contraseña larga y única. Para la contraseña, utilice un gestor de contraseñas, no un secreto almacenado en un repositorio o un chat.

Si el puerto 3000 está abierto únicamente para su IP mediante UFW y el navegador no se conecta, compruebe primero su IP pública actual. Las VPN corporativas, el internet móvil y los proveedores domésticos pueden cambiarla durante el día.

curl -I http://127.0.0.1:3000

El comando comprueba la disponibilidad local del panel en el servidor; una respuesta 200, 301, 302 o 401 normalmente significa que el servicio responde.

Realice la primera captura técnica del estado

sudo mkdir -p /root/server-inventory
sudo docker service ls > /root/server-inventory/docker-services-initial.txt
sudo docker volume ls > /root/server-inventory/docker-volumes-initial.txt
sudo docker network ls > /root/server-inventory/docker-networks-initial.txt

Los comandos guardan la lista inicial de servicios, volumes y redes de Docker, lo que ayuda en el diagnóstico y la configuración de las copias de seguridad.

Añada el usuario al grupo Docker solo si es necesario

Para la mayoría de las operaciones de Dokploy no se necesita acceso a Docker desde una consola normal: utilice sudo docker. Si aun así añade el usuario deploy al grupo docker, recuerde que esto equivale prácticamente al acceso root: mediante Docker se puede montar el sistema de archivos del host o ejecutar un contenedor privilegiado.

sudo usermod -aG docker deploy

El comando concede al usuario deploy acceso a Docker sin sudo; salga de SSH y vuelva a conectarse para que el grupo se aplique.

Compruebe el inicio automático después del reinicio

sudo reboot

El comando reinicia el servidor y comprueba que Docker, Swarm y los servicios de Dokploy se inicien correctamente después del reinicio.

Después de volver a iniciar sesión, espere uno o dos minutos y realice la comprobación.

sudo systemctl is-active docker
sudo docker service ls
curl -I http://127.0.0.1:3000

Los comandos confirman que Docker está activo, que los servicios de Swarm están en ejecución y que el panel responde localmente.

Configuración de Dokploy, GitHub y HTTPS

Después de la instalación básica, no se apresure a desplegar código de producción. Primero establezca la dirección del panel, compruebe el DNS, configure HTTPS y decida de qué manera Dokploy leerá los repositorios de GitHub. Para un repositorio público basta con una HTTPS clone URL, pero para uno privado se necesita una GitHub App, un token personal con permisos mínimos o una deploy key.

Configure el dominio del panel y HTTPS

En la interfaz de Dokploy, abra la configuración general del panel e indique el dominio, por ejemplo deploy.example.com. Asegúrese de que el registro A ya apunta a la IP del VPS y de que los puertos 80 y 443 están accesibles desde el exterior. Después, active TLS automático mediante Traefik y Let’s Encrypt integrados.

Dokploy utiliza Traefik integrado para el reverse proxy y los certificados. Por eso, no instale Caddy, Nginx ni certbot en modo standalone en el mismo servidor sin una necesidad explícita: todas estas herramientas pretenden utilizar los puertos 80 y 443. Para Dokploy, el procedimiento correcto es activar el TLS integrado en la configuración del dominio del servicio; Traefik realizará el HTTP-01 challenge y renovará automáticamente el certificado.

Si utiliza un DNS corporativo, el puerto 80 está cerrado o tiene un esquema CDN complejo, use DNS challenge solo después de comprender la integración con la DNS API. En una configuración normal, es más sencillo abrir 80/443 y permitir que Let’s Encrypt verifique el dominio directamente. Puede comprobar el HTTPS público después de emitir el certificado.

curl -I https://deploy.example.com
openssl s_client -connect deploy.example.com:443 -servername deploy.example.com < /dev/null 2>/dev/null | \
  openssl x509 -noout -issuer -dates -subject

Los comandos comprueban la respuesta HTTP del panel y muestran el emisor, el período de validez y el nombre del certificado TLS.

Conecte GitHub de forma segura

Para un equipo, lo más práctico es una GitHub App: permite que Dokploy acceda únicamente a los repositorios seleccionados y reciba eventos push. Cree una GitHub App en la configuración de la organización o de la cuenta personal, indique la URL callback y la webhook URL que muestra la interfaz de Dokploy, y conceda los permisos mínimos necesarios para leer el contenido del repositorio y los metadata.

Si todavía no necesita una GitHub App, utilice una deploy key para un único repositorio privado. Es una clave SSH sin permisos para toda la cuenta, que puede revocarse por separado. No utilice la clave SSH personal del administrador del servidor como clave para GitHub.

Genere una clave independiente en el servidor o en un entorno administrativo aislado:

sudo -u deploy ssh-keygen -t ed25519 -C "dokploy-github-readonly" \
  -f /home/deploy/.ssh/dokploy_github_ed25519 -N ""

El comando crea un par independiente de claves Ed25519 sin passphrase para una deploy key de solo lectura.

sudo cat /home/deploy/.ssh/dokploy_github_ed25519.pub

El comando muestra la parte pública de la clave, que debe añadirse en GitHub, en la sección Deploy keys del repositorio correspondiente.

En GitHub, abra Repository Settings → Deploy keys → Add deploy key, pegue la clave pública y no active Allow write access si la aplicación no necesita escribir en el repositorio. En Dokploy, añada la SSH private key mediante la interfaz del proyecto o utilice GitHub App. No copie la clave privada en el Dockerfile, el código fuente ni variables que puedan ver los usuarios de la aplicación.

Prepare la aplicación para el despliegue en contenedor

A continuación se muestra un ejemplo mínimo de un servicio Node.js. Estructura del repositorio:

my-service/
├── Dockerfile
├── .dockerignore
├── package.json
├── package-lock.json
└── src/
    └── server.js

El archivo Dockerfile debe declarar explícitamente el directorio de trabajo, las dependencias de producción, el puerto y el healthcheck. No incluya en la imagen el archivo .env, las claves SSH, los directorios node_modules ni los artefactos de compilación locales.

FROM node:22-alpine

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci --omit=dev

COPY src ./src

ENV NODE_ENV=production
ENV PORT=3000

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD node -e "fetch('http://127.0.0.1:3000/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"

CMD ["node", "src/server.js"]

Este Dockerfile crea una imagen de producción basada en Node.js 22 LTS, abre el puerto 3000 y comprueba el endpoint /health.

node_modules
.git
.env
.env.
npm-debug.log
coverage
dist
Dockerfile
docker-compose.yml

Este es un ejemplo del contenido de .dockerignore; excluye los archivos innecesarios y sensibles del Docker build context.

import http from "node:http";

const port = Number(process.env.PORT || 3000);
const appName = process.env.APP_NAME || "my-service";

const server = http.createServer((req, res) => {
  if (req.url === "/health") {
    res.writeHead(200, { "Content-Type": "application/json" });
    return res.end(JSON.stringify({ status: "ok" }));
  }

  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify({ service: appName, environment: process.env.NODE_ENV }));
});

server.listen(port, "0.0.0.0", () => {
  console.log(${appName} listens on ${port});
});

Este es un servidor mínimo con el endpoint /health, que puede utilizarse para comprobar la disponibilidad del contenedor.

Cree un servicio en la interfaz de Dokploy

  1. Cree un nuevo Project, por ejemplo production o my-saas.
  2. Añada Application dentro del proyecto.
  3. Seleccione GitHub como fuente e indique el repositorio.
  4. Indique la rama main o una rama independiente production.
  5. Seleccione el build type Dockerfile si el Dockerfile se encuentra en la raíz del repositorio.
  6. Indique el puerto interno de la aplicación 3000.
  7. Añada el dominio, por ejemplo api.example.com.
  8. Active HTTPS y la obtención automática del certificado.
  9. Guarde la configuración y haga clic en Deploy.

En Dokploy, el puerto interno es el puerto en el que escucha la aplicación dentro del contenedor. No es necesario abrirlo en UFW: el tráfico externo debe pasar por Traefik en 80/443. Si abre directamente el puerto del contenedor hacia el exterior, evita TLS, el enrutamiento y parte de los mecanismos de protección de la plataforma.

Transmita los secretos mediante environment variables

En la configuración de la aplicación, busque el bloque Environment Variables y añada las variables una por una. En producción, no almacene claves reales en el archivo .env dentro del repositorio de GitHub. Para el desarrollo local, se permite utilizar un archivo .env.example sin valores secretos.

NODE_ENV=production
APP_NAME=my-production-api
DATABASE_URL=postgresql://app_user:CHANGE_ME@postgres:5432/app_db
REDIS_URL=redis://redis:6379
JWT_SECRET=replace-with-a-random-64-character-secret
SENTRY_DSN=https://[email protected]/1

Este es un ejemplo de variables de entorno para un servicio de producción. Los valores de DATABASE_URL, JWT_SECRET y las API keys deben ser únicos y no deben incluirse en Git.

openssl rand -base64 48

El comando genera una cadena aleatoria adecuada para el secreto de sesiones, JWT o una clave interna de la aplicación.

Después de modificar las environment variables, normalmente se requiere un Redeploy, ya que el contenedor recibe las variables al iniciarse. Para las bases de datos, cree un usuario independiente para cada aplicación en lugar de utilizar el superusuario de PostgreSQL. Esto reduce el daño en caso de filtración de un connection string.

Configure el autodespliegue desde GitHub

El autodespliegue se inicia mediante un webhook después de un push. En Dokploy, active el deployment automático para la rama necesaria. Al utilizar GitHub App, el webhook normalmente se crea mediante la integración. Si realiza la configuración manualmente, añada el webhook en GitHub, en la sección Settings → Webhooks, indique la URL que muestra Dokploy, seleccione el evento push y establezca el webhook secret.

El webhook secret debe coincidir en GitHub y Dokploy. Protege el endpoint frente a solicitudes arbitrarias que podrían iniciar un despliegue. No utilice el mismo secreto para todos los repositorios.

Para realizar una prueba, haga un commit inocuo:

git checkout main
git pull --ff-only
git commit --allow-empty -m "chore: test Dokploy deployment"
git push origin main

Los comandos crean un commit vacío y lo envían a la rama para comprobar el webhook y la compilación automática sin modificar el código fuente.

Abra el historial de deployments en Dokploy. Una ejecución correcta debe pasar por las etapas clone, build, deploy y healthcheck. Si la compilación es correcta, pero el dominio devuelve 502, casi siempre el problema se debe a un puerto interno incorrecto, a una aplicación que solo escucha en 127.0.0.1 o a una dependencia, como PostgreSQL, que aún no está lista.

Compruebe la aplicación desde el exterior y desde el contenedor

curl -i https://api.example.com/health

El comando comprueba que el dominio público de la aplicación responde mediante HTTPS y devuelve el estado 200.

sudo docker service ls
sudo docker service ps --no-trunc SERVICE_NAME
sudo docker service logs --tail 100 SERVICE_NAME

Los comandos muestran el estado del servicio, el motivo detallado de un inicio fallido de la tarea y las últimas 100 líneas de los registros.

Obtenga el nombre SERVICE_NAME de la salida de docker service ls. En Docker Swarm, el nombre real puede contener el prefijo del proyecto. No elimine servicios con el comando docker service rm si Dokploy los administra: el panel perderá el estado esperado. Para una aplicación administrada, utilice Redeploy, Stop, Restart o Delete mediante la interfaz.

Copias de seguridad y mantenimiento

GitHub almacena el código, pero no los datos de la aplicación, los Docker volumes, los archivos cargados por los usuarios, la configuración de Dokploy ni los secretos. Por lo tanto, el repositorio no puede considerarse una copia de seguridad de production. La estrategia mínima consiste en una copia de seguridad automática diaria en un almacenamiento externo compatible con S3 o un VPS independiente, y verificaciones periódicas de restauración.

Qué se debe respaldar

Datos Por qué son necesarios Método de copia
Configuración de Dokploy Proyectos, ajustes, dominios, integraciones y metadatos Archivo de los directorios de configuración tras verificar su ubicación
PostgreSQL/MySQL Datos principales de las aplicaciones Dump lógico mediante pg_dump o mysqldump
Docker volumes Uploads, persistent data, Redis persistence y datos de servicios Archivado después de detenerlos o snapshot a nivel de disco
Environment variables y secretos Sin ellos no es posible restaurar rápidamente el servicio Password manager cifrado o documento offline protegido
Configuración del sistema SSH, UFW, cron, notas de DNS, configuración de monitoreo Archivo de /etc y repositorio de infraestructura sin secretos

Antes de escribir el script, localice los Docker volumes y contenedores reales en su servidor. Los nombres dependen de la versión de Dokploy, los nombres de los proyectos y el método de creación de la base de datos. No suponga que el volume necesariamente se llama postgres_data.

sudo docker volume ls
sudo docker ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Mounts}}'
sudo find /etc -maxdepth 2 -iname 'dokploy' -print

Los comandos muestran los volumes, los montajes de contenedores y los posibles directorios de configuración de Dokploy.

Instale Restic para copias de seguridad externas

Restic cifra los archivos en el servidor antes de enviarlos al almacenamiento remoto. Puede utilizar un bucket compatible con S3, Backblaze B2 mediante una API compatible, almacenamiento independiente o un segundo VPS con SFTP. No guarde la única copia en el mismo disco donde se ejecutan Docker y la base de datos.

sudo apt install -y restic

El comando instala Restic desde el repositorio de Ubuntu.

sudo install -m 700 -d /root/.config/restic
sudo nano /root/.config/restic/dokploy-backup.env

Los comandos crean un directorio protegido y abren el archivo con los parámetros de acceso al almacenamiento externo S3.

export RESTIC_REPOSITORY="s3:https://s3.example-storage.invalid/dokploy-prod"
export RESTIC_PASSWORD="CHANGE_TO_A_LONG_UNIQUE_RESTIC_PASSWORD"
export AWS_ACCESS_KEY_ID="S3_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="S3_SECRET_KEY"

Este es un ejemplo del archivo /root/.config/restic/dokploy-backup.env; reemplace los valores por los reales y limite los permisos de acceso.

sudo chmod 600 /root/.config/restic/dokploy-backup.env
sudo bash -c 'source /root/.config/restic/dokploy-backup.env && restic snapshots || restic init'

Los comandos impiden el acceso al archivo a otros usuarios y muestran los snapshots existentes o inicializan un nuevo repositorio cifrado.

Cree un script de copia de seguridad diaria

El siguiente script crea un dump lógico de PostgreSQL desde el contenedor, archiva las configuraciones del sistema y las envía a Restic. Reemplace POSTGRES_CONTAINER, POSTGRES_USER y POSTGRES_DB por los valores reales. Para una base de datos creada con Dokploy, puede consultarlos en la configuración del servicio y mediante docker ps.

sudo nano /usr/local/sbin/backup-dokploy.sh

El comando crea el archivo del script de copia de seguridad.

#!/usr/bin/env bash
set -euo pipefail

source /root/.config/restic/dokploy-backup.env

BACKUP_DIR="/var/backups/dokploy"
STAMP="$(date +%F_%H-%M-%S)"
POSTGRES_CONTAINER="POSTGRES_CONTAINER"
POSTGRES_USER="POSTGRES_USER"
POSTGRES_DB="POSTGRES_DB"

mkdir -p "${BACKUP_DIR}/postgres"

docker exec "${POSTGRES_CONTAINER}" \
  pg_dump -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -Fc \
  > "${BACKUP_DIR}/postgres/${POSTGRES_DB}_${STAMP}.dump"

tar -czf "${BACKUP_DIR}/system_${STAMP}.tar.gz" \
  /etc/ssh \
  /etc/ufw \
  /etc/fail2ban \
  /etc/crontab \
  /root/server-inventory 2>/dev/null || true

restic backup "${BACKUP_DIR}" /etc/dokploy \
  --tag dokploy \
  --tag "$(hostname)"

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

find "${BACKUP_DIR}" -type f -mtime +3 -delete

El script crea un dump de PostgreSQL, archiva configuraciones importantes del sistema, envía los datos a Restic, aplica la política de retención y elimina los archivos temporales locales antiguos.

Si el directorio /etc/dokploy no existe en su instalación, elimínelo del comando restic backup y agregue la ruta real encontrada en el servidor. Antes de automatizar, ejecute el script manualmente y verifique que haya finalizado sin errores.

sudo chmod 700 /usr/local/sbin/backup-dokploy.sh
sudo /usr/local/sbin/backup-dokploy.sh
sudo bash -c 'source /root/.config/restic/dokploy-backup.env && restic snapshots'

Los comandos asignan permisos seguros, ejecutan la primera copia de seguridad y muestran los snapshots creados.

Añada una programación cron

sudo crontab -e

El comando abre el root-crontab para ejecutar la copia de seguridad según una programación.

20 3   * /usr/local/sbin/backup-dokploy.sh >> /var/log/dokploy-backup.log 2>&1

Esta tarea cron ejecuta la copia de seguridad todos los días a las 03:20 y guarda la salida en un log.

Para una base de datos de production, un dump lógico es preferible a una simple copia del archivo volume mientras PostgreSQL está funcionando. Una copia de archivos de una base de datos activa puede ser inconsistente. Para bases de datos grandes, considere replicación, archivado WAL, snapshot a nivel de storage o una base de datos administrada independiente del VPS con Dokploy.

Verifique la restauración, no solo la existencia de la copia de seguridad

Una vez al mes, restaure al menos un dump de PostgreSQL en una base de datos de prueba en un servidor independiente o en un contenedor aislado. Una copia de seguridad sin verificar la restauración es solo una esperanza. Asegúrese también de que la contraseña de Restic no se guarde únicamente en el archivo del servidor de production: guárdela en un password manager o en un kit de emergencia protegido.

source /root/.config/restic/dokploy-backup.env
restic restore latest --target /tmp/dokploy-restore-test
find /tmp/dokploy-restore-test -maxdepth 3 -type f | head

Los comandos restauran el último snapshot en un directorio temporal y muestran los primeros archivos restaurados.

Actualizaciones de Dokploy, Docker y el sistema

Las actualizaciones son de dos tipos. Los cambios pequeños en las aplicaciones normalmente pueden desplegarse mediante rolling deployment con Dokploy: se inicia la nueva versión, pasa el healthcheck y luego se cambia el tráfico. Es mejor realizar la actualización de la propia plataforma, Docker Engine, el kernel de Ubuntu y el esquema de la base de datos en una maintenance window, cuando existe una copia de seguridad reciente y la posibilidad de verificar los servicios después de reiniciar.

  1. Verifique el estado de los servicios y el espacio libre en disco.
  2. Realice una copia de seguridad no programada y asegúrese de que el snapshot aparezca en el almacenamiento remoto.
  3. Lea las release notes de Dokploy y Docker en busca de breaking changes.
  4. Si es posible, actualice primero el servidor de staging.
  5. Actualice Dokploy mediante el método estándar previsto por la versión actual del panel.
  6. Verifique el panel, un dominio crítico, los logs y el estado de Swarm.
sudo apt update
apt list --upgradable
sudo docker service ls
sudo docker system df

Los comandos muestran las actualizaciones disponibles del sistema operativo, el estado de los servicios y el uso de disco de Docker antes de iniciar los trabajos.

No ejecute regularmente docker system prune -a --volumes mediante cron sin comprender las consecuencias. Este comando puede eliminar volumes no utilizados, build cache e imágenes que pueden ser necesarias para un rollback rápido. Es más seguro utilizar primero docker system df, eliminar imágenes antiguas que claramente no sean necesarias y conservar varias de las últimas versiones funcionales de los servicios críticos.

Solución de problemas + FAQ

¿Por qué el panel de Dokploy no se abre en el puerto 3000?

Primero verifique que Docker esté activo: sudo systemctl status docker. Luego ejecute sudo docker service ls y curl -I http://127.0.0.1:3000. Si el curl local funciona pero el navegador no se conecta, el problema casi con certeza está en UFW, el firewall externo del proveedor o una restricción de acceso al puerto 3000 según su IP. Verifique sudo ufw status numbered y asegúrese de conectarse desde una dirección permitida. Después de trasladar el panel a un dominio HTTPS, es mejor cerrar el puerto externo 3000.

¿Por qué Let’s Encrypt no emite un certificado para el dominio?

Verifique el DNS con el comando dig +short your-domain.example A: debe devolver la IP de este VPS. Luego asegúrese de que los puertos 80 y 443 sean accesibles desde el exterior y de que otro Nginx, Apache o Caddy no esté escuchando en ellos. El error suele producirse por un CDN-proxy activado, un registro AAAA de IPv6 incorrecto o un cambio reciente de DNS que aún no se ha propagado. Consulte los logs de Traefik y los logs de deployment en Dokploy. No solicite el certificado decenas de veces seguidas: Let’s Encrypt tiene límites de intentos.

El deployment finalizó correctamente, pero el dominio devuelve 502 Bad Gateway. ¿Qué hacer?

El error 502 significa que el reverse proxy no puede obtener una respuesta correcta de la aplicación. Verifique el puerto interno en la configuración de Dokploy: debe coincidir con el puerto que escucha el proceso dentro del contenedor. La aplicación debe escuchar en 0.0.0.0, no solo en 127.0.0.1. Consulte sudo docker service logs --tail 100 SERVICE_NAME; con frecuencia el proceso finalizó por una variable DATABASE_URL ausente, una migración de base de datos o un error de conexión a Redis.

¿Por qué Dokploy no puede clonar un repositorio privado de GitHub?

Verifique el método de autenticación: GitHub App debe estar instalada específicamente para el repositorio requerido, y la deploy key debe añadirse a la configuración del repository concreto. Con autenticación SSH, compare la private key en Dokploy con la public key en GitHub. No active write access si el servicio solo lee el código. Asegúrese también de que la clone URL corresponda al método elegido: la SSH URL comienza con [email protected]:, mientras que la HTTPS URL requiere un token o GitHub App.

La compilación de Docker falla con el error “no space left on device”. ¿Cómo solucionarlo?

Primero consulte el espacio libre: df -h y sudo docker system df. Luego encuentre los directorios grandes mediante sudo du -xh /var/lib/docker | sort -h | tail. Elimine únicamente imágenes no utilizadas y caché que comprenda, no los volumes de las bases de datos en funcionamiento. Optimice el Dockerfile: use multi-stage build, .dockerignore, no copie node_modules y no guarde artefactos grandes en las capas. Si queda menos de 15–20 GB de espacio libre, aumente el disco antes del próximo deployment.

¿Qué configuración de VPS es mínimamente adecuada?

Para un proyecto de laboratorio puede comenzar con 1 vCPU, 2 GB de RAM y 30–40 GB de disco, pero al compilar imágenes de Node.js, Next.js o Python, la memoria se agotará rápidamente. El mínimo práctico para production es 2 vCPU, 4 GB de RAM y 50–80 GB NVMe. Esto permite ejecutar Dokploy, un reverse proxy, una o dos aplicaciones y una base de datos pequeña. Si el servidor tiene PostgreSQL y varios servicios, elija 4 vCPU y 8 GB de RAM para que las compilaciones no afecten a la disponibilidad de los usuarios.

¿Qué elegir: VPS o dedicated para esta tarea?

Para Dokploy y la mayoría de las aplicaciones pequeñas de production, elija VPS: es más fácil de escalar, cuesta menos al principio y normalmente proporciona recursos suficientes. Dedicated tiene sentido con una carga de CPU alta y constante, una base PostgreSQL grande, requisitos de IOPS garantizados, decenas de servicios en compilación activa o la necesidad de cientos de gigabytes de datos rápidos. No cambie a dedicated solo por un único fallo puntual de compilación: primero mida la CPU, RAM, disk I/O y la carga real.

¿Se pueden ejecutar PostgreSQL y Dokploy en el mismo VPS?

Sí, para la etapa inicial es un esquema normal y habitual. Cree obligatoriamente un persistent volume, configure dumps lógicos periódicos y no permita que la base de datos ocupe todo el disco. Vigile la memoria: PostgreSQL, Docker build y una aplicación SSR pueden requerir simultáneamente varios gigabytes de RAM. Cuando la base de datos se vuelva crítica para el negocio o aumente la carga, trasládela a un VPS independiente, PostgreSQL administrado o una réplica con copias de seguridad independientes. La aplicación se conectará mediante una red privada o una dirección pública protegida.

¿Cómo limpiar Docker de forma segura después de muchos deployments?

Comience con el diagnóstico: sudo docker system df -v mostrará qué ocupa espacio. Elimine las imágenes dangling antiguas y el build cache innecesario manualmente o mediante las herramientas estándar de Dokploy, si están disponibles en su versión. Antes de limpiar, cree una copia de seguridad y no elimine volumes hasta saber a qué aplicación pertenecen. El comando docker system prune -a --volumes es agresivo y puede eliminar datos de un servicio detenido, pero todavía necesario. En production, ejecútelo primero solo sin la opción --volumes y analice la lista de eliminación.

Conclusiones y siguientes pasos

Esquema: Conclusiones y siguientes pasos
Esquema: Conclusiones y siguientes pasos

Ahora el VPS funciona como una plataforma de despliegue propia: Dokploy obtiene el código de GitHub, crea los contenedores, publica las aplicaciones en los dominios y gestiona HTTPS. Con una configuración correcta del firewall, los secretos y las copias de seguridad, este stack es adecuado para pequeños servicios de producción y varios proyectos de equipo.

  1. Cree un proyecto de staging independiente y vincúlelo a la rama develop para comprobar las migraciones y las compilaciones antes de pasar a production.
  2. Añada una monitorización externa del endpoint HTTP /health, notificaciones sobre indisponibilidad y control del espacio libre en el disco.
  3. A medida que crezca, traslade la base de datos, el object storage o los workers a nodos independientes y, después, añada un segundo nodo de Dokploy solo tras diseñar la red y la estrategia de tolerancia a fallos.

La principal recomendación práctica es automatizar no solo el despliegue, sino también la recuperación. Las pruebas periódicas de restore, las actualizaciones durante una maintenance window y la medición del consumo real de recursos proporcionan más fiabilidad que simplemente aumentar el tamaño del VPS.

¿Te fue útil esta guía?

Tus comentarios nos ayudan a mejorar nuestras guías.

Compartir esta publicación:

Envía esta guía a alguien a quien pueda resultarle útil.

Telegram VKVK WhatsApp Facebook LinkedIn XX

dokploy en VPS: tu propio Vercel/Heroku para desplegar desde GitHub
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.