🐳 Docker y Docker Compose
Instalación y configuración de Docker para contenedores de aplicaciones.
Índice
- Instalación de Docker
- Actualizar a Docker Compose v2
- Configurar Memoria Swap
- Prueba de Funcionamiento
- Comandos Útiles
Instalación de Docker
Instalar Docker y Docker Compose
Importante: Cerrar sesión y volver a entrar para que el grupo docker se aplique:
Verificar instalación
docker --version # Docker version 28.2.2
docker-compose --version # docker-compose version 1.29.2
docker ps # Debe funcionar sin errores de permisos
Resultado esperado:
Docker version 28.2.2, build 28.2.2-0ubuntu1~24.04.1
docker-compose version 1.29.2, build unknown
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Actualizar a Docker Compose v2
¿Por qué actualizar?
- Docker Compose v1 (
docker-compose): Versión legacy, ya no recibe actualizaciones importantes - Docker Compose v2 (
docker compose): Plugin oficial, más rápido y mejor mantenido
Instalación del plugin v2
Como instalamos Docker desde repositorios de Ubuntu (docker.io), el plugin no está disponible en los repos. Lo instalamos manualmente:
# Crear directorio para plugins
sudo mkdir -p /usr/local/lib/docker/cli-plugins
# Descargar Docker Compose v2 (última versión)
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \
-o /usr/local/lib/docker/cli-plugins/docker-compose
# Dar permisos de ejecución
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
# Verificar versión
docker compose version
Resultado esperado:
Ahora tienes ambas versiones
docker-compose(v1.29.2 - legacy) - Sigue funcionandodocker compose(v2.40.1 - nuevo) - ← Usa este de ahora en adelante
La sintaxis es casi idéntica, solo cambia el guión por espacio:
Configurar Memoria Swap
¿Por qué configurar Swap?
Con 4GB de RAM, la memoria swap es muy recomendable: - ✅ Evita que el sistema se bloquee si se queda sin memoria - ✅ Funciona como "colchón de seguridad" - ✅ Permite manejar picos temporales de uso - ✅ Previene que Docker mate procesos (OOM killer)
Crear archivo swap de 2GB
# Crear archivo swap
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Hacer permanente (sobrevive reinicios)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Ajustar swappiness (usar swap solo cuando sea necesario)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
¿Qué hace swappiness=10?
- Valor por defecto: 60 (usa swap frecuentemente)
- Valor 10: Solo usa swap cuando la RAM está casi llena
- Ventaja: Mejor para SSDs porque reduce escrituras
Verificar que funciona
# Ver swap activa
free -h
# Ver información detallada de swap
swapon --show
# Ver swappiness configurado
cat /proc/sys/vm/swappiness
# Resultado esperado: debería mostrar "10"
Ejemplo de salida de free -h:
total used free shared buff/cache available
Mem: 3.8Gi 1.2Gi 1.5Gi 10Mi 1.1Gi 2.4Gi
Swap: 2.0Gi 0B 2.0Gi
Prueba de Funcionamiento
Desplegar un contenedor de prueba
# Crear directorio de prueba
mkdir -p ~/apps/compose-test && cd ~/apps/compose-test
# Crear docker-compose.yml
cat > docker-compose.yml <<'YAML'
services:
hello:
image: nginxdemos/hello
ports: ["3000:80"]
YAML
# Levantar el servicio
docker compose up -d
# Ver contenedores
docker ps
Configurar Firewall para pruebas
IMPORTANTE: Para acceder a puertos personalizados (como 3000), debes abrirlos en AMBOS firewalls.
1. UFW (en el VPS):
2. Hetzner Cloud Firewall (desde el panel web): - Ve a Firewalls → Editar tu firewall - Añade regla Inbound: - Protocol: TCP - Port: 3000 - Source: Any IPv4/IPv6 - Guardar cambios
3. Probar:
Abre http://YOUR_SERVER_IP:3000 en tu navegador. Deberías ver una página de demo de Nginx.
Limpiar después de probar
cd ~/apps/compose-test
# Parar y eliminar contenedor
docker compose down
# Eliminar imagen (opcional)
docker rmi nginxdemos/hello
# Cerrar puerto en firewall (opcional)
sudo ufw delete allow 3000/tcp
# Y quitar la regla del puerto 3000 en Hetzner Cloud Firewall
Nota sobre Firewalls y Puertos Personalizados
Recuerda: Con doble firewall, AMBOS deben permitir el puerto:
- Hetzner Cloud Firewall filtra PRIMERO (capa externa)
- UFW filtra DESPUÉS (capa interna)
Si solo configuras uno, el tráfico será bloqueado.
Comandos Útiles
Docker básico
# Ver contenedores en ejecución
docker ps
# Ver todos los contenedores (incluidos detenidos)
docker ps -a
# Ver imágenes descargadas
docker images
# Ver logs de un contenedor
docker logs nombre_contenedor
docker logs -f nombre_contenedor # seguir logs en tiempo real
# Ejecutar comando en contenedor
docker exec -it nombre_contenedor bash
# Ver uso de recursos en tiempo real
docker stats
# Ver redes de Docker
docker network ls
# Ver volúmenes de Docker
docker volume ls
# Limpiar recursos no usados (cuidado: elimina contenedores parados, imágenes no usadas, etc.)
docker system prune -a
# Ver información del sistema Docker
docker info
# Inspeccionar contenedor
docker inspect nombre_contenedor
# Parar todos los contenedores
docker stop $(docker ps -q)
# Eliminar todos los contenedores parados
docker container prune
Docker Compose v2 (Recomendado)
# Ver versión
docker compose version
# Levantar servicios en segundo plano
docker compose up -d
# Levantar servicios con rebuild
docker compose up -d --build
# Ver logs
docker compose logs
docker compose logs -f # seguir logs
docker compose logs servicio # logs de un servicio específico
# Parar servicios (mantiene contenedores)
docker compose stop
# Parar y eliminar contenedores
docker compose down
# Parar, eliminar contenedores y volúmenes
docker compose down -v
# Ver estado de servicios
docker compose ps
# Reiniciar servicios
docker compose restart
# Reiniciar un servicio específico
docker compose restart nombre_servicio
# Ejecutar comando en un servicio
docker compose exec nombre_servicio bash
# Ver configuración parseada
docker compose config
# Actualizar imagen y recrear
docker compose pull
docker compose up -d
# Escalar servicios
docker compose up -d --scale web=3
Docker Compose v1 (Legacy)
# Los comandos son los mismos, solo cambia el guion
docker-compose up -d
docker-compose down
docker-compose logs -f
# etc.
Recomendación: Usa docker compose (v2) para nuevos proyectos.
Gestión de memoria
# Ver uso de memoria y swap
free -h
# Ver procesos que consumen más memoria
ps aux --sort=-%mem | head -n 10
# Ver si el swap está activo
swapon --show
# Ver swappiness (debe ser 10)
cat /proc/sys/vm/swappiness
# Ver uso de recursos en tiempo real
htop
# Deshabilitar swap temporalmente (no recomendado)
sudo swapoff -a
# Habilitar swap
sudo swapon -a
Buenas Prácticas
Estructura de proyectos
~/apps/
├── nombre-app-1/
│ ├── docker-compose.yml
│ ├── .env
│ └── data/
├── nombre-app-2/
│ ├── docker-compose.yml
│ └── config/
└── nombre-app-3/
└── docker-compose.yml
Usar .env para configuraciones
# docker-compose.yml
services:
web:
image: nginx:alpine
ports:
- "${PORT}:80"
environment:
- DOMAIN=${DOMAIN}
Siempre usar restart policies
Opciones de restart:
- no: No reiniciar (default)
- always: Siempre reiniciar
- on-failure: Solo si falla
- unless-stopped: Reiniciar excepto si se paró manualmente
Usar volúmenes nombrados
services:
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Limpieza regular
# Limpiar imágenes no usadas (semanal/mensual)
docker image prune -a
# Limpiar volúmenes huérfanos
docker volume prune
# Limpieza completa (cuidado)
docker system prune -a --volumes
Recursos del Sistema
Especificaciones del VPS
- RAM: 4 GB
- Swap: 2 GB (configurado)
- Disco: 40 GB NVMe
- CPU: 2 vCPU
Monitoreo recomendado
# Revisar uso de memoria regularmente
free -h
# Ver uso de disco
df -h
# Ver uso de Docker
docker system df
# Estadísticas de contenedores
docker stats --no-stream
Troubleshooting
Docker no funciona después de instalarlo
# Cerrar sesión y volver a entrar
exit
ssh your_username@YOUR_SERVER_IP
# Verificar que estás en el grupo docker
groups
# Si no aparece "docker", vuelve a ejecutar:
sudo usermod -aG docker your_username
Error "permission denied" al usar Docker
# Verificar grupo docker
groups
# Si no estás en el grupo, añadirte:
sudo usermod -aG docker $USER
# Cerrar sesión y volver a entrar
exit
ssh your_username@YOUR_SERVER_IP
Contenedor no arranca
# Ver logs del contenedor
docker logs nombre_contenedor
# Ver eventos de Docker
docker events
# Inspeccionar contenedor
docker inspect nombre_contenedor
Sistema sin memoria
# Ver uso de memoria
free -h
# Ver swap activo
swapon --show
# Ver procesos que consumen memoria
docker stats
# Si es necesario, reiniciar contenedores
docker compose restart
⬅️ Anterior: Seguridad | Volver al índice | ➡️ Siguiente: Nginx