Instalar e Automatizar Implantações RHEL

Red Hat Enterprise LinuxBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá os fundamentos de como implantar e automatizar contêineres do Red Hat Enterprise Linux (RHEL) 9 usando o Docker. Implantações modernas nativas da nuvem dependem cada vez mais de ambientes RHEL em contêineres, em vez de máquinas virtuais tradicionais. Você começará explorando as Imagens Base Universais (UBI - Universal Base Images) da Red Hat, que fornecem ambientes RHEL de nível empresarial em formato de contêiner.

Você examinará como os conceitos tradicionais do Kickstart se traduzem para a automação de contêineres, criará Dockerfiles personalizados que espelham as configurações de instalação e construirá scripts de implantação automatizados. Ao final deste laboratório, você entenderá como implantar contêineres RHEL de forma eficiente e automatizar o processo para implantações consistentes e repetíveis em ambientes de nuvem modernos.

Explorar as Red Hat Universal Base Images (UBI)

Nesta etapa, você explorará as Imagens Base Universais (UBI - Universal Base Images) da Red Hat, que são imagens de contêiner de nível empresarial baseadas no RHEL. Ao contrário das instalações tradicionais do RHEL que exigem máquinas virtuais completas, as imagens UBI fornecem ambientes RHEL em contêineres leves e portáteis. Essas imagens são livremente redistribuíveis e projetadas para aplicações modernas nativas da nuvem.

A Red Hat fornece várias variantes UBI otimizadas para diferentes casos de uso. A imagem redhat/ubi9 fornece um ambiente de contêiner completo baseado em RHEL com o gerenciador de pacotes dnf, tornando-o adequado para aplicações que exigem instalação de software e automação do sistema.

Primeiro, vamos examinar o modelo de configuração de contêiner da Red Hat que foi preparado para este laboratório. Este arquivo demonstra como os conceitos tradicionais do Kickstart se traduzem para ambientes de contêiner.

sudo cat /etc/labex/rhel-container-config.cfg

Você verá uma saída mostrando uma configuração no estilo Dockerfile que espelha os conceitos de instalação tradicionais:

## 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"]

Agora, vamos explorar as imagens UBI da Red Hat disponíveis. Primeiro, verifique se o Docker está em execução e acessível:

docker --version

Faça o pull da imagem Red Hat UBI 9, que fornece um ambiente de contêiner completo baseado em RHEL:

docker pull redhat/ubi9

Você deve ver uma saída semelhante 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

Liste as imagens baixadas para confirmar se o pull foi bem-sucedido:

docker images redhat/ubi9

A saída mostrará detalhes sobre a imagem:

REPOSITORY      TAG       IMAGE ID       CREATED      SIZE
redhat/ubi9     latest    b1c2d3e4f5g6   5 days ago   216MB

Agora, vamos executar um contêiner básico para explorar o ambiente RHEL:

docker run -it --rm redhat/ubi9 /bin/bash

Dentro do contêiner, explore o ambiente RHEL verificando a versão do sistema operacional:

cat /etc/redhat-release

Você deve ver algo como:

Red Hat Enterprise Linux release 9.6 (Plow)

Verifique o gerenciador de pacotes disponível:

dnf --version

Saia do contêiner digitando:

exit

Copie a configuração do modelo para o seu diretório de projeto para personalização:

sudo cp /etc/labex/rhel-container-config.cfg ~/project/rhel-container.dockerfile
sudo chown labex:labex ~/project/rhel-container.dockerfile

Verifique se o arquivo foi copiado com sucesso:

ls -l ~/project/rhel-container.dockerfile

Você agora explorou com sucesso as imagens Red Hat UBI e está pronto para criar configurações de contêiner personalizadas na próxima etapa.

Criar uma Configuração de Container RHEL Personalizada

Nesta etapa, você criará um Dockerfile personalizado com base na imagem Red Hat UBI. Este processo espelha como você personalizaria um arquivo Kickstart para instalações automatizadas, mas adaptado para ambientes de contêiner. O Dockerfile serve como o modelo de automação para criar implantações de contêiner RHEL consistentes.

