Cómo instalar / actualizar contenedores Docker con Script "update-container.sh" - Script para actualizar contenedores Docker automatizado

update-container.sh | Docker Compose | Bash Script | Automatización | Mantenimiento | Pull + Up | Pruning

update-container.sh: Script Bash para actualizar contenedores Docker Compose automático con validación segura, error handling, limpieza de imágenes, flexible (interactivo o argumento), idempotente, production-ready 🐳⚙️

update-container.sh es un script Bash profesional que automatiza la actualización de contenedores Docker Compose. Descarga imágenes nuevas (docker compose pull), relanza contenedores (docker compose up -d), limpia imágenes obsoletas (docker image prune). Soporta uso interactivo (pide nombre) o por argumento. Validación segura con set -uo pipefail. Error handling robusto. Almacena contenedores en $HOME/docker/. Production-ready. Ideal homelabs + sysadmin automation.

¿Qué es update-container.sh?

update-container.sh es un script Bash profesional que automatiza el proceso completo de actualización de contenedores Docker Compose autohospedados con pull de imágenes, relanzamiento de servicios, error handling robusto, validación segura de entrada, y limpieza automática de imágenes obsoletas, reduciendo riesgo operacional y ahorrando tiempo. El helper perfecto para mantener tu homelab actualizado sin complicaciones.

Propuesta clave: Bash script automation. Docker Compose update workflow. Asume estructura $HOME/docker//. Pull images from registry. Restart containers with up -d. Check errors every step. Prune obsolete images cleanup. User-friendly (interactive or argument mode). Input validation (prevent path traversal). Secure options (set -uo pipefail). Intuitive console output with emoji. Idempotent (safe to run multiple times). Production-ready. Works any user (personaliza paths con $HOME). No external dependencies (pure bash + docker CLI). Typical homelab usage: cron jobs (automated updates), manual runs (one-off container update). Example: ./update-container.sh authentik updates server + worker + postgres in one go. Error at any step halts execution, prevents broken state.

Para homelabs + sysadmin: Mantener contenedores actualizados. Automatizar updates. Reducir riesgo. Cleanup. Sin stress.

¿Cómo funciona update-container.sh?

El script ejecuta 5 pasos principales en orden. Si cualquier paso falla, se detiene inmediatamente.

1. Obtener nombre contenedor

Modo 1 (interactivo): Si ejecutas ./update-container.sh sin argumentos, el script pide el nombre por teclado con prompt.

Modo 2 (argumento): Si ejecutas ./update-container.sh authentik, usa "authentik" directamente.

