Introducción
En este laboratorio, aprenderá los fundamentos del despliegue y la automatización de contenedores de Red Hat Enterprise Linux (RHEL) 9 utilizando Docker. Los despliegues modernos nativos de la nube dependen cada vez más de entornos RHEL en contenedores en lugar de máquinas virtuales tradicionales. Comenzará explorando las Imágenes Base Universales (UBI, por sus siglas en inglés) de Red Hat, que proporcionan entornos RHEL de nivel empresarial en formato de contenedor.
Examinará cómo los conceptos tradicionales de Kickstart se traducen a la automatización de contenedores, creará Dockerfiles personalizados que reflejen las configuraciones de instalación y construirá scripts de despliegue automatizados. Al final de este laboratorio, comprenderá cómo desplegar contenedores RHEL de manera eficiente y automatizar el proceso para despliegues consistentes y repetibles en entornos de nube modernos.
Explorar las Imágenes Base Universales (UBI) de Red Hat
En este paso, explorará las Imágenes Base Universales (UBI, por sus siglas en inglés) de Red Hat, que son imágenes de contenedor de nivel empresarial basadas en RHEL. A diferencia de las instalaciones tradicionales de RHEL que requieren máquinas virtuales completas, las imágenes UBI proporcionan entornos RHEL en contenedores ligeros y portátiles. Estas imágenes son de libre redistribución y están diseñadas para aplicaciones modernas nativas de la nube.
Red Hat proporciona varias variantes de UBI optimizadas para diferentes casos de uso. La imagen redhat/ubi9 proporciona un entorno de contenedor completo basado en RHEL con el gestor de paquetes dnf, lo que la hace adecuada para aplicaciones que requieren instalación de software y automatización del sistema.
Primero, examinemos la plantilla de configuración de contenedor de Red Hat que se ha preparado para este laboratorio. Este archivo demuestra cómo los conceptos tradicionales de Kickstart se traducen a entornos de contenedor.
sudo cat /etc/labex/rhel-container-config.cfg
Verá una salida que muestra una configuración al estilo Dockerfile que refleja los conceptos de instalación tradicionales:
## RHEL Container Configuration Template
## Based on traditional Kickstart concepts adapted for containers
## Base image specification
FROM redhat/ubi9
## System locale and timezone
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
## User configuration
ENV CONTAINER_USER=labex
ENV ROOT_PASSWORD=redhat
## Package installation
## Packages: httpd, curl (container-appropriate equivalents)
RUN dnf install -y --allowerasing httpd curl && \
dnf clean all
## Service configuration
EXPOSE 80
## Startup command
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
Ahora, exploremos las imágenes UBI de Red Hat disponibles. Primero, compruebe si Docker se está ejecutando y es accesible:
docker --version
Descargue la imagen Red Hat UBI 9, que proporciona un entorno de contenedor completo basado en RHEL:
docker pull redhat/ubi9
Debería ver una salida similar a:
Using default tag: latest
latest: Pulling from redhat/ubi9
Digest: sha256:...
Status: Downloaded newer image for redhat/ubi9:latest
docker.io/redhat/ubi9:latest
Enumere las imágenes descargadas para confirmar que la descarga fue exitosa:
docker images redhat/ubi9
La salida mostrará detalles sobre la imagen:
REPOSITORY TAG IMAGE ID CREATED SIZE
redhat/ubi9 latest b1c2d3e4f5g6 5 days ago 216MB
Ahora, ejecutemos un contenedor básico para explorar el entorno RHEL:
docker run -it --rm redhat/ubi9 /bin/bash
Dentro del contenedor, explore el entorno RHEL comprobando la versión del sistema operativo:
cat /etc/redhat-release
Debería ver algo como:
Red Hat Enterprise Linux release 9.6 (Plow)
Compruebe el gestor de paquetes disponible:
dnf --version
Salga del contenedor escribiendo:
exit
Copie la configuración de la plantilla a su directorio de proyecto para personalizarla:
sudo cp /etc/labex/rhel-container-config.cfg ~/project/rhel-container.dockerfile
sudo chown labex:labex ~/project/rhel-container.dockerfile
Verifique que el archivo se copió correctamente:
ls -l ~/project/rhel-container.dockerfile
Ahora ha explorado con éxito las imágenes UBI de Red Hat y está listo para crear configuraciones de contenedor personalizadas en el siguiente paso.
Crear una Configuración de Contenedor RHEL Personalizada
En este paso, creará un Dockerfile personalizado basado en la imagen UBI de Red Hat. Este proceso refleja cómo personalizaría un archivo Kickstart para instalaciones automatizadas, pero adaptado para entornos de contenedor. El Dockerfile sirve como plantilla de automatización para crear despliegues de contenedores RHEL consistentes.
Primero, asegúrese de estar en su directorio de proyecto:
cd ~/project
Cree un nuevo Dockerfile, más específico, para nuestro despliegue de contenedor RHEL automatizado:
cp rhel-container.dockerfile rhel9-automated.dockerfile
Verifique que ambos archivos existan:
ls -l *.dockerfile
Debería ver ambos archivos:
-rw-r--r--. 1 labex labex 423 Jul 22 10:30 rhel-container.dockerfile
-rw-r--r--. 1 labex labex 423 Jul 22 10:35 rhel9-automated.dockerfile
Ahora, abra el nuevo Dockerfile para examinar su estructura antes de la personalización:
nano rhel9-automated.dockerfile
Dentro del archivo, verá el equivalente en contenedor de las directivas Kickstart:
- Directiva FROM: Especifica la imagen RHEL base (equivalente al medio de instalación)
- Directivas ENV: Establecen variables de entorno (equivalentes a la configuración del sistema)
- Directivas RUN: Ejecutan comandos durante la construcción de la imagen (equivalente a la instalación de paquetes)
- EXPOSE y CMD: Configuran servicios e inicio (equivalente a la configuración del servicio)
Por ahora, simplemente salga del editor presionando Ctrl+X para proceder al paso de personalización.
Comprender esta estructura lo prepara para el siguiente paso, donde personalizará la configuración del contenedor para satisfacer los requisitos específicos de despliegue, tal como personalizaría un archivo Kickstart para instalaciones automatizadas de VM.
Personalizar la Configuración del Contenedor para la Implementación Automatizada
En este paso, reemplazará el contenido de rhel9-automated.dockerfile con una configuración personalizada para el despliegue automatizado de contenedores RHEL. Este proceso es similar a la personalización de un archivo Kickstart, pero utiliza el enfoque declarativo de Docker para definir el entorno y los servicios del contenedor.
Primero, asegúrese de estar en el directorio del proyecto:
cd ~/project
Ahora, cree el Dockerfile personalizado completo reemplazando todo el contenido de rhel9-automated.dockerfile:
cat > rhel9-automated.dockerfile << 'EOF'
## RHEL 9 Automated Container Deployment
## Based on Red Hat Universal Base Image 9
FROM redhat/ubi9:latest
## Container metadata
LABEL maintainer="LabEx Admin"
LABEL description="Automated RHEL 9 container with web services"
LABEL version="1.0"
## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001
## Package installation and system configuration
RUN dnf update -y \
&& dnf install -y --allowerasing \
httpd \
curl \
tar \
gzip \
&& dnf clean all \
&& rm -rf /var/cache/dnf
## Create non-root user for security
RUN useradd -u ${CONTAINER_UID} -m -s /bin/bash ${CONTAINER_USER} \
&& echo "${CONTAINER_USER}:labex" | chpasswd
## Configure Apache for container environment
RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
&& chown -R ${CONTAINER_USER}:${CONTAINER_USER} /var/log/httpd /var/run/httpd
## Create startup script
RUN echo '#!/bin/bash' > /start.sh \
&& echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh \
&& echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh \
&& echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh \
&& chmod +x /start.sh
## Switch to non-root user
USER ${CONTAINER_USER}
## Expose port and define startup
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/ || exit 1
CMD ["/start.sh"]
EOF
Ahora, examinemos la estructura de este Dockerfile personalizado y comprendamos cómo cada sección cumple el mismo propósito que las diferentes partes de una configuración Kickstart:
1. Sección de Imagen Base y Metadatos:
## RHEL 9 Automated Container Deployment
## Based on Red Hat Universal Base Image 9
FROM redhat/ubi9:latest
## Container metadata
LABEL maintainer="LabEx Admin"
LABEL description="Automated RHEL 9 container with web services"
LABEL version="1.0"
Esta sección es equivalente a especificar el medio de instalación y la información básica del sistema en un archivo Kickstart. La directiva FROM especifica nuestra imagen RHEL base, mientras que las directivas LABEL proporcionan metadatos sobre el contenedor.
2. Configuración del Entorno:
## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001
Esto es similar a las directivas timezone y lang en los archivos Kickstart. Estamos configurando la configuración regional del sistema, la zona horaria y definiendo variables para la creación de usuarios.
3. Instalación de Paquetes:
## Package installation and system configuration
RUN dnf update -y \
&& dnf install -y --allowerasing \
httpd \
curl \
tar \
gzip \
&& dnf clean all \
&& rm -rf /var/cache/dnf
Esta sección realiza la misma función que la sección %packages en Kickstart. Actualizamos el sistema, instalamos los paquetes requeridos usando --allowerasing para manejar conflictos y limpiamos las cachés de paquetes para reducir el tamaño de la imagen.
4. Configuración de Usuario y Seguridad:
## Create non-root user for security
RUN useradd -u ${CONTAINER_UID} -m -s /bin/bash ${CONTAINER_USER} \
&& echo "${CONTAINER_USER}:labex" | chpasswd
## Configure Apache for container environment
RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
&& chown -R ${CONTAINER_USER}:${CONTAINER_USER} /var/log/httpd /var/run/httpd
Esto refleja la directiva user y la configuración posterior a la instalación en Kickstart. Creamos un usuario no root para la seguridad y configuramos Apache para que se ejecute en el puerto 8080 (adecuado para entornos de contenedor).
5. Configuración de Inicio:
## Create startup script
RUN echo '#!/bin/bash' > /start.sh \
&& echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh \
&& echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh \
&& echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh \
&& chmod +x /start.sh
## Switch to non-root user
USER ${CONTAINER_USER}
## Expose port and define startup
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/ || exit 1
CMD ["/start.sh"]
Esta sección final es equivalente a la sección %post y la configuración del servicio en Kickstart. Creamos un script de inicio, cambiamos al usuario no root, exponemos el puerto del servicio web, definimos comprobaciones de estado y especificamos el comando de inicio del contenedor.
Verifique que el nuevo Dockerfile se creó correctamente:
cat rhel9-automated.dockerfile
Debería ver el contenido completo del Dockerfile que demuestra cómo los conceptos tradicionales de automatización Kickstart se traducen a despliegues RHEL modernos basados en contenedores.
Validar la Configuración del Contenedor y Construir la Imagen
En este paso, validará su Dockerfile personalizado y construirá la imagen del contenedor RHEL. Este proceso es similar a la validación de un archivo Kickstart con ksvalidator, pero utiliza la validación integrada de Docker durante el proceso de construcción. Docker verificará la sintaxis e intentará ejecutar cada instrucción, proporcionando retroalimentación inmediata sobre cualquier problema.
Primero, asegúrese de estar en el directorio del proyecto donde se encuentra su Dockerfile:
cd ~/project
Antes de construir, realicemos una verificación básica de la sintaxis examinando la estructura del Dockerfile. Docker proporciona una forma de validar la sintaxis básica sin construir:
docker build --no-cache --progress=plain -f rhel9-automated.dockerfile -t rhel9-test:validation . --target ""
Sin embargo, la validación más efectiva es construir realmente la imagen. Si hay errores de sintaxis o problemas con los comandos, Docker los informará durante el proceso de construcción. Tenga en cuenta que usamos la bandera --allowerasing con dnf install para manejar los conflictos de paquetes entre curl y curl-minimal que existen en la imagen UBI9 base:
docker build -t rhel9-automated:latest -f rhel9-automated.dockerfile .
Debería ver la salida que muestra cada paso del proceso de construcción:
[+] Building 45.2s (12/12) FINISHED
=> [internal] load build definition from rhel9-automated.dockerfile
=> => transferring dockerfile: 1.23kB
=> [internal] load .dockerignore
=> => transferring context: 2B
=> [internal] load metadata for docker.io/redhat/ubi9:latest
=> [1/8] FROM docker.io/redhat/ubi9:latest@sha256:...
=> [2/8] RUN dnf update -y && dnf install -y --allowerasing httpd curl tar gzip && dnf clean all && rm -rf /var/cache/dnf
=> [3/8] RUN useradd -u 1001 -m -s /bin/bash labex && echo "labex:labex" | chpasswd
=> [4/8] RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf && chown -R labex:labex /var/log/httpd /var/run/httpd
=> [5/8] RUN echo '#!/bin/bash' > /start.sh && echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh && echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh && echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh && chmod +x /start.sh
=> [6/8] USER labex
=> exporting to image
=> => exporting layers
=> => writing image sha256:a1b2c3d4e5f6...
=> => naming to docker.io/library/rhel9-automated:latest
Si la construcción se completa con éxito, significa que la sintaxis de su Dockerfile es correcta y todos los comandos se ejecutaron correctamente. Es posible que vea algunos mensajes de advertencia sobre la configuración regional y la gestión de suscripciones durante el proceso de construcción; estos son normales para los contenedores UBI y no afectan la funcionalidad.
Verifique que la imagen se haya creado:
docker images rhel9-automated
Debería ver su imagen recién construida:
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel9-automated latest a1b2c3d4e5f6 2 minutes ago 280MB
Ahora, probemos el contenedor para asegurarnos de que funciona como se espera. Ejecute el contenedor en modo desasociado:
docker run -d --name rhel9-test -p 8080:8080 rhel9-automated:latest
Verifique si el contenedor se está ejecutando:
docker ps
Debería ver su contenedor en la lista:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 rhel9-automated:latest "/start.sh" 30 seconds ago Up 30 seconds 0.0.0.0:8080->8080/tcp rhel9-test
Pruebe el servicio web haciendo una solicitud al contenedor:
curl http://localhost:8080
Debería ver la salida HTML de su contenedor RHEL automatizado:
RHEL Container started on Wed Jul 22 14:30:15 UTC 2024
<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>
Finalmente, limpie deteniendo y eliminando el contenedor de prueba:
docker stop rhel9-test
docker rm rhel9-test
Su configuración del contenedor RHEL se ha validado y probado con éxito, lo que demuestra las capacidades de despliegue automatizado.
Crear un Script de Despliegue Automatizado
En este paso, creará un script de automatización que demuestra cómo desplegar contenedores RHEL de forma consistente y repetida. Este script cumple el mismo propósito que el uso de archivos Kickstart para la automatización de VM, pero está adaptado para despliegues RHEL en contenedores. El script se encargará de la construcción de la imagen, el despliegue del contenedor y la verificación básica del estado.
Primero, asegúrese de estar en el directorio de su proyecto:
cd ~/project
Cree un script de automatización de despliegue que imite las capacidades de automatización que lograría con Kickstart y virt-install:
nano deploy-rhel-container.sh
Agregue el siguiente contenido para crear un script de despliegue completo:
#!/bin/bash
## Script de Despliegue Automatizado de Contenedores RHEL
## Este script demuestra la automatización del despliegue de RHEL basado en contenedores
## Similar a la automatización de Kickstart para VM, pero para contenedores
set -e ## Salir ante cualquier error
## Variables de configuración
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
## Códigos de color para la salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## Sin Color
## Función para imprimir salida coloreada
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
## Función para verificar si Docker se está ejecutando
check_docker() {
print_status "Verificando la disponibilidad de Docker..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker no se está ejecutando o no es accesible"
exit 1
fi
print_success "Docker está disponible"
}
## Función para construir la imagen
build_image() {
print_status "Construyendo la imagen del contenedor RHEL..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE' no encontrado"
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "Imagen '${IMAGE_NAME}:${IMAGE_TAG}' construida con éxito"
}
## Función para detener y eliminar el contenedor existente
cleanup_existing() {
print_status "Verificando la existencia de un contenedor..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "Deteniendo y eliminando el contenedor existente '$CONTAINER_NAME'"
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
fi
}
## Función para desplegar el contenedor
deploy_container() {
print_status "Desplegando el contenedor RHEL..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "Contenedor '$CONTAINER_NAME' desplegado con éxito"
}
## Función para verificar el despliegue
verify_deployment() {
print_status "Verificando el despliegue del contenedor..."
## Esperar a que el contenedor se inicie
sleep 5
## Verificar si el contenedor se está ejecutando
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "El contenedor no se está ejecutando"
docker logs "$CONTAINER_NAME"
exit 1
fi
## Verificar si el servicio web está respondiendo
print_status "Probando el servicio web..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "El servicio web está respondiendo"
break
fi
if [ $i -eq 10 ]; then
print_error "El servicio web no responde después de 10 intentos"
exit 1
fi
sleep 2
done
}
## Función para mostrar la información del despliegue
show_deployment_info() {
print_success "=== Despliegue del Contenedor RHEL Completado ==="
echo "Nombre del Contenedor: $CONTAINER_NAME"
echo "Imagen: ${IMAGE_NAME}:${IMAGE_TAG}"
echo "Mapeo de Puertos: ${HOST_PORT}:${CONTAINER_PORT}"
echo "URL de Acceso: http://localhost:${HOST_PORT}"
echo ""
print_status "Estado del Contenedor:"
docker ps | grep "$CONTAINER_NAME"
echo ""
print_status "Contenido de Ejemplo:"
curl -s "http://localhost:${HOST_PORT}" | head -2
}
## Proceso principal de despliegue
main() {
echo "=== Despliegue Automatizado del Contenedor RHEL ==="
echo "Este script automatiza el despliegue del contenedor RHEL"
echo "Similar a la automatización de Kickstart para instalaciones tradicionales"
echo ""
check_docker
build_image
cleanup_existing
deploy_container
verify_deployment
show_deployment_info
print_success "El despliegue automatizado del contenedor RHEL se completó con éxito!"
}
## Manejar los argumentos del script
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "Limpiando el despliegue..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "Limpieza completada"
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "Contenedor no en ejecución"
;;
*)
echo "Uso: $0 [deploy|cleanup|status]"
echo " deploy - Construir y desplegar el contenedor RHEL (por defecto)"
echo " cleanup - Detener el contenedor y eliminar la imagen"
echo " status - Mostrar el estado del contenedor"
exit 1
;;
esac
Guarde el archivo y salga de nano (Ctrl+X, luego Y, luego Enter).
Comprender la Estructura del Script de Despliegue
Antes de ejecutar el script, comprendamos cómo funciona este script de automatización. Esta sección proporciona una explicación detallada de cada componente, lo que facilita que los principiantes comprendan los conceptos de scripting de shell y automatización de contenedores.
Encabezado del Script y Manejo de Errores
#!/bin/bash
set -e ## Salir ante cualquier error
#!/bin/bash: Esto se llama "shebang" - le dice al sistema que use el shell Bash para ejecutar este scriptset -e: Esto hace que el script salga inmediatamente si algún comando falla, asegurando que el script se detenga en el primer error en lugar de continuar con un estado potencialmente roto
Variables de Configuración
## Variables de configuración
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
Estas variables definen todos los parámetros clave para nuestro despliegue. Al colocarlos en la parte superior, podemos modificar fácilmente la configuración del despliegue sin cambiar la lógica del script. Esto es similar a cómo los archivos Kickstart usan parámetros de configuración.
Sistema de Salida Amigable para el Usuario
## Códigos de color para la salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## Sin Color
## Función para imprimir salida coloreada
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
Esto crea un sistema de registro profesional con salida coloreada:
\033[0;31m: Códigos de escape ANSI para colores (31 = rojo, 32 = verde, etc.)echo -e: La bandera-ehabilita la interpretación de escapes de barra invertida para colores$1: Se refiere al primer argumento pasado a la función
Funciones Principales de Despliegue
1. Verificación del Entorno Docker
check_docker() {
print_status "Verificando la disponibilidad de Docker..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker no se está ejecutando o no es accesible"
exit 1
fi
print_success "Docker está disponible"
}
docker info > /dev/null 2>&1: Ejecutadocker infoy redirige tanto la salida (>) como los errores (2>&1) a/dev/null(los descarta)!: Niega el resultado - sidocker infofalla (devuelve un valor distinto de cero), la condición se vuelve verdadera- Esto es equivalente a verificar si la virtualización está disponible en los despliegues tradicionales de VM
2. Función de Construcción de Imagen
build_image() {
print_status "Construyendo la imagen del contenedor RHEL..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE' no encontrado"
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "Imagen '${IMAGE_NAME}:${IMAGE_TAG}' construida con éxito"
}
[ ! -f "$DOCKERFILE" ]: Verifica si el Dockerfile NO existe (!niega,-fverifica la existencia del archivo)docker build -t: Crea una imagen de contenedor con una etiqueta (nombre:versión)- Esto reemplaza el proceso de instalación tradicional desde medios ISO
3. Función de Limpieza
cleanup_existing() {
print_status "Verificando la existencia de un contenedor..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "Deteniendo y eliminando el contenedor existente '$CONTAINER_NAME'"
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
fi
}
docker ps -a | grep -q: Enumera todos los contenedores y busca silenciosamente nuestro nombre de contenedor|| true: Asegura que el comando siempre tenga éxito (devuelve 0) incluso si el contenedor no existe- Esto evita conflictos con despliegues existentes
4. Despliegue del Contenedor
deploy_container() {
print_status "Desplegando el contenedor RHEL..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "Contenedor '$CONTAINER_NAME' desplegado con éxito"
}
-d: Ejecuta el contenedor en modo desasociado (segundo plano)-p "${HOST_PORT}:${CONTAINER_PORT}": Mapea el puerto del host al puerto del contenedor--restart unless-stopped: Reinicia automáticamente el contenedor si se detiene (excepto paradas manuales)\: Carácter de continuación de línea para comandos de varias líneas
5. Verificación del Estado
verify_deployment() {
print_status "Verificando el despliegue del contenedor..."
## Esperar a que el contenedor se inicie
sleep 5
## Verificar si el contenedor se está ejecutando
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "El contenedor no se está ejecutando"
docker logs "$CONTAINER_NAME"
exit 1
fi
## Verificar si el servicio web está respondiendo
print_status "Probando el servicio web..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "El servicio web está respondiendo"
break
fi
if [ $i -eq 10 ]; then
print_error "El servicio web no responde después de 10 intentos"
exit 1
fi
sleep 2
done
}
{1..10}: Expansión de llaves de Bash - crea la secuencia 1, 2, 3... 10curl -s: Modo silencioso de solicitud HTTPbreak: Sale del bucle temprano cuando el servicio responde- Esto implementa un mecanismo de reintento con tiempo de espera
Interfaz de Línea de Comandos
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "Limpiando el despliegue..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "Limpieza completada"
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "Contenedor no en ejecución"
;;
*)
echo "Uso: $0 [deploy|cleanup|status]"
echo " deploy - Construir y desplegar el contenedor RHEL (por defecto)"
echo " cleanup - Detener el contenedor y eliminar la imagen"
echo " status - Mostrar el estado del contenedor"
exit 1
;;
esac
${1:-deploy}: Expansión de parámetros - usa$1(primer argumento) o "deploy" como predeterminado- Declaración
case: Similar a switch/case en otros lenguajes ;;: Termina cada rama del caso$0: Se refiere al nombre del script en sí
Esto crea un script versátil que se puede usar para múltiples operaciones, de manera similar a cómo los administradores de sistemas usan diferentes herramientas para el despliegue, el mantenimiento y la supervisión.
Haga que el script sea ejecutable:
chmod +x deploy-rhel-container.sh
Ahora ejecute el script de despliegue automatizado para ver el proceso de automatización completo:
./deploy-rhel-container.sh
Debería ver la salida que muestra el proceso de despliegue completo:
=== Despliegue Automatizado del Contenedor RHEL ===
Este script automatiza el despliegue del contenedor RHEL
Similar a la automatización de Kickstart para instalaciones tradicionales
[INFO] Verificando la disponibilidad de Docker...
[SUCCESS] Docker está disponible
[INFO] Construyendo la imagen del contenedor RHEL...
[SUCCESS] Imagen 'rhel9-automated:latest' construida con éxito
[INFO] Verificando la existencia de un contenedor...
[INFO] Desplegando el contenedor RHEL...
[SUCCESS] Contenedor 'rhel9-production' desplegado con éxito
[INFO] Verificando el despliegue del contenedor...
[INFO] Probando el servicio web...
[SUCCESS] El servicio web está respondiendo
[SUCCESS] === Despliegue del Contenedor RHEL Completado ===
Nombre del Contenedor: rhel9-production
Imagen: rhel9-automated:latest
Mapeo de Puertos: 8080:8080
URL de Acceso: http://localhost:8080
Pruebe las diferentes opciones del script:
./deploy-rhel-container.sh status
Recorrido de la Ejecución del Script
Cuando ejecuta el script, ejecuta la siguiente secuencia automáticamente:
1. Fase de Validación del Entorno
El script primero verifica si Docker está disponible y es accesible. Esto es crucial porque el despliegue de contenedores requiere un entorno Docker en funcionamiento, de manera similar a cómo el despliegue de VM requiere un hipervisor en funcionamiento.
2. Fase de Construcción de la Imagen
El script construye una nueva imagen de contenedor a partir de su Dockerfile. Este proceso:
- Lee el
rhel9-automated.dockerfile - Descarga la imagen UBI9 base si aún no está presente
- Ejecuta cada instrucción en el Dockerfile
- Crea una nueva imagen etiquetada como
rhel9-automated:latest
3. Fase de Limpieza
Antes de desplegar, el script verifica y elimina cualquier contenedor existente con el mismo nombre. Esto asegura un despliegue limpio sin conflictos de nombres.
4. Fase de Despliegue
El script crea e inicia el nuevo contenedor con:
- Modo desasociado: El contenedor se ejecuta en segundo plano
- Mapeo de puertos: El puerto del host 8080 se mapea al puerto del contenedor 8080
- Política de reinicio: El contenedor se reinicia automáticamente si se detiene inesperadamente
- Contenedor con nombre: Fácil identificación y gestión
5. Fase de Verificación
El script realiza comprobaciones de estado para asegurar un despliegue exitoso:
- Verificación del estado del contenedor: Verifica que el contenedor se esté ejecutando
- Verificación de la disponibilidad del servicio: Prueba la respuesta del servicio HTTP
- Mecanismo de reintento: Intenta hasta 10 veces con intervalos de 2 segundos
- Detección automática de fallos: Sale con error si la verificación falla
6. Fase de Visualización de la Información
Finalmente, el script muestra información completa del despliegue, incluidos los detalles del contenedor, las URL de acceso y el contenido de ejemplo.
Ejemplos de Uso Práctico
Puede usar este script de varias maneras:
Despliegue normal:
./deploy-rhel-container.sh
## o explícitamente
./deploy-rhel-container.sh deploy
Verificar el estado del despliegue:
./deploy-rhel-container.sh status
Limpiar recursos:
./deploy-rhel-container.sh cleanup
Ver la ayuda del script:
./deploy-rhel-container.sh help
Beneficios sobre los Métodos Tradicionales
Este enfoque de automatización proporciona varias ventajas en comparación con los despliegues tradicionales de Kickstart + VM:
- Velocidad: El inicio del contenedor es típicamente 10-100x más rápido que el arranque de la VM
- Eficiencia de recursos: Los contenedores comparten el kernel del host, usando menos memoria y CPU
- Consistencia: El mismo contenedor se ejecuta de forma idéntica en diferentes entornos
- Escalabilidad: Fácil de crear múltiples instancias o escalar horizontalmente
- Portabilidad: Puede ejecutarse en cualquier sistema con Docker instalado
- Control de versiones: Las imágenes de contenedor se pueden versionar y almacenar en registros
Este script de automatización demuestra cómo los despliegues RHEL modernos basados en contenedores pueden lograr el mismo nivel de automatización y consistencia que las instalaciones tradicionales de VM basadas en Kickstart, pero con los beneficios adicionales de la contenedorización, como un despliegue más rápido, una mejor utilización de los recursos y una escalabilidad más fácil en los entornos de nube modernos.
Resumen
En este laboratorio, exploró el enfoque moderno para automatizar los despliegues de Red Hat Enterprise Linux (RHEL) 9 utilizando contenedores Docker e imágenes base universales (UBI) de Red Hat. Aprendió que, si bien los despliegues tradicionales de RHEL se basaban en archivos Kickstart y máquinas virtuales, los entornos nativos de la nube modernos utilizan cada vez más RHEL en contenedores a través de imágenes UBI como redhat/ubi9.
Practicó la traducción de los conceptos tradicionales de Kickstart a la automatización de contenedores mediante la creación de Dockerfiles personalizados que definen la configuración del sistema, la instalación de paquetes, la gestión de usuarios y la configuración de servicios. En lugar de usar ksvalidator para los archivos Kickstart, aprendió a validar las configuraciones de los contenedores a través del proceso de construcción de Docker, que proporciona retroalimentación inmediata sobre la sintaxis y los errores de ejecución.
Finalmente, creó un script de automatización completo que demuestra el despliegue de contenedores de extremo a extremo, de forma similar al uso de virt-install con archivos Kickstart para la automatización de VM. Este enfoque proporciona el mismo nivel de automatización y consistencia que los métodos tradicionales, al tiempo que ofrece los beneficios de la contenedorización: un despliegue más rápido, una mejor utilización de los recursos, portabilidad y una escalabilidad más sencilla en los entornos de nube modernos.