Primeiro, certifique-se de estar no seu diretório de projeto:

cd ~/project

Crie um novo Dockerfile, mais específico, para nossa implantação automatizada de contêiner RHEL:

cp rhel-container.dockerfile rhel9-automated.dockerfile

Verifique se ambos os arquivos existem:

ls -l *.dockerfile

Você deve ver ambos os arquivos:

-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

Agora, abra o novo Dockerfile para examinar sua estrutura antes da personalização:

nano rhel9-automated.dockerfile

Dentro do arquivo, você verá o equivalente em contêiner das diretivas Kickstart:

  • Diretiva FROM: Especifica a imagem RHEL base (equivalente à mídia de instalação)
  • Diretivas ENV: Define variáveis de ambiente (equivalente à configuração do sistema)
  • Diretivas RUN: Executa comandos durante a construção da imagem (equivalente à instalação do pacote)
  • EXPOSE e CMD: Configura serviços e inicialização (equivalente à configuração do serviço)

Por enquanto, simplesmente saia do editor pressionando Ctrl+X para prosseguir para a etapa de personalização.

Compreender essa estrutura prepara você para a próxima etapa, onde você personalizará a configuração do contêiner para atender aos requisitos específicos de implantação, assim como você personalizaria um arquivo Kickstart para instalações automatizadas de VM.

Personalizar a Configuração do Container para Implantação Automatizada

Nesta etapa, você substituirá o conteúdo do rhel9-automated.dockerfile por uma configuração personalizada para implantação automatizada de contêiner RHEL. Este processo é semelhante à personalização de um arquivo Kickstart, mas usa a abordagem declarativa do Docker para definir o ambiente e os serviços do contêiner.

Primeiro, certifique-se de estar no diretório do projeto:

cd ~/project

Agora, crie o Dockerfile personalizado completo, substituindo todo o conteúdo 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

Agora, vamos examinar a estrutura deste Dockerfile personalizado e entender como cada seção serve ao mesmo propósito que diferentes partes de uma configuração Kickstart:

1. Seção de Imagem Base e Metadados:

## 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 seção é equivalente a especificar a mídia de instalação e as informações básicas do sistema em um arquivo Kickstart. A diretiva FROM especifica nossa imagem RHEL base, enquanto as diretivas LABEL fornecem metadados sobre o contêiner.

2. Configuração do Ambiente:

## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001

Isso é paralelo às diretivas timezone e lang em arquivos Kickstart. Estamos definindo a localidade do sistema, o fuso horário e definindo variáveis para a criação do usuário.

3. Instalação do Pacote:

## 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 seção executa a mesma função que a seção %packages no Kickstart. Atualizamos o sistema, instalamos os pacotes necessários usando --allowerasing para lidar com conflitos e limpamos os caches de pacotes para reduzir o tamanho da imagem.

4. Configuração do Usuário e Segurança:

## 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

Isso espelha a diretiva user e a configuração pós-instalação no Kickstart. Criamos um usuário não root para segurança e configuramos o Apache para ser executado na porta 8080 (adequado para ambientes de contêiner).

5. Configuração de Inicialização:

## 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 seção final é equivalente à seção %post e à configuração do serviço no Kickstart. Criamos um script de inicialização, mudamos para o usuário não root, expomos a porta do serviço web, definimos verificações de integridade e especificamos o comando de inicialização do contêiner.

Verifique se o novo Dockerfile foi criado corretamente:

cat rhel9-automated.dockerfile

Você deve ver o conteúdo completo do Dockerfile que demonstra como os conceitos tradicionais de automação Kickstart se traduzem para implantações RHEL modernas baseadas em contêiner.

Validar a Configuração do Container e Construir a Imagem