if [ $# -ge 1 ]; then micontenedor="$1" else read -rp "Por favor, introduce el nombre del contenedor: " micontenedor fi

2. Validación de entrada

Previene path traversal attacks (ej: ../../../etc/passwd) y rutas raras. Solo permite nombres simples sin barras ni ../.

if [[ -z "$micontenedor" || "$micontenedor" == *..* || "$micontenedor" == */* ]]; then echo "❌ Nombre de contenedor no válido: '$micontenedor'" >&2 exit 1 fi

3. Verificar directorio existe

Asume estructura: $HOME/docker//. Si no existe, sale con error antes de hacer cambios.

contenedor_dir="${DOCKER_BASE_DIR}/${micontenedor}" if [ ! -d "$contenedor_dir" ]; then echo "❌ El directorio $contenedor_dir no existe." >&2 exit 1 fi

4. Cambiar directorio

Navega a $HOME/docker// donde está el docker-compose.yml.

if ! cd "$contenedor_dir"; then echo "❌ No se pudo cambiar al directorio $contenedor_dir." >&2 exit 1 fi

5. Pull imágenes nuevas

Descarga versiones nuevas de imágenes Docker desde registry (Docker Hub, GHCR, etc). Si falla, script se detiene.

echo "📥 Descargando imágenes nuevas..." if ! docker compose pull; then echo "❌ Hubo un problema al ejecutar 'docker compose pull'." >&2 exit 1 fi

6. Relanzar contenedores

Ejecuta docker compose up -d. Detiene contenedores viejos, crea nuevos con imágenes actualizadas, levanta en background.

echo "🚀 Levantando el contenedor..." if ! docker compose up -d; then echo "❌ Hubo un problema al ejecutar 'docker compose up -d'." >&2 exit 1 fi

7. Limpieza automática

Ejecuta docker image prune -f al final. Elimina imágenes no usadas (dangling images). Libera espacio automático.

echo "🧹 Eliminando imágenes obsoletas de Docker..." docker image prune -f

Características principales

Modo dual (interactivo + argumento)

Pide nombre si no lo dan. O recibe argumento. Flexible.

Validación segura

Previene path traversal. Solo nombres simples. Input sanitizado.

Error handling robusto

Cada paso validado. Si falla, sale con error. No continúa.

set -uo pipefail

Variables no definidas = error. Pipe falla = script falla.

Pull + Up combo

docker compose pull → docker compose up -d. Actualización completa.

Limpieza automática

docker image prune -f. Elimina images dangling. Libera espacio.

Emoji feedback

📥🚀✅❌🧹. User-friendly console output. Visual progress.

$HOME personalización

$HOME/docker/. Funciona cualquier usuario. No paths hardcodeados.

Idempotente

Correr 2x mismo comando = mismo resultado. Seguro repetir.

Cron-ready

Automatiza updates. Pasa nombre argumento. Cron job friendly.

Instalación y setup

Paso 1: Descargar script

# Opción A: Descarga directa cd ~ wget https://github.com/JLalib/update-container.sh # Opción B: Copiar manualmente # Copia el contenido update-container.sh a un archivo. #!/bin/bash # # update-container.sh # Actualiza y relanza un contenedor Docker Compose ubicado en $HOME/docker/ # (usa el home del usuario que ejecuta el script, sea quien sea) # # Uso: # ./update-container.sh -> pide el nombre por teclado # ./update-container.sh nombre -> lo recibe como argumento set -uo pipefail # -u: variables no definidas dan error | pipefail: falla si falla algún comando en un pipe # (Nota: no usamos -e a propósito, porque queremos capturar y reportar errores nosotros mismos) DOCKER_BASE_DIR="$HOME/docker" # --- 1. Obtener el nombre del contenedor (por argumento o interactivo) --- if [ $# -ge 1 ]; then micontenedor="$1" else read -rp "Por favor, introduce el nombre del contenedor: " micontenedor fi # Validación básica: que no esté vacío y no contenga rutas raras (../ etc.) if [[ -z "$micontenedor" || "$micontenedor" == *..* || "$micontenedor" == */* ]]; then echo "❌ Nombre de contenedor no válido: '$micontenedor'" >&2 exit 1 fi contenedor_dir="${DOCKER_BASE_DIR}/${micontenedor}" echo "El nombre del contenedor es: $micontenedor" # --- 2. Verificar que el directorio existe --- if [ ! -d "$contenedor_dir" ]; then echo "❌ El directorio $contenedor_dir no existe." >&2 exit 1 fi # --- 3. Cambiar al directorio --- if ! cd "$contenedor_dir"; then echo "❌ No se pudo cambiar al directorio $contenedor_dir." >&2 exit 1 fi # --- 4. Pull + up, comprobando cada paso por separado --- echo "📥 Descargando imágenes nuevas..." if ! docker compose pull; then echo "❌ Hubo un problema al ejecutar 'docker compose pull'." >&2 exit 1 fi echo "🚀 Levantando el contenedor..." if ! docker compose up -d; then echo "❌ Hubo un problema al ejecutar 'docker compose up -d'." >&2 exit 1 fi echo "✅ Contenedor actualizado y en ejecución." # --- 5. Limpieza de imágenes obsoletas --- echo "🧹 Eliminando imágenes obsoletas de Docker..." docker image prune -f echo "✅ Todo se ha actualizado correctamente."

Paso 2: Hacer ejecutable

chmod +x update-container.sh

Paso 3: Verificar estructura directorio

El script espera esta estructura:

$HOME/docker/ ├── authentik/ │ └── docker-compose.yml ├── dawarich/ │ └── docker-compose.yml ├── heimdall/ │ └── docker-compose.yml └── update-container.sh
💡 Tip: El script busca docker-compose.yml en $HOME/docker//. Si tu estructura es diferente (ej: /opt/docker/), edita DOCKER_BASE_DIR en el script.

Cómo usar update-container.sh

Uso modo interactivo

./update-container.sh # Output: # Por favor, introduce el nombre del contenedor: authentik # El nombre del contenedor es: authentik # 📥 Descargando imágenes nuevas... # (... output docker compose pull ...) # 🚀 Levantando el contenedor... # (... output docker compose up -d ...) # ✅ Contenedor actualizado y en ejecución. # 🧹 Eliminando imágenes obsoletas de Docker... # ✅ Todo se ha actualizado correctamente.

Uso con argumento

./update-container.sh authentik # El nombre del contenedor es: authentik # 📥 Descargando imágenes nuevas... # (... rest igual ...)

Uso en cron (automatizado)

Actualiza contenedores automáticamente según cronograma:

# Edita crontab crontab -e # Actualizar authentik cada domingo a las 3am 0 3 * * 0 /home/usuario/update-container.sh authentik # Actualizar dawarich cada lunes a las 4am 0 4 * * 1 /home/usuario/update-container.sh dawarich # Actualizar todos los contenedores (script manual con loop) 0 2 * * 0 for app in authentik dawarich heimdall; do /home/usuario/update-container.sh $app; done
⚠️ Cron logs: Cron redirige output a mail. Para debugging, usa:
0 3 * * 0 /home/usuario/update-container.sh authentik >> /var/log/update-container.log 2>&1

Análisis código línea por línea

Shebang + comentarios iniciales

#!/bin/bash # Especifica usar bash (no sh, que podría ser dash)

set -uo pipefail (línea 10)

set -uo pipefail # -u: undefined variables error (previene $typo) # -o pipefail: if any command in pipe fails, whole pipe fails # Example: cat missing.txt | sort → exit 1 (no solo sort éxito) # -e NO usado porque queremos error handling manual

Variable DOCKER_BASE_DIR (línea 13)

DOCKER_BASE_DIR="$HOME/docker" # $HOME = home usuario (flexible, no /home/usuario hardcoded) # Estructura esperada: $HOME/docker/authentik/docker-compose.yml

Obtener nombre contenedor (línea 16-19)

if [ $# -ge 1 ]; then micontenedor="$1" else read -rp "Por favor, introduce el nombre del contenedor: " micontenedor fi # $# = number of arguments passed to script # $1 = first argument # -r en read: raw input (no interpreta backslashes) # -p "prompt": muestra prompt antes de esperar input

Validación entrada (línea 21-25)

if [[ -z "$micontenedor" || "$micontenedor" == *..* || "$micontenedor" == */* ]]; then echo "❌ Nombre de contenedor no válido: '$micontenedor'" >&2 exit 1 fi # -z: string is empty # *..* : contains ".." (path traversal prevention) # */: contains "/" (path traversal prevention) # >&2: redirect to stderr (errors to stderr, not stdout) # exit 1: exit with error code 1

Verificar directorio existe (línea 27-30)

contenedor_dir="${DOCKER_BASE_DIR}/${micontenedor}" if [ ! -d "$contenedor_dir" ]; then echo "❌ El directorio $contenedor_dir no existe." >&2 exit 1 fi # -d: test if directory exists # ! -d: test if directory does NOT exist

Cambiar directorio con error check (línea 32-36)

if ! cd "$contenedor_dir"; then echo "❌ No se pudo cambiar al directorio $contenedor_dir." >&2 exit 1 fi # ! cd: if cd command fails (permission denied, etc) # Crucial: si cd falla, no continuamos (podrías borrar el home!)

Pull imágenes con error check (línea 38-43)

echo "📥 Descargando imágenes nuevas..." if ! docker compose pull; then echo "❌ Hubo un problema al ejecutar 'docker compose pull'." >&2 exit 1 fi # docker compose pull: descarga todas imágenes del compose # Asume docker-compose.yml en directorio actual # Si falla (network, registry error), sale con exit 1

Up -d con error check (línea 45-50)

echo "🚀 Levantando el contenedor..." if ! docker compose up -d; then echo "❌ Hubo un problema al ejecutar 'docker compose up -d'." >&2 exit 1 fi # docker compose up -d: detiene viejos, crea nuevos, levanta background # -d: detached mode (no bloquea terminal)

Limpieza imágenes (línea 52-54)

echo "🧹 Eliminando imágenes obsoletas de Docker..." docker image prune -f # docker image prune: elimina untagged/dangling images # -f: force (no pide confirmación) # Nota: NO es if !, es intentional (prune puede fallar OK)

Consideraciones de seguridad

Path traversal prevention

Script valida entrada para prevenir ataques path traversal:

# ❌ Atacante intenta: ./update-container.sh ../../../etc/passwd # ✅ Script rechaza (contiene /)

Error stderr redirection

Errores van a stderr (>&2), no stdout. Importante para pipes y logging:

./update-container.sh authentik 2>errors.log # Captura solo errores en errors.log

Variable quoting

Todas variables quoted "$var". Previene word splitting:

# ❌ Peligroso (espacios en path causan problemas) cd $contenedor_dir # ✅ Seguro cd "$contenedor_dir"

Exit codes

Script retorna 1 on error, 0 on success. Importante para scripts/cron:

./update-container.sh authentik echo $? # 0 = success, 1 = error

Casos de uso reales

  • Manual update: Un contenedor rápido: ./update-container.sh authentik
  • Cron automated: Updates nocturnos: cron ejecuta script cada semana.
  • Batch updates: Loop actualiza múltiples contenedores: for app in authentik dawarich heimdall; do ./update-container.sh $app; done
  • Backup antes update: docker compose exec postgres pg_dump > backup.sql && ./update-container.sh dawarich
  • Monitoring: Cron logs a file, monitorea errores con alertas.

Troubleshooting y debugging

Problema: "El directorio no existe"

Verifica estructura $HOME/docker//:

ls -la ~/docker/authentik/ # Debería ver docker-compose.yml

Problema: "docker compose command not found"

Script espera docker compose (v2). Si tienes docker-compose (v1):

docker compose version # Si v1, edita script línea 40 y 46: # Cambiar "docker compose" a "docker-compose"

Problema: "Permission denied"

Asegúrate script es ejecutable:

chmod +x update-container.sh

Problema: Cron no corre script

Usa path absoluto en cron:

# ❌ Incorrecto en cron 0 3 * * 0 ./update-container.sh authentik # ✅ Correcto en cron (path absoluto) 0 3 * * 0 /home/usuario/update-container.sh authentik

Debugging verbose

Agrega set -x al inicio para tracing:

set -uo pipefail set -x # Print every command before executing

Mejoras posibles (extensiones)

Verificar cambios antes de actualizar

# Agregar entre pull y up: docker compose config > /tmp/config-new.json # Si config cambió significativamente, pedir confirmación

Rollback automático

Si up falla, volver a versión anterior con tag específico.

Notificaciones

Enviar email o Telegram si falla update:

if ! docker compose pull; then # send alert exit 1 fi

Multi-contenedor

Script versión que actualiza TODOS contenedores sin argumento.


Comentarios

Entradas populares de este blog

Cómo Instalar y configurar SERVIDOR VPN WIREGUARD en MIKROTIK 🔐 #VPN #Wireguard #Mikrotik #RouterOS

Cómo instalar y configurar DSM SYNOLOGY 7.2.2 en PC | Guía completa, instalación, RAID 1, SMB

Cómo INSTALAR y CONFIGURAR OpenVPN en MIKROTIK. Guía completa paso a paso.