¡Desplega tu aplicación con estilo usando Bash Scripting!
Mastering Automation, One Script at a Time: The Series
Hoy te traigo una guía sobre un poderoso script en Bash que te permitirá automatizar la construcción y despliegue de una aplicación Node.js, ya sea ejecutándola localmente o dentro de un contenedor Docker. Además, te enseñaré algunos tips and tricks de buenas prácticas para mejorar tu desarrollo en Bash.
Este script forma parte del proyecto alojado en mi repositorio de GitHub. ¡Vamos a explorarlo y aprender algunos trucos para hacer que tus scripts Bash sean más robustos y eficientes!
¿Qué hace este script?
Este script es un ejemplo perfecto de cómo escribir código en Bash de manera organizada y robusta. Incluye funciones útiles para:
Verificar herramientas instaladas: Asegura que todas las dependencias necesarias (como
node
,npm
,jq
,git
, e inclusodocker
en modo contenedor) estén presentes.Obtener información del repositorio Git: Como el nombre del repositorio, la rama activa, y el nombre de la imagen Docker.
Leer la versión de la aplicación desde
package.json
: Esto ayuda a versionar las imágenes Docker correctamente.Construir y ejecutar un contenedor Docker: Crea un
Dockerfile
de forma dinámica y luego ejecuta el contenedor de la aplicación.Ejecutar localmente: Si prefieres probar tu aplicación en tu máquina sin usar Docker, ¡también lo cubre!
Detener la aplicación: Tanto en local como en Docker.
Código:
#!/bin/bash
# Habilitar modo estricto y debugging
set -euo pipefail
#set -x
IFS=$'\n\t'
TEMP_DIR="tempdir"
PORT=3000
DOCKERFILE_PATH="Dockerfile"
PID_FILE="/tmp/node-server-app.pid"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
NC='\033[0m'
# Banner llamativo
print_banner() {
echo -e "${BLUE}"
echo "##############################################"
echo " 🚀 Bienvenido al RoxsApp Deployer! 🚀 "
echo " Automatizando todo con estilo... "
echo " MODO:$EXECUTION_MODE "
echo "###############################################"
echo -e "${NC}"
}
# Función para imprimir mensajes coloreados
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# .......
Puedes encontrar el código completo en mi repositorio en GitHub.
¿Cómo Funciona el Script?
Este script en Bash está diseñado para automatizar el proceso de despliegue de una aplicación Node.js, permitiendo ejecutarla de manera local o dentro de un contenedor Docker. A continuación, te explico cada paso clave del funcionamiento:
Configuración Inicial:
El script activa el modo estricto (
set -euo pipefail
) para asegurar una mejor gestión de errores.Se definen variables de entorno importantes, como el directorio temporal (
TEMP_DIR
), el puerto de la aplicación (PORT
), el archivoDockerfile
y otros parámetros necesarios para el despliegue.
Modos de Ejecución:
LOCAL: Ejecuta la aplicación Node.js en tu máquina local.
DOCKER: Construye y ejecuta la aplicación dentro de un contenedor Docker.
STOP: Detiene la aplicación, ya sea que esté corriendo localmente o en Docker.
Funciones Clave:
check_all_tools
: Verifica que todas las herramientas necesarias (Node.js, npm, jq, git) estén instaladas antes de proceder.get_git_info
: Obtiene información del repositorio y rama actual, generando nombres para la imagen Docker y el contenedor basados en estos datos.read_app_version
: Lee la versión de la aplicación desde el archivopackage.json
para etiquetar la imagen Docker con la versión correcta.create_dockerfile
: Genera dinámicamente un archivoDockerfile
que especifica cómo construir la imagen de la aplicación Node.js.docker_build_and_run
: Construye la imagen Docker y la despliega en un contenedor.run_locally
: Ejecuta la aplicación localmente en el puerto especificado y administra los procesos activos.
Flujo de Trabajo:
Dependiendo del modo seleccionado (LOCAL o DOCKER), el script realiza los siguientes pasos:
Verifica las herramientas necesarias.
Obtiene la información del repositorio y la versión de la aplicación.
En modo DOCKER, genera un
Dockerfile
, construye la imagen y despliega un contenedor.En modo LOCAL, instala las dependencias de npm y ejecuta la aplicación directamente en el puerto especificado.
Si la aplicación ya está corriendo en el puerto designado, el script puede detener el proceso anterior antes de iniciar uno nuevo.
Limpieza y Finalización:
- Al finalizar, se realiza una limpieza de recursos temporales para garantizar que no queden archivos ni contenedores innecesarios ocupando espacio.
¿Cómo Ejecutar el Script?
Sigue estos pasos para ejecutar el script y automatizar el despliegue de tu aplicación Node.js, ya sea localmente o dentro de un contenedor Docker.
1. Clona el Repositorio
Primero, clona el repositorio que contiene el script y la configuración necesaria:
branch devops-cars-management-system
git clone -b devops-cars-management-system https://github.com/roxsross/roxs-projects-blog.git
cd roxs-projects-blog
2. Haz el Script Ejecutable
Si aún no lo has hecho, asegúrate de que el archivo del script tenga permisos de ejecución:
chmod +x deploy.sh
3. Modos de Ejecución del Script
El script ofrece tres modos de ejecución: LOCAL
, DOCKER
, y STOP
. A continuación te explico cómo usar cada uno:
Ejecución Local
Para ejecutar la aplicación Node.js localmente, ejecuta el siguiente comando:./deploy.sh LOCAL
Esto iniciará la aplicación en tu máquina usando el puerto configurado (por defecto el puerto
3000
). Si deseas cambiar el puerto, puedes hacerlo editando la variablePORT
en el script.- 💡Version de Node Recomendada superior a v18
- ℹTe recomiendo usar el Gestor NVM para trabajar con multiples versiones de node su instalación es muy fácil https://github.com/nvm-sh/nvm
- 💡Importante si ejecutas el script LOCAL ten en cuenta que si lo corres en Ubuntu debes tener instalado estos paquetes
sudo apt update sudo apt install build-essential python3 make
Ejecución en Docker
Si prefieres desplegar la aplicación dentro de un contenedor Docker, usa el siguiente comando:./deploy.sh DOCKER
El script construirá la imagen Docker utilizando el
Dockerfile
generado automáticamente y ejecutará la aplicación en un contenedor.Detener la Aplicación
Para detener la aplicación, ya sea que esté corriendo localmente o en Docker, utiliza:./deploy.sh STOP
Esto se encargará de matar el proceso local o detener el contenedor Docker que esté en ejecución.
4. Verificar el Despliegue
Dependiendo del modo de ejecución que elijas, puedes acceder a la aplicación desde el navegador usando:
Local:
Si ejecutaste la aplicación localmente, ve ahttp://localhost:3000
(o el puerto que hayas configurado).Docker:
Si utilizaste Docker, abre el navegador y accede ahttp://localhost:<puerto>
para verificar que el contenedor se está ejecutando correctamente.
Script en Acción
Buenas prácticas y tips
1. Usa set -euo pipefail
y IFS=$'\n\t'
para evitar errores ocultos
set -euo pipefail
: Habilitar este modo es clave para evitar que el script continúe si ocurre un error. De esta forma, el script se detiene si un comando falla (-e
), si intentas usar una variable no declarada (-u
), o si algún comando dentro de una pipeline falla (pipefail
).IFS=$'\n\t'
: Esto ajusta el Internal Field Separator para que los espacios en blanco no separen elementos inesperadamente. Es especialmente útil cuando trabajas con archivos o variables que contienen saltos de línea.
Tip: No olvides incluir este ajuste en tus scripts para prevenir errores difíciles de detectar.
2. Colorea tus salidas para mejorar la legibilidad
- Este script utiliza variables de color como
RED
,GREEN
,YELLOW
,BLUE
,NC
para imprimir mensajes coloridos. Esto hace que sea más fácil identificar errores, advertencias o mensajes de éxito.
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
Tip: Añadir colores es una excelente manera de hacer que tu script sea más intuitivo. Úsalo especialmente cuando haya errores, advertencias o información clave.
3. Verifica dependencias antes de continuar
check_tool
es una función que comprueba si las herramientas necesarias están instaladas antes de proceder. Si alguna no está, el script muestra un mensaje de error y sale.
check_tool() {
if ! command -v "$1" &>/dev/null; then
print_message "$RED" "Error: '$1' no está instalado."
exit 1
fi
}
Tip: Siempre asegúrate de que todas las dependencias estén disponibles antes de ejecutar el código principal de tu script. Esto evitará problemas inesperados durante la ejecución.
4. Divide tu script en funciones reutilizables
- Agrupar tareas en funciones como
create_dockerfile
,docker_build_and_run
,run_locally
ystop_node_server
ayuda a mantener el código organizado y facilita el mantenimiento.
create_dockerfile() {
cat <<EOF > "$TEMP_DIR/$DOCKERFILE_PATH"
FROM node:18-alpine
LABEL org.opencontainers.image.authors="RoxsRoss"
RUN apk add --no-cache python3 make g++
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE $PORT
CMD ["npm", "start"]
EOF
}
Tip: Cada función debe cumplir un propósito claro y específico. Esto no solo mejora la legibilidad del código, sino que también facilita la depuración.
5. Control de errores y salida temprana
- A lo largo del script, hay comprobaciones continuas de errores con el uso de
if
y el comandoexit 1
si algo falla. Por ejemplo, si el archivopackage.json
no existe o no puede leerse:
if [ ! -f "package.json" ]; then
print_message "$RED" "Error: 'package.json' no encontrado."
exit 1
fi
Tip: Controlar errores y salir temprano es esencial en scripts Bash para evitar que el flujo continúe cuando las condiciones no son las correctas.
6. Automatiza el manejo de procesos
- El script incluye funciones para detener procesos locales o contenedores en ejecución, lo que es clave para limpiar después de cada ejecución:
stop_node_server() {
PIDS=$(lsof -t -i:"$PORT")
if [ -n "$PIDS" ]; then
echo "$PIDS" | xargs kill -9
fi
}
Tip: Asegúrate de limpiar los procesos o contenedores para evitar que el puerto quede bloqueado o que queden recursos innecesarios ejecutándose.
7. Usa trap
para manejar la limpieza al salir
- Este script maneja la limpieza de recursos (como directorios temporales) usando
trap
. Esto asegura que, incluso si el script es interrumpido, la limpieza ocurra:
trap 'cleanup; show_running_processes; exit 0' EXIT
Tip: Implementar un trap para la limpieza es una buena práctica en Bash scripting, especialmente cuando se trabaja con archivos o procesos temporales.
8. Desactiva debugging para producción, pero habilítalo durante el desarrollo
- El script incluye
set -x
, que está comentado, pero se puede habilitar para hacer un debugging más sencillo:
#set -x
Tip: Habilita el modo de debugging (set -x
) cuando estés depurando un problema y desactívalo en producción para mantener los logs limpios.
Desafio
Crear un script de automatización para un pipeline de CI/CD que prepare, construya y despliegue una aplicación web simple.
Requisitos
Script de Automatización
Crea un script en Bash llamado
ci_cd_
automation.sh
.El script debe realizar las siguientes tareas:
a. Obtener la versión actual del proyecto (de package.json, CHANGELOG.md o Git tags).
b. Obtener el nombre del repositorio y la rama actual.
c. Construir el nombre de la imagen Docker basado en el repositorio y la versión.
d. Obtener información del último commit (autor y correo electrónico).
e. Verificar si las herramientas necesarias (git, docker, jq) están instaladas.
Revisa el Repositorio Pasos a Seguir
Conclusión
Este script en Bash es un excelente ejemplo de cómo automatizar tareas comunes en el ciclo de vida de desarrollo de una aplicación, desde la verificación de dependencias hasta la ejecución de aplicaciones localmente o en contenedores. Usar funciones modulares, manejo adecuado de errores, y técnicas avanzadas como trap
y set -euo pipefail
garantiza que tu script sea seguro, escalable y fácil de mantener.
Implementar estos tips y seguir buenas prácticas de scripting te permitirá mejorar tus habilidades y evitar sorpresas inesperadas en producción. ¡Pruébalo y mejora la automatización de tus despliegues!