Nesta etapa, você validará seu Dockerfile personalizado e construirá a imagem do contêiner RHEL. Este processo é semelhante à validação de um arquivo Kickstart com ksvalidator, mas usa a validação integrada do Docker durante o processo de construção. O Docker verificará a sintaxe e tentará executar cada instrução, fornecendo feedback imediato sobre quaisquer problemas.

Primeiro, certifique-se de estar no diretório do projeto onde seu Dockerfile está localizado:

cd ~/project

Antes de construir, vamos realizar uma verificação de sintaxe básica examinando a estrutura do Dockerfile. O Docker fornece uma maneira de validar a sintaxe básica sem construir:

docker build --no-cache --progress=plain -f rhel9-automated.dockerfile -t rhel9-test:validation . --target ""

No entanto, a validação mais eficaz é realmente construir a imagem. Se houver erros de sintaxe ou problemas com os comandos, o Docker os relatará durante o processo de construção. Observe que usamos a flag --allowerasing com dnf install para lidar com conflitos de pacotes entre curl e curl-minimal que existem na imagem UBI9 base:

docker build -t rhel9-automated:latest -f rhel9-automated.dockerfile .

Você deve ver a saída mostrando cada etapa do processo de construção:

[+] 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

Se a construção for concluída com sucesso, isso significa que a sintaxe do seu Dockerfile está correta e todos os comandos foram executados corretamente. Você pode ver algumas mensagens de aviso sobre as configurações de localidade e o gerenciamento de assinaturas durante o processo de construção - isso é normal para contêineres UBI e não afeta a funcionalidade.

Verifique se a imagem foi criada:

docker images rhel9-automated

Você deve ver sua imagem recém-construída:

REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
rhel9-automated  latest    a1b2c3d4e5f6   2 minutes ago    280MB

Agora, vamos testar o contêiner para garantir que ele funcione conforme o esperado. Execute o contêiner no modo detached:

docker run -d --name rhel9-test -p 8080:8080 rhel9-automated:latest

Verifique se o contêiner está em execução:

docker ps

Você deve ver seu contêiner na 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

Teste o serviço web fazendo uma solicitação ao contêiner:

curl http://localhost:8080

Você deve ver a saída HTML do seu contêiner 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, limpe parando e removendo o contêiner de teste:

docker stop rhel9-test
docker rm rhel9-test

Sua configuração do contêiner RHEL foi validada e testada com sucesso, demonstrando recursos de implantação automatizada.

Criar um Script de Implantação Automatizada

Nesta etapa, você criará um script de automação que demonstra como implantar contêineres RHEL de forma consistente e repetida. Este script serve ao mesmo propósito de usar arquivos Kickstart para automação de VM, mas é adaptado para implantações RHEL em contêineres. O script lidará com a construção da imagem, a implantação do contêiner e a verificação básica de integridade.

Primeiro, certifique-se de estar no diretório do seu projeto:

cd ~/project

Crie um script de automação de implantação que imite os recursos de automação que você obteria com Kickstart e virt-install:

nano deploy-rhel-container.sh

Adicione o seguinte conteúdo para criar um script de implantação abrangente:

#!/bin/bash

## Script de Implantação Automatizada de Contêiner RHEL
## Este script demonstra a automação da implantação RHEL baseada em contêineres
## Semelhante à automação Kickstart para VMs, mas para contêineres

set -e ## Sair em caso de erro

## Variáveis de configuração
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"

## Códigos de cores para saída
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## Sem Cor

## Função para imprimir saída colorida
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"
}

## Função para verificar se o Docker está em execução
check_docker() {
  print_status "Verificando a disponibilidade do Docker..."
  if ! docker info > /dev/null 2>&1; then
    print_error "O Docker não está em execução ou não é acessível"
    exit 1
  fi
  print_success "Docker está disponível"
}

## Função para construir a imagem
build_image() {
  print_status "Construindo a imagem do contêiner RHEL..."
  if [ ! -f "$DOCKERFILE" ]; then
    print_error "Dockerfile '$DOCKERFILE' não encontrado"
    exit 1
  fi

  docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
  print_success "Imagem '${IMAGE_NAME}:${IMAGE_TAG}' construída com sucesso"
}

