Введение
В этой лабораторной работе вы изучите основы развертывания и автоматизации контейнеров Red Hat Enterprise Linux (RHEL) 9 с использованием Docker. Современные облачные развертывания все чаще полагаются на контейнеризированные среды RHEL, а не на традиционные виртуальные машины. Вы начнете с изучения Universal Base Images (UBI) от Red Hat, которые предоставляют среды RHEL корпоративного уровня в формате контейнеров.
Вы изучите, как традиционные концепции Kickstart преобразуются в автоматизацию контейнеров, создадите пользовательские Dockerfile, которые отражают конфигурации установки, и создадите автоматизированные скрипты развертывания. К концу этой лабораторной работы вы поймете, как эффективно развертывать контейнеры RHEL и автоматизировать процесс для последовательных, повторяемых развертываний в современных облачных средах.
Изучение Red Hat Universal Base Images (UBI)
На этом шаге вы изучите Red Hat Universal Base Images (UBI), которые представляют собой контейнерные образы корпоративного уровня на основе RHEL. В отличие от традиционных установок RHEL, требующих полных виртуальных машин, образы UBI предоставляют среды RHEL в легких, переносимых контейнерах. Эти образы свободно распространяются и предназначены для современных облачных приложений.
Red Hat предоставляет несколько вариантов UBI, оптимизированных для различных вариантов использования. Образ redhat/ubi9 предоставляет полную контейнерную среду на основе RHEL с менеджером пакетов dnf, что делает его подходящим для приложений, требующих установки программного обеспечения и автоматизации системы.
Сначала давайте рассмотрим шаблон конфигурации контейнера Red Hat, который был подготовлен для этой лабораторной работы. Этот файл демонстрирует, как традиционные концепции Kickstart преобразуются в контейнерные среды.
sudo cat /etc/labex/rhel-container-config.cfg
Вы увидите вывод, показывающий конфигурацию в стиле Dockerfile, которая отражает традиционные концепции установки:
## 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"]
Теперь давайте изучим доступные образы Red Hat UBI. Сначала проверьте, запущен ли Docker и доступен ли он:
docker --version
Извлеките образ Red Hat UBI 9, который предоставляет полную контейнерную среду на основе RHEL:
docker pull redhat/ubi9
Вы должны увидеть вывод, похожий на:
Using default tag: latest
latest: Pulling from redhat/ubi9
Digest: sha256:...
Status: Downloaded newer image for redhat/ubi9:latest
docker.io/redhat/ubi9:latest
Выведите список загруженных образов, чтобы подтвердить успешное извлечение:
docker images redhat/ubi9
Вывод покажет подробную информацию об образе:
REPOSITORY TAG IMAGE ID CREATED SIZE
redhat/ubi9 latest b1c2d3e4f5g6 5 days ago 216MB
Теперь давайте запустим базовый контейнер, чтобы изучить среду RHEL:
docker run -it --rm redhat/ubi9 /bin/bash
Внутри контейнера изучите среду RHEL, проверив версию операционной системы:
cat /etc/redhat-release
Вы должны увидеть что-то вроде:
Red Hat Enterprise Linux release 9.6 (Plow)
Проверьте доступный менеджер пакетов:
dnf --version
Выйдите из контейнера, набрав:
exit
Скопируйте шаблон конфигурации в ваш рабочий каталог для настройки:
sudo cp /etc/labex/rhel-container-config.cfg ~/project/rhel-container.dockerfile
sudo chown labex:labex ~/project/rhel-container.dockerfile
Убедитесь, что файл был успешно скопирован:
ls -l ~/project/rhel-container.dockerfile
Теперь вы успешно изучили образы Red Hat UBI и готовы создать пользовательские конфигурации контейнеров на следующем шаге.
Создание пользовательской конфигурации контейнера RHEL
На этом шаге вы создадите пользовательский Dockerfile на основе образа Red Hat UBI. Этот процесс отражает то, как вы настраиваете файл Kickstart для автоматизированных установок, но адаптирован для контейнерных сред. Dockerfile служит шаблоном автоматизации для создания последовательных развертываний контейнеров RHEL.
Сначала убедитесь, что вы находитесь в своем рабочем каталоге:
cd ~/project
Создайте новый, более конкретный Dockerfile для нашего автоматизированного развертывания контейнера RHEL:
cp rhel-container.dockerfile rhel9-automated.dockerfile
Убедитесь, что оба файла существуют:
ls -l *.dockerfile
Вы должны увидеть оба файла:
-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
Теперь откройте новый Dockerfile, чтобы изучить его структуру перед настройкой:
nano rhel9-automated.dockerfile
Внутри файла вы увидите эквивалент директив Kickstart для контейнеров:
- Директива FROM: Указывает базовый образ RHEL (эквивалент установочного носителя)
- Директивы ENV: Устанавливают переменные окружения (эквивалент конфигурации системы)
- Директивы RUN: Выполняют команды во время сборки образа (эквивалент установки пакетов)
- EXPOSE и CMD: Настраивают службы и запуск (эквивалент конфигурации служб)
Пока просто выйдите из редактора, нажав Ctrl+X, чтобы перейти к шагу настройки.
Понимание этой структуры подготовит вас к следующему шагу, где вы настроите конфигурацию контейнера в соответствии с конкретными требованиями развертывания, точно так же, как вы настраиваете файл Kickstart для автоматизированных установок виртуальных машин.
Настройка конфигурации контейнера для автоматизированного развертывания
На этом шаге вы замените содержимое файла rhel9-automated.dockerfile пользовательской конфигурацией для автоматизированного развертывания контейнера RHEL. Этот процесс аналогичен настройке файла Kickstart, но использует декларативный подход Docker для определения среды и служб контейнера.
Сначала убедитесь, что вы находитесь в рабочем каталоге проекта:
cd ~/project
Теперь создайте полный пользовательский Dockerfile, заменив все содержимое 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
Теперь давайте рассмотрим структуру этого настроенного Dockerfile и поймем, как каждый раздел выполняет ту же функцию, что и разные части конфигурации Kickstart:
1. Раздел базового образа и метаданных:
## 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"
Этот раздел эквивалентен указанию установочного носителя и базовой информации о системе в файле Kickstart. Директива FROM указывает наш базовый образ RHEL, а директивы LABEL предоставляют метаданные о контейнере.
2. Конфигурация окружения:
## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001
Это соответствует директивам timezone и lang в файлах Kickstart. Мы устанавливаем локаль системы, часовой пояс и определяем переменные для создания пользователя.
3. Установка пакетов:
## 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
Этот раздел выполняет ту же функцию, что и раздел %packages в Kickstart. Мы обновляем систему, устанавливаем необходимые пакеты, используя --allowerasing для обработки конфликтов, и очищаем кэши пакетов, чтобы уменьшить размер образа.
4. Конфигурация пользователя и безопасности:
## 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
Это отражает директиву user и конфигурацию после установки в Kickstart. Мы создаем непривилегированного пользователя для безопасности и настраиваем Apache для работы на порту 8080 (подходит для контейнерных сред).
5. Конфигурация запуска:
## 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"]
Этот заключительный раздел эквивалентен разделу %post и конфигурации служб в Kickstart. Мы создаем сценарий запуска, переключаемся на непривилегированного пользователя, открываем порт веб-службы, определяем проверки работоспособности и указываем команду запуска контейнера.
Убедитесь, что новый Dockerfile был создан правильно:
cat rhel9-automated.dockerfile
Вы должны увидеть полное содержимое Dockerfile, которое демонстрирует, как традиционные концепции автоматизации Kickstart преобразуются в современные контейнерные развертывания RHEL.
Проверка конфигурации контейнера и сборка образа
На этом шаге вы проверите свой пользовательский Dockerfile и соберете образ контейнера RHEL. Этот процесс аналогичен проверке файла Kickstart с помощью ksvalidator, но использует встроенную проверку Docker во время процесса сборки. Docker проверит синтаксис и попытается выполнить каждую инструкцию, предоставляя немедленную обратную связь по любым проблемам.
Сначала убедитесь, что вы находитесь в каталоге проекта, где находится ваш Dockerfile:
cd ~/project
Перед сборкой давайте выполним базовую проверку синтаксиса, изучив структуру Dockerfile. Docker предоставляет способ проверки базового синтаксиса без сборки:
docker build --no-cache --progress=plain -f rhel9-automated.dockerfile -t rhel9-test:validation . --target ""
Однако наиболее эффективной проверкой является фактическая сборка образа. Если есть синтаксические ошибки или проблемы с командами, Docker сообщит о них в процессе сборки. Обратите внимание, что мы используем флаг --allowerasing с dnf install для обработки конфликтов пакетов между curl и curl-minimal, которые существуют в базовом образе UBI9:
docker build -t rhel9-automated:latest -f rhel9-automated.dockerfile .
Вы должны увидеть вывод, показывающий каждый шаг процесса сборки:
[+] 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
Если сборка завершится успешно, это означает, что синтаксис вашего Dockerfile верен и все команды выполнены правильно. Вы можете увидеть некоторые предупреждающие сообщения о настройках локали и управлении подписками в процессе сборки — это нормально для контейнеров UBI и не влияет на функциональность.
Убедитесь, что образ был создан:
docker images rhel9-automated
Вы должны увидеть свой вновь собранный образ:
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel9-automated latest a1b2c3d4e5f6 2 minutes ago 280MB
Теперь давайте протестируем контейнер, чтобы убедиться, что он работает должным образом. Запустите контейнер в отсоединенном режиме:
docker run -d --name rhel9-test -p 8080:8080 rhel9-automated:latest
Проверьте, запущен ли контейнер:
docker ps
Вы должны увидеть свой контейнер в списке:
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
Протестируйте веб-службу, отправив запрос в контейнер:
curl http://localhost:8080
Вы должны увидеть вывод HTML из вашего автоматизированного контейнера RHEL:
RHEL Container started on Wed Jul 22 14:30:15 UTC 2024
<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>
Наконец, выполните очистку, остановив и удалив тестовый контейнер:
docker stop rhel9-test
docker rm rhel9-test
Конфигурация вашего контейнера RHEL была успешно проверена и протестирована, демонстрируя возможности автоматизированного развертывания.
Создание скрипта автоматического развертывания
На этом шаге вы создадите скрипт автоматизации, который демонстрирует, как последовательно и многократно развертывать контейнеры RHEL. Этот скрипт служит той же цели, что и использование файлов Kickstart для автоматизации виртуальных машин, но адаптирован для контейнерных развертываний RHEL. Скрипт будет обрабатывать сборку образов, развертывание контейнеров и базовую проверку работоспособности.
Сначала убедитесь, что вы находитесь в каталоге вашего проекта:
cd ~/project
Создайте скрипт автоматизации развертывания, который имитирует возможности автоматизации, которые вы могли бы достичь с помощью Kickstart и virt-install:
nano deploy-rhel-container.sh
Добавьте следующее содержимое для создания комплексного скрипта развертывания:
#!/bin/bash
## RHEL Container Automated Deployment Script
## This script demonstrates container-based RHEL deployment automation
## Similar to Kickstart automation for VMs, but for containers
set -e ## Exit on any error
## Configuration variables
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
## Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## No Color
## Function to print colored output
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"
}
## Function to check if Docker is running
check_docker() {
print_status "Checking Docker availability..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker is not running or not accessible"
exit 1
fi
print_success "Docker is available"
}
## Function to build the image
build_image() {
print_status "Building RHEL container image..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE' not found"
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "Image '${IMAGE_NAME}:${IMAGE_TAG}' built successfully"
}
## Function to stop and remove existing container
cleanup_existing() {
print_status "Checking for existing container..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "Stopping and removing existing container '$CONTAINER_NAME'"
docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
fi
}
## Function to deploy the container
deploy_container() {
print_status "Deploying RHEL container..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "Container '$CONTAINER_NAME' deployed successfully"
}
## Function to verify deployment
verify_deployment() {
print_status "Verifying container deployment..."
## Wait for container to start
sleep 5
## Check if container is running
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "Container is not running"
docker logs "$CONTAINER_NAME"
exit 1
fi
## Check if web service is responding
print_status "Testing web service..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "Web service is responding"
break
fi
if [ $i -eq 10 ]; then
print_error "Web service is not responding after 10 attempts"
exit 1
fi
sleep 2
done
}
## Function to display deployment information
show_deployment_info() {
print_success "=== RHEL Container Deployment Complete ==="
echo "Container Name: $CONTAINER_NAME"
echo "Image: ${IMAGE_NAME}:${IMAGE_TAG}"
echo "Port Mapping: ${HOST_PORT}:${CONTAINER_PORT}"
echo "Access URL: http://localhost:${HOST_PORT}"
echo ""
print_status "Container Status:"
docker ps | grep "$CONTAINER_NAME"
echo ""
print_status "Sample Content:"
curl -s "http://localhost:${HOST_PORT}" | head -2
}
## Main deployment process
main() {
echo "=== RHEL Container Automated Deployment ==="
echo "This script automates RHEL container deployment"
echo "Similar to Kickstart automation for traditional installations"
echo ""
check_docker
build_image
cleanup_existing
deploy_container
verify_deployment
show_deployment_info
print_success "Automated RHEL container deployment completed successfully!"
}
## Handle script arguments
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "Cleaning up deployment..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "Cleanup completed"
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "Container not running"
;;
*)
echo "Usage: $0 [deploy|cleanup|status]"
echo " deploy - Build and deploy RHEL container (default)"
echo " cleanup - Stop container and remove image"
echo " status - Show container status"
exit 1
;;
esac
Сохраните файл и выйдите из nano (Ctrl+X, затем Y, затем Enter).
Понимание структуры скрипта развертывания
Прежде чем запускать скрипт, давайте разберемся, как работает этот скрипт автоматизации. Этот раздел содержит подробное объяснение каждого компонента, что упрощает понимание концепций написания сценариев оболочки и автоматизации контейнеров для начинающих.
Заголовок скрипта и обработка ошибок
#!/bin/bash
set -e ## Exit on any error
#!/bin/bash: Это называется "shebang" - он указывает системе использовать оболочку Bash для выполнения этого скриптаset -e: Это заставляет скрипт немедленно завершаться, если какая-либо команда завершается неудачей, гарантируя, что скрипт остановится при первой ошибке, а не продолжит работу с потенциально сломанным состоянием
Переменные конфигурации
## Configuration variables
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"
Эти переменные определяют все ключевые параметры для нашего развертывания. Разместив их вверху, мы можем легко изменить конфигурацию развертывания, не изменяя логику скрипта. Это аналогично тому, как файлы Kickstart используют параметры конфигурации.
Удобная система вывода
## Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## No Color
## Function to print colored output
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
Это создает профессиональную систему ведения журнала с цветным выводом:
\033[0;31m: ANSI escape codes for colors (31 = red, 32 = green, etc.)echo -e: Флаг-eвключает интерпретацию обратных косых черт для цветов$1: Относится к первому аргументу, переданному функции
Основные функции развертывания
1. Проверка среды Docker
check_docker() {
print_status "Checking Docker availability..."
if ! docker info > /dev/null 2>&1; then
print_error "Docker is not running or not accessible"
exit 1
fi
print_success "Docker is available"
}
docker info > /dev/null 2>&1: Запускаетdocker infoи перенаправляет как вывод (>), так и ошибки (2>&1) в/dev/null(отбрасывает их)!: Отрицает результат - еслиdocker infoзавершается неудачей (возвращает ненулевое значение), условие становится истинным- Это эквивалентно проверке доступности виртуализации в традиционных развертываниях виртуальных машин
2. Функция сборки образа
build_image() {
print_status "Building RHEL container image..."
if [ ! -f "$DOCKERFILE" ]; then
print_error "Dockerfile '$DOCKERFILE' not found"
exit 1
fi
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
print_success "Image '${IMAGE_NAME}:${IMAGE_TAG}' built successfully"
}
[ ! -f "$DOCKERFILE" ]: Проверяет, что Dockerfile НЕ существует (!отрицает,-fпроверяет существование файла)docker build -t: Создает образ контейнера с тегом (имя:версия)- Это заменяет традиционный процесс установки с носителя ISO
3. Функция очистки
cleanup_existing() {
print_status "Checking for existing container..."
if docker ps -a | grep -q "$CONTAINER_NAME"; then
print_warning "Stopping and removing existing container '$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: Выводит список всех контейнеров и тихо ищет имя нашего контейнера|| true: Гарантирует, что команда всегда завершится успешно (возвращает 0), даже если контейнер не существует- Это предотвращает конфликты с существующими развертываниями
4. Развертывание контейнера
deploy_container() {
print_status "Deploying RHEL container..."
docker run -d \
--name "$CONTAINER_NAME" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
print_success "Container '$CONTAINER_NAME' deployed successfully"
}
-d: Запускает контейнер в отсоединенном режиме (в фоновом режиме)-p "${HOST_PORT}:${CONTAINER_PORT}": Сопоставляет порт хоста с портом контейнера--restart unless-stopped: Автоматически перезапускает контейнер, если он останавливается (за исключением ручных остановок)\: Символ продолжения строки для многострочных команд
5. Проверка работоспособности
verify_deployment() {
print_status "Verifying container deployment..."
## Wait for container to start
sleep 5
## Check if container is running
if ! docker ps | grep -q "$CONTAINER_NAME"; then
print_error "Container is not running"
docker logs "$CONTAINER_NAME"
exit 1
fi
## Check if web service is responding
print_status "Testing web service..."
for i in {1..10}; do
if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
print_success "Web service is responding"
break
fi
if [ $i -eq 10 ]; then
print_error "Web service is not responding after 10 attempts"
exit 1
fi
sleep 2
done
}
{1..10}: Расширение фигурных скобок Bash - создает последовательность 1, 2, 3... 10curl -s: Беззвучный режим HTTP-запросаbreak: Прерывает цикл раньше времени, когда служба отвечает- Это реализует механизм повторных попыток с тайм-аутом
Интерфейс командной строки
case "${1:-deploy}" in
"deploy" | "")
main
;;
"cleanup")
print_status "Cleaning up deployment..."
cleanup_existing
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
print_success "Cleanup completed"
;;
"status")
docker ps | grep "$CONTAINER_NAME" || print_warning "Container not running"
;;
*)
echo "Usage: $0 [deploy|cleanup|status]"
echo " deploy - Build and deploy RHEL container (default)"
echo " cleanup - Stop container and remove image"
echo " status - Show container status"
exit 1
;;
esac
${1:-deploy}: Расширение параметра - использует$1(первый аргумент) или "deploy" по умолчанию- Оператор
case: Аналогично switch/case в других языках ;;: Завершает каждую ветвь case$0: Относится к имени самого скрипта
Это создает универсальный скрипт, который можно использовать для нескольких операций, аналогично тому, как системные администраторы используют разные инструменты для развертывания, обслуживания и мониторинга.
Сделайте скрипт исполняемым:
chmod +x deploy-rhel-container.sh
Теперь запустите скрипт автоматизированного развертывания, чтобы увидеть полный процесс автоматизации:
./deploy-rhel-container.sh
Вы должны увидеть вывод, показывающий полный процесс развертывания:
=== RHEL Container Automated Deployment ===
This script automates RHEL container deployment
Similar to Kickstart automation for traditional installations
[INFO] Checking Docker availability...
[SUCCESS] Docker is available
[INFO] Building RHEL container image...
[SUCCESS] Image 'rhel9-automated:latest' built successfully
[INFO] Checking for existing container...
[INFO] Deploying RHEL container...
[SUCCESS] Container 'rhel9-production' deployed successfully
[INFO] Verifying container deployment...
[INFO] Testing web service...
[SUCCESS] Web service is responding
[SUCCESS] === RHEL Container Deployment Complete ===
Container Name: rhel9-production
Image: rhel9-automated:latest
Port Mapping: 8080:8080
Access URL: http://localhost:8080
Протестируйте различные параметры скрипта:
./deploy-rhel-container.sh status
Пошаговое выполнение скрипта
При запуске скрипта он автоматически выполняет следующую последовательность:
1. Фаза проверки среды
Скрипт сначала проверяет, доступен ли Docker и доступен ли он. Это очень важно, потому что для развертывания контейнера требуется рабочая среда Docker, аналогично тому, как для развертывания виртуальной машины требуется работающий гипервизор.
2. Фаза сборки образа
Скрипт собирает новый образ контейнера из вашего Dockerfile. Этот процесс:
- Считывает
rhel9-automated.dockerfile - Загружает базовый образ UBI9, если он еще не присутствует
- Выполняет каждую инструкцию в Dockerfile
- Создает новый образ с тегом
rhel9-automated:latest
3. Фаза очистки
Перед развертыванием скрипт проверяет и удаляет любой существующий контейнер с тем же именем. Это обеспечивает чистое развертывание без конфликтов имен.
4. Фаза развертывания
Скрипт создает и запускает новый контейнер со следующими параметрами:
- Отсоединенный режим: Контейнер работает в фоновом режиме
- Сопоставление портов: Порт хоста 8080 сопоставляется с портом контейнера 8080
- Политика перезапуска: Контейнер автоматически перезапускается, если он неожиданно останавливается
- Именованный контейнер: Простота идентификации и управления
5. Фаза проверки
Скрипт выполняет проверки работоспособности, чтобы обеспечить успешное развертывание:
- Проверка состояния контейнера: Проверяет, работает ли контейнер
- Проверка доступности службы: Тестирует ответ службы HTTP
- Механизм повторных попыток: Попытки до 10 раз с интервалом в 2 секунды
- Автоматическое обнаружение сбоев: Завершается с ошибкой, если проверка завершается неудачей
6. Фаза отображения информации
Наконец, скрипт отображает исчерпывающую информацию о развертывании, включая сведения о контейнере, URL-адреса доступа и пример содержимого.
Практические примеры использования
Вы можете использовать этот скрипт различными способами:
Обычное развертывание:
./deploy-rhel-container.sh
## or explicitly
./deploy-rhel-container.sh deploy
Проверка состояния развертывания:
./deploy-rhel-container.sh status
Очистка ресурсов:
./deploy-rhel-container.sh cleanup
Просмотр справки по скрипту:
./deploy-rhel-container.sh help
Преимущества по сравнению с традиционными методами
Этот подход к автоматизации предоставляет несколько преимуществ по сравнению с традиционными развертываниями Kickstart + VM:
- Скорость: Запуск контейнера обычно в 10-100 раз быстрее, чем загрузка виртуальной машины
- Эффективность использования ресурсов: Контейнеры совместно используют ядро хоста, используя меньше памяти и ЦП
- Согласованность: Один и тот же контейнер работает одинаково в разных средах
- Масштабируемость: Легко создавать несколько экземпляров или масштабировать по горизонтали
- Портативность: Может работать в любой системе с установленным Docker
- Управление версиями: Образы контейнеров могут быть версионированы и храниться в реестрах
Этот скрипт автоматизации демонстрирует, как современные контейнерные развертывания RHEL могут достичь того же уровня автоматизации и согласованности, что и традиционные установки виртуальных машин на основе Kickstart, но с дополнительными преимуществами контейнеризации, такими как более быстрое развертывание, лучшее использование ресурсов и более простое масштабирование в современных облачных средах.
Резюме
В этой лабораторной работе вы изучили современный подход к автоматизации развертываний Red Hat Enterprise Linux (RHEL) 9 с использованием контейнеров Docker и Red Hat Universal Base Images (UBI). Вы узнали, что в то время как традиционные развертывания RHEL полагались на файлы Kickstart и виртуальные машины, современные облачные среды все чаще используют контейнеризированный RHEL через образы UBI, такие как redhat/ubi9.
Вы попрактиковались в переводе традиционных концепций Kickstart на автоматизацию контейнеров, создавая пользовательские Dockerfile, которые определяют конфигурацию системы, установку пакетов, управление пользователями и конфигурацию служб. Вместо использования ksvalidator для файлов Kickstart, вы научились проверять конфигурации контейнеров с помощью процесса сборки Docker, который обеспечивает немедленную обратную связь по синтаксическим и исполнительным ошибкам.
Наконец, вы создали комплексный скрипт автоматизации, который демонстрирует сквозное развертывание контейнеров, аналогично использованию virt-install с файлами Kickstart для автоматизации виртуальных машин. Этот подход обеспечивает тот же уровень автоматизации и согласованности, что и традиционные методы, предлагая при этом преимущества контейнеризации: более быстрое развертывание, лучшее использование ресурсов, переносимость и более простое масштабирование в современных облачных средах.



