Eliminar página de Backup
520
Backup.md
520
Backup.md
@@ -1,520 +0,0 @@
|
||||
# Backup y Restauración
|
||||
|
||||
Esta guía explica cómo realizar copias de seguridad y restaurar los datos de Portainer CE.
|
||||
|
||||
## ¿Qué se Respalda?
|
||||
|
||||
Portainer almacena todos sus datos en el volumen Docker **`portainer_data`**, que incluye:
|
||||
|
||||
- 🔐 **Configuración de usuarios y autenticación**
|
||||
- 🌐 **Entornos (endpoints) configurados**
|
||||
- 📦 **Stacks, plantillas y configuraciones**
|
||||
- 🔑 **Secretos, configs, y credenciales**
|
||||
- 📊 **Configuraciones de roles y permisos**
|
||||
- 🎨 **Personalizaciones de UI y configuraciones**
|
||||
|
||||
⚠️ **Importante**: El volumen `portainer_data` contiene información sensible. Protege los backups adecuadamente.
|
||||
|
||||
## Estrategias de Backup
|
||||
|
||||
### Opción 1: Backup Manual del Volumen
|
||||
|
||||
#### Crear Backup
|
||||
|
||||
```bash
|
||||
# Detener Portainer (recomendado para consistencia)
|
||||
docker compose down
|
||||
|
||||
# Crear backup del volumen usando contenedor temporal
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
|
||||
|
||||
# Reiniciar Portainer
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Resultado**: Archivo `portainer-backup-YYYYMMDD-HHMMSS.tar.gz` en el directorio actual.
|
||||
|
||||
#### Backup sin Detener Portainer (En Caliente)
|
||||
|
||||
```bash
|
||||
# Crear backup sin detener el servicio
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
|
||||
```
|
||||
|
||||
⚠️ **Nota**: Los backups en caliente pueden tener inconsistencias si hay cambios durante la copia. Para backups críticos, detén Portainer primero.
|
||||
|
||||
#### Restaurar Backup
|
||||
|
||||
```bash
|
||||
# 1. Detener Portainer
|
||||
docker compose down
|
||||
|
||||
# 2. Eliminar volumen existente (⚠️ cuidado!)
|
||||
docker volume rm portainer_data
|
||||
|
||||
# 3. Crear nuevo volumen
|
||||
docker volume create portainer_data
|
||||
|
||||
# 4. Restaurar datos desde backup
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data
|
||||
|
||||
# 5. Verificar permisos
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
alpine \
|
||||
chown -R root:root /data
|
||||
|
||||
# 6. Reiniciar Portainer
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Opción 2: Backup con Script Automatizado
|
||||
|
||||
Crear script `backup-portainer.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
BACKUP_DIR="/var/backups/portainer"
|
||||
RETENTION_DAYS=30
|
||||
VOLUME_NAME="portainer_data"
|
||||
COMPOSE_PATH="/ruta/a/tu/portainer"
|
||||
|
||||
# Crear directorio de backups si no existe
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Timestamp
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
BACKUP_FILE="$BACKUP_DIR/portainer-backup-$TIMESTAMP.tar.gz"
|
||||
|
||||
echo "[$(date)] Iniciando backup de Portainer..."
|
||||
|
||||
# Opción 1: Backup en caliente (servicio corriendo)
|
||||
docker run --rm \
|
||||
-v "$VOLUME_NAME":/data:ro \
|
||||
-v "$BACKUP_DIR":/backup \
|
||||
alpine \
|
||||
tar czf "/backup/portainer-backup-$TIMESTAMP.tar.gz" -C /data .
|
||||
|
||||
# Opción 2: Backup con detención (más seguro, comentar la opción 1 si usas esta)
|
||||
# cd "$COMPOSE_PATH"
|
||||
# docker compose down
|
||||
# docker run --rm \
|
||||
# -v "$VOLUME_NAME":/data \
|
||||
# -v "$BACKUP_DIR":/backup \
|
||||
# alpine \
|
||||
# tar czf "/backup/portainer-backup-$TIMESTAMP.tar.gz" -C /data .
|
||||
# docker compose up -d
|
||||
|
||||
# Verificar que el backup se creó
|
||||
if [ -f "$BACKUP_FILE" ]; then
|
||||
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
echo "[$(date)] Backup completado: $BACKUP_FILE ($SIZE)"
|
||||
else
|
||||
echo "[$(date)] ERROR: Backup falló"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Limpiar backups antiguos
|
||||
echo "[$(date)] Limpiando backups antiguos (>$RETENTION_DAYS días)..."
|
||||
find "$BACKUP_DIR" -name "portainer-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
|
||||
|
||||
echo "[$(date)] Proceso completado"
|
||||
```
|
||||
|
||||
Hacer ejecutable y probar:
|
||||
|
||||
```bash
|
||||
chmod +x backup-portainer.sh
|
||||
./backup-portainer.sh
|
||||
```
|
||||
|
||||
### Opción 3: Backup Automatizado con Cron
|
||||
|
||||
Programar backups diarios a las 2:00 AM:
|
||||
|
||||
```bash
|
||||
# Editar crontab
|
||||
crontab -e
|
||||
|
||||
# Añadir línea:
|
||||
0 2 * * * /ruta/a/backup-portainer.sh >> /var/log/portainer-backup.log 2>&1
|
||||
```
|
||||
|
||||
Verificar cron:
|
||||
|
||||
```bash
|
||||
# Ver crontab actual
|
||||
crontab -l
|
||||
|
||||
# Ver logs de backup
|
||||
tail -f /var/log/portainer-backup.log
|
||||
```
|
||||
|
||||
### Opción 4: Backup a Almacenamiento Remoto
|
||||
|
||||
#### Backup a NFS/CIFS
|
||||
|
||||
```bash
|
||||
# Montar share remoto
|
||||
mount -t nfs servidor.local:/backups /mnt/backups
|
||||
|
||||
# Crear backup directamente en share
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v /mnt/backups:/backup \
|
||||
alpine \
|
||||
tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
|
||||
```
|
||||
|
||||
#### Backup a S3/MinIO
|
||||
|
||||
Usando `rclone`:
|
||||
|
||||
```bash
|
||||
# Configurar rclone primero
|
||||
rclone config
|
||||
|
||||
# Crear backup y subir a S3
|
||||
BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf "/backup/$BACKUP_FILE" -C /data .
|
||||
|
||||
rclone copy "$BACKUP_FILE" s3-remote:bucket-name/portainer-backups/
|
||||
rm "$BACKUP_FILE"
|
||||
```
|
||||
|
||||
#### Backup con rsync
|
||||
|
||||
```bash
|
||||
# Crear backup local
|
||||
BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf "/backup/$BACKUP_FILE" -C /data .
|
||||
|
||||
# Copiar a servidor remoto
|
||||
rsync -avz --progress "$BACKUP_FILE" usuario@servidor-backup:/backups/portainer/
|
||||
|
||||
# Opcional: eliminar backup local
|
||||
rm "$BACKUP_FILE"
|
||||
```
|
||||
|
||||
## Restauración de Emergencia
|
||||
|
||||
### Escenario 1: Corrupción de Datos
|
||||
|
||||
```bash
|
||||
# 1. Detener Portainer inmediatamente
|
||||
docker compose down
|
||||
|
||||
# 2. Renombrar volumen corrupto (por si acaso)
|
||||
docker volume create portainer_data_corrupted
|
||||
docker run --rm \
|
||||
-v portainer_data:/source \
|
||||
-v portainer_data_corrupted:/dest \
|
||||
alpine \
|
||||
sh -c "cp -a /source/. /dest/"
|
||||
|
||||
# 3. Limpiar volumen original
|
||||
docker volume rm portainer_data
|
||||
docker volume create portainer_data
|
||||
|
||||
# 4. Restaurar desde último backup válido
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data
|
||||
|
||||
# 5. Reiniciar
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Escenario 2: Migración a Nuevo Servidor
|
||||
|
||||
En el **servidor antiguo**:
|
||||
|
||||
```bash
|
||||
# Crear backup
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf /backup/portainer-migration.tar.gz -C /data .
|
||||
|
||||
# Copiar a nuevo servidor
|
||||
scp portainer-migration.tar.gz usuario@nuevo-servidor:/tmp/
|
||||
```
|
||||
|
||||
En el **servidor nuevo**:
|
||||
|
||||
```bash
|
||||
# 1. Clonar repositorio o copiar docker-compose.yaml
|
||||
git clone https://git.ictiberia.com/groales/portainer
|
||||
cd portainer
|
||||
|
||||
# 2. Crear volumen
|
||||
docker volume create portainer_data
|
||||
|
||||
# 3. Restaurar datos
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v /tmp:/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-migration.tar.gz -C /data
|
||||
|
||||
# 4. Iniciar Portainer
|
||||
docker compose up -d
|
||||
|
||||
# 5. Verificar
|
||||
docker logs portainer
|
||||
```
|
||||
|
||||
### Escenario 3: Rollback a Versión Anterior
|
||||
|
||||
Si una actualización de Portainer causa problemas:
|
||||
|
||||
```bash
|
||||
# 1. Detener versión actual
|
||||
docker compose down
|
||||
|
||||
# 2. Editar docker-compose.yaml y cambiar tag
|
||||
# De: portainer/portainer-ce:lts
|
||||
# A: portainer/portainer-ce:2.19.4 (versión específica)
|
||||
|
||||
# 3. Restaurar backup de antes de la actualización
|
||||
docker volume rm portainer_data
|
||||
docker volume create portainer_data
|
||||
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-backup-pre-update.tar.gz -C /data
|
||||
|
||||
# 4. Iniciar versión anterior
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Verificación de Backups
|
||||
|
||||
### Test de Restauración
|
||||
|
||||
Es crítico **probar tus backups regularmente**:
|
||||
|
||||
```bash
|
||||
# 1. Crear volumen de test
|
||||
docker volume create portainer_data_test
|
||||
|
||||
# 2. Restaurar backup en volumen de test
|
||||
docker run --rm \
|
||||
-v portainer_data_test:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data
|
||||
|
||||
# 3. Iniciar Portainer temporal en otro puerto
|
||||
docker run -d \
|
||||
-p 19443:9443 \
|
||||
--name portainer-test \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v portainer_data_test:/data \
|
||||
portainer/portainer-ce:lts
|
||||
|
||||
# 4. Verificar en https://localhost:19443
|
||||
# Login y verificar que los datos son correctos
|
||||
|
||||
# 5. Limpiar
|
||||
docker stop portainer-test
|
||||
docker rm portainer-test
|
||||
docker volume rm portainer_data_test
|
||||
```
|
||||
|
||||
### Validar Integridad de Backup
|
||||
|
||||
```bash
|
||||
# Verificar que el tar.gz no está corrupto
|
||||
tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz > /dev/null
|
||||
echo $? # Debe devolver 0 si OK
|
||||
|
||||
# Ver contenido del backup
|
||||
tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz | head -20
|
||||
|
||||
# Ver tamaño
|
||||
du -h portainer-backup-YYYYMMDD-HHMMSS.tar.gz
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Estrategia 3-2-1
|
||||
|
||||
- ✅ **3 copias** de tus datos (original + 2 backups)
|
||||
- ✅ **2 medios diferentes** (ej: disco local + NAS)
|
||||
- ✅ **1 copia offsite** (ej: cloud, otro datacenter)
|
||||
|
||||
### 2. Frecuencia de Backups
|
||||
|
||||
Según criticidad:
|
||||
|
||||
| Entorno | Frecuencia Recomendada |
|
||||
|---------|------------------------|
|
||||
| Producción crítica | Cada 6-12 horas |
|
||||
| Producción estándar | Diario |
|
||||
| Desarrollo/Testing | Semanal |
|
||||
|
||||
### 3. Retención
|
||||
|
||||
Ejemplo de política:
|
||||
|
||||
- **Diarios**: 7 días
|
||||
- **Semanales**: 4 semanas
|
||||
- **Mensuales**: 12 meses
|
||||
- **Anuales**: 3 años
|
||||
|
||||
Script de retención:
|
||||
|
||||
```bash
|
||||
# Diarios (últimos 7)
|
||||
find /backups -name "portainer-backup-*.tar.gz" -mtime +7 -mtime -30 -delete
|
||||
|
||||
# Mantener un backup semanal (domingos)
|
||||
# Mantener un backup mensual (día 1)
|
||||
# (implementar lógica adicional según necesidades)
|
||||
```
|
||||
|
||||
### 4. Encriptación de Backups
|
||||
|
||||
Para backups con datos sensibles:
|
||||
|
||||
```bash
|
||||
# Crear backup encriptado con GPG
|
||||
BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||
|
||||
docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf "/backup/$BACKUP_FILE" -C /data .
|
||||
|
||||
# Encriptar
|
||||
gpg --symmetric --cipher-algo AES256 "$BACKUP_FILE"
|
||||
|
||||
# Resultado: portainer-backup-YYYYMMDD-HHMMSS.tar.gz.gpg
|
||||
rm "$BACKUP_FILE" # Eliminar versión sin encriptar
|
||||
```
|
||||
|
||||
Restaurar encriptado:
|
||||
|
||||
```bash
|
||||
# Desencriptar
|
||||
gpg --decrypt portainer-backup-YYYYMMDD-HHMMSS.tar.gz.gpg > portainer-backup.tar.gz
|
||||
|
||||
# Restaurar normalmente
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar xzf /backup/portainer-backup.tar.gz -C /data
|
||||
```
|
||||
|
||||
### 5. Monitorización de Backups
|
||||
|
||||
Script con notificaciones:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# backup-portainer-monitored.sh
|
||||
|
||||
BACKUP_DIR="/var/backups/portainer"
|
||||
WEBHOOK_URL="https://hooks.slack.com/services/TU_WEBHOOK" # O email, etc.
|
||||
|
||||
# ... (lógica de backup) ...
|
||||
|
||||
# Notificar resultado
|
||||
if [ $? -eq 0 ]; then
|
||||
curl -X POST "$WEBHOOK_URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"text\":\"✅ Backup Portainer completado: $BACKUP_FILE\"}"
|
||||
else
|
||||
curl -X POST "$WEBHOOK_URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"text\":\"❌ ERROR: Backup Portainer falló\"}"
|
||||
fi
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "Permission denied"
|
||||
|
||||
```bash
|
||||
# Ejecutar backup con sudo
|
||||
sudo docker run --rm \
|
||||
-v portainer_data:/data:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine \
|
||||
tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
|
||||
```
|
||||
|
||||
### Backup Muy Grande
|
||||
|
||||
```bash
|
||||
# Ver tamaño del volumen
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
alpine \
|
||||
du -sh /data
|
||||
|
||||
# Limpiar logs/cache dentro del volumen si es necesario
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
alpine \
|
||||
sh -c "find /data -name '*.log' -delete"
|
||||
```
|
||||
|
||||
### Restauración No Funciona
|
||||
|
||||
```bash
|
||||
# Verificar contenido del backup
|
||||
tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz | less
|
||||
|
||||
# Listar contenido del volumen restaurado
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
alpine \
|
||||
ls -laR /data
|
||||
|
||||
# Verificar permisos
|
||||
docker run --rm \
|
||||
-v portainer_data:/data \
|
||||
alpine \
|
||||
chown -R root:root /data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Recursos adicionales**:
|
||||
- [Documentación oficial de Portainer](https://docs.portainer.io/)
|
||||
- [Docker Volume Backup Strategies](https://docs.docker.com/storage/volumes/)
|
||||
|
||||
**Volver a**: [Página Principal](Home) | [Instalación Avanzada](Instalacion)
|
||||
1
Home.md
1
Home.md
@@ -77,7 +77,6 @@ https://<IP-del-servidor>:9443
|
||||
|
||||
## Próximos Pasos
|
||||
|
||||
- 💾 [Backup y Restauración](Backup) - Cómo respaldar y restaurar datos de Portainer
|
||||
- 🌐 [Integración con Traefik](Traefik) - Configurar proxy inverso con TLS automático
|
||||
- 🔌 [Edge Agents](Edge-Agents) - Gestionar entornos remotos con agentes Edge
|
||||
|
||||
|
||||
Reference in New Issue
Block a user