## Função para parar e remover o contêiner existente
cleanup_existing() {
  print_status "Verificando a existência de um contêiner..."
  if docker ps -a | grep -q "$CONTAINER_NAME"; then
    print_warning "Parando e removendo o contêiner existente '$CONTAINER_NAME'"
    docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
    docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
  fi
}

## Função para implantar o contêiner
deploy_container() {
  print_status "Implantando o contêiner RHEL..."
  docker run -d \
    --name "$CONTAINER_NAME" \
    -p "${HOST_PORT}:${CONTAINER_PORT}" \
    --restart unless-stopped \
    "${IMAGE_NAME}:${IMAGE_TAG}"

  print_success "Contêiner '$CONTAINER_NAME' implantado com sucesso"
}

## Função para verificar a implantação
verify_deployment() {
  print_status "Verificando a implantação do contêiner..."

  ## Aguardar o início do contêiner
  sleep 5

  ## Verificar se o contêiner está em execução
  if ! docker ps | grep -q "$CONTAINER_NAME"; then
    print_error "O contêiner não está em execução"
    docker logs "$CONTAINER_NAME"
    exit 1
  fi

  ## Verificar se o serviço web está respondendo
  print_status "Testando o serviço web..."
  for i in {1..10}; do
    if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
      print_success "O serviço web está respondendo"
      break
    fi
    if [ $i -eq 10 ]; then
      print_error "O serviço web não está respondendo após 10 tentativas"
      exit 1
    fi
    sleep 2
  done
}

## Função para exibir informações de implantação
show_deployment_info() {
  print_success "=== Implantação do Contêiner RHEL Concluída ==="
  echo "Nome do Contêiner: $CONTAINER_NAME"
  echo "Imagem: ${IMAGE_NAME}:${IMAGE_TAG}"
  echo "Mapeamento de Porta: ${HOST_PORT}:${CONTAINER_PORT}"
  echo "URL de Acesso: http://localhost:${HOST_PORT}"
  echo ""
  print_status "Status do Contêiner:"
  docker ps | grep "$CONTAINER_NAME"
  echo ""
  print_status "Conteúdo de Exemplo:"
  curl -s "http://localhost:${HOST_PORT}" | head -2
}

## Processo principal de implantação
main() {
  echo "=== Implantação Automatizada do Contêiner RHEL ==="
  echo "Este script automatiza a implantação do contêiner RHEL"
  echo "Semelhante à automação Kickstart para instalações tradicionais"
  echo ""

  check_docker
  build_image
  cleanup_existing
  deploy_container
  verify_deployment
  show_deployment_info

  print_success "Implantação automatizada do contêiner RHEL concluída com sucesso!"
}

## Lidar com os argumentos do script
case "${1:-deploy}" in
  "deploy" | "")
    main
    ;;
  "cleanup")
    print_status "Limpando a implantação..."
    cleanup_existing
    docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
    print_success "Limpeza concluída"
    ;;
  "status")
    docker ps | grep "$CONTAINER_NAME" || print_warning "Contêiner não está em execução"
    ;;
  *)
    echo "Uso: $0 [deploy|cleanup|status]"
    echo "  deploy  - Construir e implantar o contêiner RHEL (padrão)"
    echo "  cleanup - Parar o contêiner e remover a imagem"
    echo "  status  - Mostrar o status do contêiner"
    exit 1
    ;;
esac

Salve o arquivo e saia do nano (Ctrl+X, depois Y, depois Enter).

Compreendendo a Estrutura do Script de Implantação

Antes de executar o script, vamos entender como este script de automação funciona. Esta seção fornece uma explicação detalhada de cada componente, tornando mais fácil para iniciantes entender os conceitos de script de shell e automação de contêineres.

Cabeçalho do Script e Tratamento de Erros

