Requisitos previos
Antes de empezar, los siguientes elementos deben estar en su sitio:
- Acceso SSH protegido por clave: Guía de clave SSH
- Cortafuegos UFW configurado: Guía UFW (lea también la sección Docker y UFW más abajo antes de exponer puertos)
- Un usuario no root con permisos sudo, o acceso root directo
- SO: Debian 13 (Trixie) o Ubuntu 24.04 LTS
Paso 1: Añadir el repositorio oficial de Docker
No instale el paquete docker.io que ofrecen Debian/Ubuntu: va por detrás de las versiones oficiales. Utilice el repositorio de Docker Inc. para obtener docker-ce, la versión mantenida activamente.
En Debian 13
Fuente: docs.docker.com/engine/install/debian/
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update En Ubuntu 24.04
Fuente: docs.docker.com/engine/install/ubuntu/
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update Paso 2: Instalar Docker Engine y Docker Compose
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin Este paquete instala a la vez:
- docker-ce: el motor Docker
- docker-ce-cli: la interfaz de línea de comandos
- containerd.io: el runtime de contenedores
- docker-buildx-plugin: el plugin de build multiplataforma
- docker-compose-plugin: Docker Compose v2 (comando
docker compose, sin guion)
Verificar la instalación:
docker --version
docker compose version Nota importante sobre Docker Compose: el plugin v2 se llama docker compose (dos palabras, sin guion). El antiguo binario standalone docker-compose (con guion) es la versión v1, obsoleta desde julio de 2023 y no instalada aquí. Fuente: docs.docker.com/compose/migrate/
Activar Docker en el arranque del sistema:
sudo systemctl enable docker.service
sudo systemctl enable containerd.service Fuente: docs.docker.com/engine/install/linux-postinstall/
Paso 3: Configurar el acceso no root
Añadir el usuario al grupo docker
Por defecto, los comandos Docker requieren sudo. Para ejecutarlos sin sudo, añada el usuario al grupo docker:
sudo usermod -aG docker $USER
newgrp docker El comando newgrp docker aplica el cambio en la sesión actual sin cerrar sesión. Fuente: docs.docker.com/engine/install/linux-postinstall/
Advertencia de seguridad sobre el grupo docker
Paso 4: Primer contenedor de prueba
Comprobar que la instalación funciona con la imagen oficial hello-world:
docker run hello-world Docker descarga la imagen desde Docker Hub si no está presente localmente, lanza un contenedor, muestra un mensaje de confirmación y se detiene. Una salida que contenga "Hello from Docker!" confirma que la instalación es operativa.
Docker y UFW: la trampa que hay que conocer
Lo que ocurre en la práctica
Lanzar un contenedor con docker run -p 8080:80 nginx abre el puerto 8080 en todas las interfaces de red del VPS, incluida la IP pública, aunque UFW no autorice ese puerto. Fuente: docs.docker.com/engine/network/packet-filtering-firewalls/
La buena práctica: enlazar a 127.0.0.1
Para exponer un puerto solo en local (accesible desde el VPS pero no desde Internet), enlazar a la interfaz loopback:
# Comando docker run
docker run -p 127.0.0.1:8080:80 nginx
# En un compose.yml
ports:
- "127.0.0.1:8080:80" El puerto 8080 queda entonces accesible únicamente desde el propio VPS (a través de un reverse proxy Nginx, por ejemplo), y no desde el exterior.
Para los puertos que deben seguir siendo públicos
Utilizar la cadena DOCKER-USER de iptables para filtrar el tráfico antes de que Docker lo procese. Añadir una regla en /etc/ufw/after.rules o configurar iptables directamente. La documentación oficial detalla este enfoque: Restrict connections to the Docker host.
Recomendación práctica
Para un VPS que aloja servicios web mediante Docker:
- Enlazar todos los contenedores a
127.0.0.1por defecto - Colocar un reverse proxy Nginx delante (puertos 80 y 443 gestionados por Nginx, no por Docker directamente)
- Abrir únicamente los puertos 80 y 443 en UFW (Guía UFW)
- No exponer nunca directamente los puertos de bases de datos (3306, 5432, 6379) en la IP pública
Mantenimiento de los contenedores
Limpiar los recursos no utilizados
Docker acumula imágenes, contenedores detenidos, volúmenes y redes huérfanas. Limpiar con regularidad:
# Eliminar todos los contenedores detenidos, imágenes no utilizadas, redes huérfanas
docker system prune
# Incluir también los volúmenes no utilizados (atención: eliminación definitiva)
docker system prune --volumes Consultar los logs de un contenedor
# Mostrar los logs del contenedor
docker logs nombre_contenedor
# Seguimiento en tiempo real
docker logs -f nombre_contenedor
# Limitar el número de líneas mostradas
docker logs --tail 100 nombre_contenedor Actualizar Docker Engine
sudo apt update
sudo apt upgrade docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin Actualizar una imagen Docker
# Descargar la última versión de la imagen
docker pull nombre_imagen:tag
# Recrear el contenedor con la nueva imagen
docker compose pull
docker compose up -d ¿Qué configuración de VPS para Docker?
| Uso | RAM recomendada | Oferta OuiHeberg |
|---|---|---|
| 1 a 3 contenedores ligeros (web, bot, API) | 4 GB | VPS Linux 04G: 7,00 € IVA incl./mes |
| Stack completa (app + base de datos + caché) | 8 GB | Ver la gama VPS Linux |
| Varios proyectos o servicios pesados | 16 GB+ | Ver la gama VPS Linux |
Estas estimaciones suponen contenedores en producción estándar. Las necesidades varían según las imágenes utilizadas y el tráfico simultáneo.
Preguntas frecuentes
¿Cuál es la diferencia entre docker.io y docker-ce?
docker.io es el paquete Docker que ofrecen los repositorios de Debian/Ubuntu. Suele ir por detrás de las versiones oficiales y no recibe las actualizaciones con la misma rapidez. docker-ce (Community Edition) es el paquete mantenido directamente por Docker Inc. a través de su repositorio oficial. Esta guía utiliza docker-ce.
¿Es Docker Compose v2 compatible con los antiguos ficheros docker-compose.yml?
Sí. El formato de los ficheros compose.yml (o docker-compose.yml) es compatible entre v1 y v2. La única diferencia visible es el comando: docker compose (v2, plugin) sustituye a docker-compose (v1, binario standalone). La sintaxis de los ficheros sigue siendo idéntica en la gran mayoría de los casos de uso.
¿Cómo comprobar que Docker funciona tras reiniciar el VPS?
sudo systemctl status docker Si Docker está configurado con systemctl enable docker.service, arranca automáticamente. Compruebe también que los contenedores tienen la política de reinicio adecuada en el compose.yml: restart: unless-stopped o restart: always.
¿Se puede usar Docker sin acceso root?
Sí, mediante el modo rootless. Docker puede funcionar por completo sin privilegios root, lo que reduce la superficie de ataque. La puesta en marcha es más compleja y está documentada aquí: docs.docker.com/engine/security/rootless/
¿Cómo proteger mejor el daemon Docker?
Configurar Fail2ban para proteger el acceso SSH al VPS es un primer paso: consulte la Guía Fail2ban. Para el propio Docker, no exponga nunca el socket Docker (/var/run/docker.sock) a contenedores que no sean de confianza, y no active la API TCP de Docker sin TLS mutuo.
¿Docker instalado? Antes de pasar a producción, repasa la seguridad de tu VPS de la A a la Z.
