---
title: "Cómo Dejé que mi Asistente de IA Desplegara Apps Docker con un Solo Mensaje"
description: "Cómo crear una skill docker-deploy para tu asistente de IA para que pueda instalar y configurar apps Docker en tu VPS usando Caddy y Docker Compose, todo desde un…"
date: 2026-02-09
categories: ["ai"]
tags: ["docker","self-hosted","ai-tools"]
---

import YouTubeEmbed from "@components/widgets/YouTubeEmbed.astro";
import Button from "@components/widgets/Button.astro";
import Notice from "@components/widgets/Notice.astro";
import ListCheck from "@components/widgets/ListCheck.astro";
import Accordion from "@components/widgets/Accordion.astro";
import Tabs from "@components/widgets/Tabs.astro";
import Tab from "@components/widgets/Tab.astro";

Me cansé de conectarme por SSH a mi VPS cada vez que quería probar una nueva app Docker. Instalar esto, escribir un archivo compose, añadir la configuración de Caddy, reiniciar, comprobar si funciona. Los mismos pasos una y otra vez.

Así que construí una skill para mi asistente de IA. Ahora abro Telegram (o Discord, o Slack) y escribo algo como «instala Plausible Analytics en mi servidor». El asistente crea la carpeta, escribe el archivo compose, actualiza Caddy para HTTPS, lo arranca todo y comprueba si la app responde. No toco la terminal en absoluto.

Este artículo recorre la configuración que hace que esto funcione y te da el archivo de skill que puedes usar en tu propio asistente de IA.

<YouTubeEmbed
  url="https://www.youtube.com/embed/ty836MWWSak"
  label="IA 24/7 Despliega CUALQUIER App Docker Mientras Duermes"
/>


## Qué necesitas antes de empezar

Esta configuración tiene cinco piezas que deben estar listas antes de que la skill haga algo útil:

<ListCheck>
<ul>
<li>Un VPS (yo uso [Hetzner CX22](https://go.bitdoze.com/hetzner) por unos $4.50/mes)</li>
<li>Docker y Docker Compose instalados en el VPS</li>
<li>Caddy ejecutándose como contenedor Docker para proxy inverso y HTTPS automático</li>
<li>Un registro DNS wildcard que apunte `*.tudominio.com` a la IP de tu servidor</li>
<li>Una estructura de directorios para tus stacks Docker (como `/home/user/docker-apps`)</li>
</ul>
</ListCheck>

_Los precios de los VPS subieron en todos los proveedores en 2026 — si estás replanteándote un servidor alquilado, mira [qué cambió y cuándo gana un mini PC](/es/subidas-precios-vps/)._

Si ya tienes las cinco, salta directamente al archivo de skill. Si no, cubriré cada una.

<Button link="https://go.bitdoze.com/hetzner" text="Hetzner VPS" />
<Button link="https://go.bitdoze.com/hostinger-vps" text="Hostinger VPS" />
<Button link="https://go.bitdoze.com/do" text="DigitalOcean $100 Gratis" />
<Button link="https://go.bitdoze.com/vultr" text="Vultr $100 Gratis" />

## El VPS

Cualquier VPS Linux sirve. Llevo años usando Hetzner porque es barato y la red es sólida. Un CX22 con 2 vCPUs y 4 GB de RAM maneja Caddy más una docena de apps Docker sin problemas. Ubuntu 24.04 es mi opción habitual.

Si eres nuevo en el hosting VPS, la [reseña de Hetzner Cloud](https://www.bitdoze.com/es/hetzner-cloud-resena/) cubre lo que obtienes y cómo configurar uno. O usa un [mini PC como servidor doméstico](https://www.bitdoze.com/best-mini-pc-home-server/) si prefieres mantener todo en local.

## Instalar Docker

Si aún no tienes Docker en tu servidor:

```sh
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
```

Guía completa: [Instalar Docker y Docker Compose en Ubuntu](https://www.bitdoze.com/install-docker-ubuntu-arm/).

## Configurar Caddy como proxy inverso

Caddy gestiona HTTPS automáticamente. Sin certbot, sin crons de renovación, sin archivos de configuración de nginx. Obtiene los certificados de Let's Encrypt por sí solo y los renueva antes de que caduquen.

Yo ejecuto Caddy como contenedor Docker dentro de la misma estructura de directorios donde viven todas mis apps.

### Crear la estructura de directorios

```sh
mkdir -p /home/$USER/docker-apps/caddy
cd /home/$USER/docker-apps/caddy
```

### Docker Compose para Caddy

Crea un `docker-compose.yml` en el directorio de Caddy:

```yaml
services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./data:/data
      - ./config:/config
    networks:
      - caddy

networks:
  caddy:
    external: true
```

### Crear la red Docker

Todas tus apps se conectarán a esta red compartida para que Caddy pueda alcanzarlas:

```sh
sudo docker network create caddy
```

### Crear el Caddyfile

Crea un `Caddyfile` en la misma carpeta. Empieza con un marcador de posición:

```
# Apps will be added here by the AI assistant or manually
```

### Arrancar Caddy

```sh
cd /home/$USER/docker-apps/caddy
sudo docker compose up -d
```

Caddy está en marcha. Cualquier app que añadas después solo necesita una entrada en este Caddyfile y una conexión a la red `caddy`.

## Configurar el DNS wildcard

Necesitas un registro DNS que envíe todos los subdominios a tu servidor. En tu registrador de dominios o proveedor de DNS (Cloudflare, etc.), añade un registro A:

| Tipo | Nombre | Valor | TTL |
|------|------|-------|-----|
| A | `*` | `IP_DE_TU_SERVIDOR` | Auto |

Si tu dominio es `example.com`, esto significa que `anything.example.com` resolverá a tu VPS. Caddy se encarga luego de enrutar cada subdominio al contenedor correcto.

<Notice type="info" title="Usuarios de Cloudflare">
Si usas Cloudflare, puedes activar el proxy en el registro wildcard (nube naranja), pero tendrás que configurar Caddy para que funcione con el modo SSL de Cloudflare. La configuración más sencilla es usar «Solo DNS» (nube gris) y dejar que Caddy gestione los certificados directamente.
</Notice>

## La convención de directorios

Cada app tiene su propia carpeta dentro de `/home/$USER/docker-apps/`. La estructura queda así después de unas cuantas apps:

```
/home/user/docker-apps/
  caddy/
    docker-compose.yml
    Caddyfile
    data/
    config/
  plausible/
    docker-compose.yml
    .env
  arcane/
    docker-compose.yml
    .env
  dockhand/
    docker-compose.yml
    .env
```

Esto mantiene todo predecible. El asistente de IA sabe dónde poner los archivos, y tú sabes dónde encontrarlos cuando necesitas revisar algo manualmente.

## Qué hace el asistente de IA con todo esto

Con la infraestructura lista, puedes decirle a tu asistente de IA que despliegue apps. He instalado [Arcane](/es/instalar-arcane/) y [Dockhand](/es/instalar-dockhand/) de esta forma. Para más contexto sobre ambas, escribí una [comparación de las dos](/es/arcane-vs-dockhand/).

El asistente sigue el mismo flujo de trabajo cada vez:

1. Crea una nueva carpeta en `/home/user/docker-apps/app-name/`
2. Escribe un `docker-compose.yml` con rutas de volúmenes locales `./` (sin volúmenes nombrados)
3. Pone contraseñas y claves API en un archivo `.env`, no hardcodeadas en el archivo compose
4. Actualiza el Caddyfile en `/home/user/docker-apps/caddy/` con un nuevo bloque de subdominio
5. Arranca los contenedores con `sudo docker compose up -d`
6. Recarga Caddy para aplicar la nueva configuración
7. Ejecuta un curl contra el subdominio para confirmar que la app responde

Funciona porque hay un archivo de skill que le dice al asistente exactamente cómo está configurado este servidor y qué reglas seguir. Sin la skill, el asistente adivinaría las rutas, podría usar volúmenes nombrados, podría saltarse el proxy inverso o poner secretos directamente en el archivo compose.

## El archivo de skill

Este es el archivo que le enseña a tu asistente de IA cómo funciona tu servidor. Necesitas cambiar dos cosas en él antes de usarlo:

1. **La ruta** - reemplaza `/home/dragos/docker-apps` con tu ruta real
2. **El dominio** - reemplaza `*.ai.bitdoze.com` con tu dominio wildcard

<Notice type="warning" title="Cambia la ruta y el dominio">
La skill de abajo usa mi configuración como ejemplo. Necesitas reemplazar `/home/dragos/docker-apps` con tu propia ruta (como `/home/youruser/docker-apps`) y `*.ai.bitdoze.com` con tu dominio wildcard real.
</Notice>

Crea el archivo de skill en el directorio de skills de tu asistente. La ubicación depende de qué asistente de IA uses:

- **OpenClaw**: `~/.openclaw/workspace/skills/docker-deploy/SKILL.md`
- **Bot personalizado de Agno**: `workspace/skills/docker-deploy/SKILL.md`
- **OpenCode/Claude Code**: `.agents/skills/docker-deploy/SKILL.md`

El archivo de skill en sí:

<Tabs>
<Tab name="Archivo de skill">

```markdown
---
name: docker-deploy
description: >-
  Use this skill when deploying or modifying Dockerized apps on this server.
  It enforces server-specific constraints: Docker is installed with Caddy,
  commands that change system/runtime state should be run with sudo, app
  stacks live in /home/dragos/docker-apps, Caddy lives in
  /home/dragos/docker-apps/caddy, wildcard DNS *.ai.bitdoze.com points to this
  server for subdomain routing, and Docker Compose files should use local ./
  paths instead of named volumes.
---

# Docker + Caddy Server Rules

Apply these rules for all deployment, operations, and setup tasks on this server.

## Environment facts
- Docker is installed and available.
- Caddy is installed and managed from `/home/dragos/docker-apps/caddy`.
- Docker app projects must be placed under `/home/dragos/docker-apps`.
- Wildcard DNS `*.ai.bitdoze.com` points to this server and should be used for app subdomains.

## Permission model
- Use `sudo` for commands that manage Docker runtime/services, networking, filesystem locations requiring elevation, or system-level setup.
- Prefer explicit commands that can be audited and repeated.

## Compose placement and style
- Prefer Docker Compose-based deployments.
- Place each app in its own folder under `/home/dragos/docker-apps/<app-name>`.
- Keep compose and related app files together in the app folder.
- Do not use named volumes for app data/config in compose files.
- Use local relative paths (`./...`) in the location where the compose file is created.

## Caddy integration
- Route apps through Caddy using subdomains under `*.ai.bitdoze.com`.
- Keep Caddy config changes under `/home/dragos/docker-apps/caddy`.
- When adding a new app, include the target hostname and upstream container/service mapping.

## Expected workflow
1. Create app directory in `/home/dragos/docker-apps/<app-name>`.
2. Add `docker-compose.yml` with services and `./...` path mappings.
3. Add/update Caddy config in `/home/dragos/docker-apps/caddy` for `<app>.ai.bitdoze.com`.
4. Run required Docker/Caddy commands with `sudo`.
5. Validate service health and public routing.
6. Run curl to see if the new app is up on port or subdomain.
7. Place sensitive data into `.env` file not in compose directly like passwords and hashes.

## Guardrails
- Reject plans that place apps outside `/home/dragos/docker-apps`.
- Reject plans that use named Docker volumes for persistent files.
- Reject plans that bypass Caddy when public HTTP(S) access is required.
- Place sensitive data into `.env` file not in compose directly like passwords and hashes.
```

</Tab>
<Tab name="Qué cambiar">

Reemplaza estos valores con los tuyos:

| Marcador de posición | Tu valor |
|-------------|-----------|
| `/home/dragos/docker-apps` | La ruta de tu directorio de apps |
| `*.ai.bitdoze.com` | Tu dominio wildcard |
| `dragos` | Tu nombre de usuario |

Por ejemplo, si tu usuario es `john` y tu dominio es `apps.johndoe.com`:

- `/home/dragos/docker-apps` se convierte en `/home/john/docker-apps`
- `*.ai.bitdoze.com` se convierte en `*.apps.johndoe.com`

</Tab>
</Tabs>

## Cómo funciona la skill en la práctica

Una vez que el archivo de skill está en su lugar, el asistente lo lee cada vez que le pides desplegar algo. Así es como se ve una conversación real:

**Yo:** «Instala Uptime Kuma en mi servidor»

El asistente entonces:

```sh
# 1. Creates the directory
sudo mkdir -p /home/dragos/docker-apps/uptime-kuma

# 2. Writes the .env file (passwords go here, not in compose)
# Creates /home/dragos/docker-apps/uptime-kuma/.env

# 3. Writes docker-compose.yml with local paths
# Creates /home/dragos/docker-apps/uptime-kuma/docker-compose.yml
```

El archivo compose queda más o menos así:

```yaml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    networks:
      - caddy

networks:
  caddy:
    external: true
```

Fíjate en `./data` en lugar de un volumen nombrado. Eso es lo que impone la skill.

Luego actualiza el Caddyfile:

```
uptime-kuma.ai.bitdoze.com {
    reverse_proxy uptime-kuma:3001
}
```

Y lo arranca todo:

```sh
cd /home/dragos/docker-apps/uptime-kuma
sudo docker compose up -d
cd /home/dragos/docker-apps/caddy
sudo docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
curl -I https://uptime-kuma.ai.bitdoze.com
```

Todo el proceso tarda unos 30 segundos. Yo solo veo cómo llegan los mensajes.

## Por qué importan las salvaguardas

Sin la skill, los asistentes de IA toman decisiones razonables pero inconsistentes. Podrían:

- Poner los datos de la app en `/opt/` o `/var/` o donde les parezca
- Usar volúmenes nombrados de Docker, lo que complica los backups (tienes que rebuscar en `/var/lib/docker/volumes/`)
- Saltarse el proxy inverso y exponer puertos directamente
- Hardcodear contraseñas en el archivo compose, donde aparecen en `docker inspect`
- Olvidar comprobar si la app realmente arrancó

Las salvaguardas de la skill evitan todo esto. Si el asistente intenta crear un archivo compose con un volumen nombrado, la skill le dice que no. Si intenta exponer un puerto directamente sin pasar por Caddy, la skill dice que no.

Esta es la diferencia entre tener un asistente que puede desplegar apps y tener uno que despliega apps como tú quieres.

## Gestionar las apps desplegadas

Después de unos cuantos despliegues, querrás revisar cómo van las cosas. Algunos comandos útiles:

```sh
# See all running containers
sudo docker ps

# Check logs for a specific app
sudo docker logs uptime-kuma --tail 50

# Restart an app
cd /home/$USER/docker-apps/uptime-kuma
sudo docker compose restart

# Update an app to latest image
cd /home/$USER/docker-apps/uptime-kuma
sudo docker compose pull
sudo docker compose up -d

# Remove an app completely
cd /home/$USER/docker-apps/uptime-kuma
sudo docker compose down
cd ..
rm -rf uptime-kuma
# Also remove the Caddyfile entry
```

Para gestionar contenedores desde una UI web en lugar de la terminal, echa un vistazo a [Arcane](/es/instalar-arcane/) o [Dockhand](/es/instalar-dockhand/). Escribí sobre [cuál elegir](/es/arcane-vs-dockhand/) si estás decidiendo entre ambas. Incluso puedes pedirle a tu asistente de IA que instale cualquiera de ellas usando esta misma skill.

Si quieres actualizaciones automáticas de contenedores, [Tugtainer](/tugtainer-docker-autoupdate/) se encarga de eso sin necesidad de reconstruir los stacks de compose.

## Qué asistente de IA usar

Cualquier asistente de IA que admita skills o prompts de sistema puede usar este archivo. Lo he probado con:

- **[OpenClaw](/es/guia-configuracion-openclaw/)** ejecutándose en el mismo VPS, chateando por Telegram. Tiene acceso directo a la shell del servidor, así que ejecuta los comandos Docker él mismo.
- **Un [bot de Agno](/create-your-own-ai-agent/) personalizado** en Discord con herramientas de shell habilitadas. La misma idea, distinta plataforma de chat.
- **OpenCode/Claude Code** conectado por SSH. Funciona si prefieres herramientas de código a bots de chat.

La configuración con OpenClaw es la más desatendida. Le envías mensajes por Telegram desde tu teléfono, y él hace todo en el servidor sin que abras una terminal. La [guía de configuración](/es/guia-configuracion-openclaw/) cubre la instalación.

Para construir tu propio bot desde cero, la [guía del bot de Agno](/create-your-own-ai-agent/) recorre todo el proceso, incluida la integración con Discord, la memoria y los agentes de equipo.

## Ampliar la skill

El archivo de skill es solo markdown. Puedes añadir reglas a medida que tu configuración crece. Algunas cosas que he añadido a la mía con el tiempo:

- Una sección de backups que le dice al asistente que cree un script `backup.sh` en cada carpeta de app
- Preferencias de base de datos (usar PostgreSQL en lugar de MySQL cuando la app admite ambas)
- Límites de recursos para los contenedores (`deploy.resources.limits` en compose)
- Una regla de monitorización que añade todas las apps nuevas a mi instancia de Uptime Kuma automáticamente

También puedes pedirle al asistente que actualice la propia skill. «Añade una regla para que todas las apps nuevas incluyan un healthcheck en el archivo compose» funciona bien. Lee la skill, añade la regla y la sigue a partir de entonces.

## El panorama general

Esta configuración convierte un VPS en algo que gestionas mediante conversación. El servidor sigue ejecutando Docker y Caddy como cualquier configuración normal. La diferencia es que tu asistente de IA conoce las reglas y las sigue de forma consistente.

He desplegado unas 15 apps de esta forma en las últimas semanas. Algunas las mantuve, otras las probé una hora y las eliminé. Lo que cambió es la velocidad a la que pruebas cosas. Cuando instalar una app lleva 30 segundos escribiendo un mensaje en lugar de 10 minutos escribiendo archivos compose, pruebas más cosas.

Los prerrequisitos llevan quizá una hora de configuración si empiezas desde cero. Después de eso, cada despliegue es un mensaje de chat.

El archivo de skill de aquí usa el mismo formato `SKILL.md` que emplean los agentes de código. Para skills que mejoran lo que tu agente construye —no solo dónde lo despliega— comparé las [mejores skills de IA para diseño web](/es/mejores-skills-ia-diseno-web/).

<Accordion label="Preguntas frecuentes" group="faq" expanded="true">

**¿El asistente necesita acceso root?**

Necesita ejecutar comandos Docker con `sudo`. Si tu usuario está en el grupo `docker`, puedes modificar la skill para eliminar el requisito de `sudo`, pero prefiero mantenerlo explícito.

**¿Puedo usar Nginx o Traefik en lugar de Caddy?**

Sí, pero tendrías que reescribir las partes específicas de Caddy de la skill. Caddy es la opción más sencilla porque gestiona los certificados automáticamente sin configuración extra. Si ya usas [Traefik](/traefik-proxy-docker/), adapta la skill para usar labels en lugar de entradas de Caddyfile.

**¿Qué pasa si el asistente estropea algo?**

Cada app está aislada en su propia carpeta. Si algo sale mal, `docker compose down` en esa carpeta la detiene, y borrar la carpeta la limpia por completo. El peor caso es una entrada rota en el Caddyfile, que se arregla editando un solo archivo.

**¿Pueden varios asistentes compartir la misma skill?**

Sí. La skill describe convenciones del servidor, no comportamientos específicos del asistente. Pon el mismo archivo en el directorio de skills de cada asistente y todos seguirán las mismas reglas.

**¿Funciona esto en servidores ARM (Raspberry Pi)?**

La skill en sí es agnóstica a la arquitectura. Que las imágenes Docker que despliegues tengan builds para ARM es otra cuestión. La mayoría de las apps self-hosted populares ya publican imágenes multi-arquitectura.

</Accordion>