#!/bin/bash
set -e ## Sair em caso de erro
  • #!/bin/bash: Isso é chamado de "shebang" - ele diz ao sistema para usar o shell Bash para executar este script
  • set -e: Isso faz com que o script saia imediatamente se algum comando falhar, garantindo que o script pare no primeiro erro em vez de continuar com um estado potencialmente quebrado

Variáveis de Configuração

## Variáveis de configuração
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"

Essas variáveis definem todos os parâmetros-chave para nossa implantação. Ao colocá-los no topo, podemos modificar facilmente a configuração da implantação sem alterar a lógica do script. Isso é semelhante à forma como os arquivos Kickstart usam parâmetros de configuração.

Sistema de Saída Amigável ao Usuário

## Códigos de cores para saída
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## Sem Cor

## Função para imprimir saída colorida
print_status() {
  echo -e "${BLUE}[INFO]${NC} $1"
}

Isso cria um sistema de registro profissional com saída colorida:

  • \033[0;31m: Códigos de escape ANSI para cores (31 = vermelho, 32 = verde, etc.)
  • echo -e: A flag -e permite a interpretação de escapes de barra invertida para cores
  • $1: Refere-se ao primeiro argumento passado para a função

Funções Principais de Implantação

1. Verificação do Ambiente Docker

check_docker() {
  print_status "Verificando a disponibilidade do Docker..."
  if ! docker info > /dev/null 2>&1; then
    print_error "O Docker não está em execução ou não é acessível"
    exit 1
  fi
  print_success "Docker está disponível"
}
  • docker info > /dev/null 2>&1: Executa docker info e redireciona a saída (>) e os erros (2>&1) para /dev/null (os descarta)
  • !: Nega o resultado - se docker info falhar (retorna não-zero), a condição se torna verdadeira
  • Isso é equivalente a verificar se a virtualização está disponível em implantações tradicionais de VM

2. Função de Construção de Imagem

build_image() {
  print_status "Construindo a imagem do contêiner RHEL..."
  if [ ! -f "$DOCKERFILE" ]; then
    print_error "Dockerfile '$DOCKERFILE' não encontrado"
    exit 1
  fi

  docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
  print_success "Imagem '${IMAGE_NAME}:${IMAGE_TAG}' construída com sucesso"
}
  • [ ! -f "$DOCKERFILE" ]: Testa se o Dockerfile NÃO existe (! nega, -f testa a existência do arquivo)
  • docker build -t: Cria uma imagem de contêiner com uma tag (nome:versão)
  • Isso substitui o processo de instalação tradicional da mídia ISO

3. Função de Limpeza

cleanup_existing() {
  print_status "Verificando a existência de um contêiner..."
  if docker ps -a | grep -q "$CONTAINER_NAME"; then
    print_warning "Parando e removendo o contêiner 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: Lista todos os contêineres e pesquisa silenciosamente o nome do nosso contêiner
  • || true: Garante que o comando sempre seja bem-sucedido (retorna 0) mesmo que o contêiner não exista
  • Isso evita conflitos com implantações existentes

4. Implantação do Contêiner

deploy_container() {
  print_status "Implantando o contêiner RHEL..."
  docker run -d \
    --name "$CONTAINER_NAME" \
    -p "${HOST_PORT}:${CONTAINER_PORT}" \
    --restart unless-stopped \
    "${IMAGE_NAME}:${IMAGE_TAG}"

  print_success "Contêiner '$CONTAINER_NAME' implantado com sucesso"
}
  • -d: Executa o contêiner no modo detached (segundo plano)
  • -p "${HOST_PORT}:${CONTAINER_PORT}": Mapeia a porta do host para a porta do contêiner
  • --restart unless-stopped: Reinicia automaticamente o contêiner se ele parar (exceto paradas manuais)
  • \: Caractere de continuação de linha para comandos de várias linhas

5. Verificação de Integridade

verify_deployment() {
  print_status "Verificando a implantação do contêiner..."

  ## Aguardar o início do contêiner
  sleep 5

  ## Verificar se o contêiner está em execução
  if ! docker ps | grep -q "$CONTAINER_NAME"; then
    print_error "O contêiner não está em execução"
    docker logs "$CONTAINER_NAME"
    exit 1
  fi

  ## Verificar se o serviço web está respondendo
  print_status "Testando o serviço web..."
  for i in {1..10}; do
    if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
      print_success "O serviço web está respondendo"
      break
    fi
    if [ $i -eq 10 ]; then
      print_error "O serviço web não está respondendo após 10 tentativas"
      exit 1
    fi
    sleep 2
  done
}
  • {1..10}: Expansão de chaves Bash - cria a sequência 1, 2, 3... 10
  • curl -s: Modo silencioso de solicitação HTTP
  • break: Sai do loop antecipadamente quando o serviço responde
  • Isso implementa um mecanismo de repetição com tempo limite

Interface de Linha de Comando

case "${1:-deploy}" in
  "deploy" | "")
    main
    ;;
  "cleanup")
    print_status "Limpando a implantação..."
    cleanup_existing
    docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
    print_success "Limpeza concluída"
    ;;
  "status")
    docker ps | grep "$CONTAINER_NAME" || print_warning "Contêiner não está em execução"
    ;;
  *)
    echo "Uso: $0 [deploy|cleanup|status]"
    exit 1
    ;;
esac
  • ${1:-deploy}: Expansão de parâmetro - usa $1 (primeiro argumento) ou "deploy" como padrão
  • Instrução case: Semelhante a switch/case em outras linguagens
  • ;;: Termina cada ramificação do caso
  • $0: Refere-se ao próprio nome do script

Isso cria um script versátil que pode ser usado para várias operações, semelhante à forma como os administradores de sistema usam diferentes ferramentas para implantação, manutenção e monitoramento.

Torne o script executável:

chmod +x deploy-rhel-container.sh

Agora, execute o script de implantação automatizado para ver o processo de automação completo:

./deploy-rhel-container.sh

Você deve ver a saída mostrando o processo de implantação completo:

=== Implantação Automatizada do Contêiner RHEL ===
Este script automatiza a implantação do contêiner RHEL
Semelhante à automação Kickstart para instalações tradicionais

[INFO] Verificando a disponibilidade do Docker...
[SUCCESS] Docker está disponível
[INFO] Construindo a imagem do contêiner RHEL...
[SUCCESS] Imagem 'rhel9-automated:latest' construída com sucesso
[INFO] Verificando a existência de um contêiner...
[INFO] Implantando o contêiner RHEL...
[SUCCESS] Contêiner 'rhel9-production' implantado com sucesso
[INFO] Verificando a implantação do contêiner...
[INFO] Testando o serviço web...
[SUCCESS] O serviço web está respondendo
[SUCCESS] === Implantação do Contêiner RHEL Concluída ===
Nome do Contêiner: rhel9-production
Imagem: rhel9-automated:latest
Mapeamento de Porta: 8080:8080
URL de Acesso: http://localhost:8080

Teste as diferentes opções de script:

./deploy-rhel-container.sh status

Passo a Passo da Execução do Script

Quando você executa o script, ele executa a seguinte sequência automaticamente:

1. Fase de Validação do Ambiente

O script primeiro verifica se o Docker está disponível e acessível. Isso é crucial porque a implantação do contêiner requer um ambiente Docker em funcionamento, semelhante à forma como a implantação de VM requer um hipervisor em funcionamento.

2. Fase de Construção da Imagem

O script constrói uma nova imagem de contêiner a partir do seu Dockerfile. Este processo:

  • Lê o rhel9-automated.dockerfile
  • Baixa a imagem base UBI9 se ela ainda não estiver presente
  • Executa cada instrução no Dockerfile
  • Cria uma nova imagem marcada como rhel9-automated:latest

3. Fase de Limpeza

Antes de implantar, o script verifica e remove qualquer contêiner existente com o mesmo nome. Isso garante uma implantação limpa sem conflitos de nomenclatura.

4. Fase de Implantação

O script cria e inicia o novo contêiner com:

  • Modo detached: O contêiner é executado em segundo plano
  • Mapeamento de porta: A porta do host 8080 mapeia para a porta do contêiner 8080
  • Política de reinicialização: O contêiner reinicia automaticamente se parar inesperadamente
  • Contêiner nomeado: Fácil identificação e gerenciamento

5. Fase de Verificação

O script realiza verificações de integridade para garantir uma implantação bem-sucedida:

  • Verificação do status do contêiner: Verifica se o contêiner está em execução
  • Verificação da disponibilidade do serviço: Testa a resposta do serviço HTTP
  • Mecanismo de repetição: Tenta até 10 vezes com intervalos de 2 segundos
  • Detecção automática de falhas: Sai com erro se a verificação falhar

6. Fase de Exibição de Informações

Finalmente, o script exibe informações abrangentes de implantação, incluindo detalhes do contêiner, URLs de acesso e conteúdo de exemplo.

Exemplos de Uso Prático

Você pode usar este script de várias maneiras:

Implantação normal:

./deploy-rhel-container.sh
## ou explicitamente
./deploy-rhel-container.sh deploy

Verificar o status da implantação:

./deploy-rhel-container.sh status

Limpar recursos:

./deploy-rhel-container.sh cleanup

Visualizar a ajuda do script:

./deploy-rhel-container.sh help

Benefícios em Relação aos Métodos Tradicionais

Esta abordagem de automação oferece várias vantagens em comparação com as implantações tradicionais Kickstart + VM:

  1. Velocidade: A inicialização do contêiner é tipicamente 10-100x mais rápida do que a inicialização da VM
  2. Eficiência de Recursos: Os contêineres compartilham o kernel do host, usando menos memória e CPU
  3. Consistência: O mesmo contêiner é executado de forma idêntica em diferentes ambientes
  4. Escalabilidade: Fácil de criar várias instâncias ou escalar horizontalmente
  5. Portabilidade: Pode ser executado em qualquer sistema com o Docker instalado
  6. Controle de Versão: As imagens de contêiner podem ter controle de versão e serem armazenadas em registros

Este script de automação demonstra como as implantações RHEL modernas baseadas em contêineres podem alcançar o mesmo nível de automação e consistência que as instalações tradicionais de VM baseadas em Kickstart, mas com os benefícios adicionais da conteinerização, como implantação mais rápida, melhor utilização de recursos e escalonamento mais fácil em ambientes de nuvem modernos.

Resumo

Neste laboratório, você explorou a abordagem moderna para automatizar implantações do Red Hat Enterprise Linux (RHEL) 9 usando contêineres Docker e Red Hat Universal Base Images (UBI). Você aprendeu que, embora as implantações tradicionais do RHEL dependessem de arquivos Kickstart e máquinas virtuais, os ambientes modernos nativos da nuvem usam cada vez mais o RHEL em contêineres por meio de imagens UBI como redhat/ubi9.

Você praticou a tradução de conceitos tradicionais do Kickstart para a automação de contêineres, criando Dockerfiles personalizados que definem a configuração do sistema, a instalação de pacotes, o gerenciamento de usuários e a configuração de serviços. Em vez de usar ksvalidator para arquivos Kickstart, você aprendeu a validar as configurações de contêineres por meio do processo de construção do Docker, que fornece feedback imediato sobre erros de sintaxe e execução.

Finalmente, você criou um script de automação abrangente que demonstra a implantação de contêineres de ponta a ponta, semelhante ao uso de virt-install com arquivos Kickstart para automação de VM. Essa abordagem fornece o mesmo nível de automação e consistência que os métodos tradicionais, oferecendo ao mesmo tempo os benefícios da conteinerização: implantação mais rápida, melhor utilização de recursos, portabilidade e escalonamento mais fácil em ambientes de nuvem modernos.