Введение
В этой лабораторной работе вы узнаете, как развернуть многоуровневое веб-приложение с использованием Podman на Red Hat Enterprise Linux (RHEL). Вы создадите полное решение, развернув контейнер базы данных MariaDB в качестве серверной части (backend) и контейнер веб-сервера Apache в качестве клиентской части (frontend). Этот практический опыт проведет вас через основные этапы развертывания контейнеризованного приложения, от начальной конфигурации до обеспечения публичного доступа к сервису.
Вы начнете с запуска контейнера MariaDB и его настройки при запуске с использованием переменных окружения. Далее вы настроите постоянное хранилище (persistent storage), чтобы обеспечить сохранность данных для базы данных, и создадите пользовательскую сеть для взаимодействия между контейнерами. Затем вы развернете веб-сервер Apache, откроете его порт для проверки подключения и, наконец, узнаете, как управлять контейнером как сервисом systemd для надежной и автоматизированной работы.
Запуск контейнера базы данных MariaDB с переменными окружения
На этом шаге вы узнаете, как запустить контейнеризованное приложение и настроить его при запуске с использованием переменных окружения. Это фундаментальный навык в управлении контейнерами, позволяющий выполнять гибкие и безопасные развертывания. Мы будем использовать официальный образ MariaDB в качестве примера, поскольку он требует нескольких параметров конфигурации для инициализации базы данных.
Во-первых, убедитесь, что вы находитесь в правильном рабочем каталоге. Вся работа для этой лабораторной работы будет выполняться внутри каталога ~/project.
cd ~/project
Перед запуском контейнера рекомендуется явно извлечь образ из реестра. Это гарантирует, что у вас будет правильная версия локально. Мы будем использовать образ mariadb:10.6 для этой лабораторной работы, чтобы обеспечить согласованность.
podman pull mariadb:10.6
Выберите образ mariadb:10.6 из реестра docker.
Вы должны увидеть вывод, указывающий на то, что образ загружается и извлекается.
10.6: Pulling from library/mariadb
...
Status: Downloaded newer image for mariadb:10.6
docker.io/library/mariadb:10.6
Теперь вы можете запустить контейнер MariaDB. Команда podman run создает и запускает новый контейнер. Мы будем использовать несколько флагов:
-d: Запускает контейнер в detached mode (в фоновом режиме).--name mariadb_server: Присваивает запоминающееся имя нашему контейнеру.-e VARIABLE=value: Устанавливает переменную окружения внутри контейнера. Образ MariaDB использует их для настройки базы данных при первом запуске.
Выполните следующую команду, чтобы запустить контейнер MariaDB. Мы устанавливаем пароль root, а также создаем новую базу данных с именем webappdb со специальным пользователем webappuser.
podman run -d \
--name mariadb_server \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
mariadb:10.6
Команда выведет длинный идентификатор контейнера, что подтверждает создание контейнера.
a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
Чтобы убедиться, что контейнер запущен, используйте команду podman ps.
podman ps
Вы должны увидеть mariadb_server в списке запущенных контейнеров.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 15 seconds ago Up 14 seconds 3306/tcp mariadb_server
Наконец, давайте проверим журналы контейнера, чтобы убедиться, что база данных инициализирована правильно, используя предоставленные нами переменные окружения.
podman logs mariadb_server
Прокрутите журналы. Вы ищете строку, которая указывает, что сервер готов к подключениям, что подтверждает успешный запуск. Вывод будет длинным, но ключевое сообщение об успехе в конце выглядит так:
...
2024-05-20 10:30:00+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/
...
2024-05-20 10:30:15+00:00 [Note] mariadbd: ready for connections.
Version: '10.6.x-MariaDB-1:10.6.x+maria~ubu2004' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
Вы успешно запустили и настроили контейнер MariaDB, используя переменные окружения.
Настройка постоянного хранилища для контейнера MariaDB
На этом шаге вы узнаете, как настроить постоянное хранилище для контейнера. По умолчанию все данные, созданные внутри контейнера, хранятся в перезаписываемом слое, который привязан к жизненному циклу контейнера. Если вы удалите контейнер, все эти данные будут потеряны. Для stateful приложений (приложений с сохранением состояния), таких как базы данных, это не идеально. Чтобы решить эту проблему, мы используем Podman volumes или bind mounts для хранения данных в файловой системе хоста, независимо от контейнера.
Во-первых, нам нужно удалить контейнер, который мы создали на предыдущем шаге, так как мы перезапустим его с новой конфигурацией хранилища.
Остановите запущенный контейнер mariadb_server:
podman stop mariadb_server
Вы увидите имя контейнера в выводе, подтверждающем получение команды.
mariadb_server
Теперь удалите остановленный контейнер:
podman rm mariadb_server
Опять же, имя контейнера будет выведено обратно.
mariadb_server
Далее создайте каталог на вашем хост-компьютере в каталоге ~/project. Этот каталог будет содержать файлы базы данных MariaDB.
mkdir ~/project/mariadb_data
При использовании Podman в rootless mode (без прав root) нам нужно установить правильные разрешения для смонтированного каталога. Контейнер MariaDB запускается от имени определенного пользователя (UID 999), поэтому нам нужно убедиться, что каталог доступен. Мы будем использовать флаг --userns=keep-id и установим соответствующие разрешения:
chmod 755 ~/project/mariadb_data
Теперь снова запустите контейнер MariaDB. Эта команда аналогична команде из предыдущего шага, но с добавлением флага -v и --userns=keep-id для правильной обработки сопоставления пространства имен пользователя. Флаг -v монтирует каталог ~/project/mariadb_data с вашего хоста в каталог /var/lib/mysql внутри контейнера, где MariaDB хранит свои данные. Мы используем $(pwd)/mariadb_data, чтобы предоставить абсолютный путь к команде podman.
podman run -d \
--name mariadb_server \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
Суффикс :Z в монтировании тома указывает Podman перемаркировать содержимое с помощью частной неразделяемой метки, что важно для совместимости с SELinux.
После запуска контейнера вы можете убедиться, что данные хранятся на вашем хост-компьютере. Выведите список содержимого каталога ~/project/mariadb_data.
ls -l ~/project/mariadb_data
Поскольку механизм базы данных контейнера был инициализирован, вы увидите несколько файлов и каталогов, созданных внутри ~/project/mariadb_data. Это подтверждает, что ваши данные теперь постоянны. Даже если вы удалите контейнер, эти данные останутся.
total 110632
-rw-rw---- 1 labex labex 16384 May 20 10:45 aria_log.00000001
-rw-rw---- 1 labex labex 52 May 20 10:45 aria_log_control
-rw-rw---- 1 labex labex 983 May 20 10:45 ib_buffer_pool
-rw-rw---- 1 labex labex 12582912 May 20 10:45 ibdata1
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile0
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile1
drwx------ 2 labex labex 4096 May 20 10:45 mysql
drwx------ 2 labex labex 4096 May 20 10:45 performance_schema
drwx------ 2 labex labex 4096 May 20 10:45 sys
drwx------ 2 labex labex 4096 May 20 10:45 webappdb
Вы успешно настроили свой контейнер MariaDB для использования постоянного хранилища, гарантируя, что данные вашей базы данных будут сохраняться при перезапусках и удалениях контейнера.
Создание пользовательской сети и развертывание веб-сервера Apache
На этом шаге вы создадите пользовательскую сеть для ваших контейнеров и развернете веб-сервер Apache. Хотя Podman предоставляет сеть по умолчанию, использование пользовательских сетей является лучшей практикой. Они обеспечивают лучшую изоляцию и, что наиболее важно, включают автоматическое разрешение DNS между контейнерами. Это позволяет контейнерам взаимодействовать друг с другом, используя их имена, что более надежно, чем использование IP-адресов, которые могут меняться.
Во-первых, давайте создадим пользовательскую bridge network (мостовую сеть) для нашего приложения. Мы назовем ее webapp-network.
podman network create webapp-network
Команда выведет имя вновь созданной сети.
webapp-network
Вы можете вывести список всех сетей Podman, чтобы убедиться, что ваша сеть была успешно создана.
podman network ls
Вы должны увидеть webapp-network в списке, наряду с сетями по умолчанию.
NETWORK ID NAME DRIVER SCOPE
...
f1e2d3c4b5a6 webapp-network bridge local
...
Далее нам нужно пересоздать наш контейнер mariadb_server в этой новой сети. Из-за конфигурации сетевого бэкенда в этой среде мы не можем подключить существующий контейнер к новой сети. Вместо этого мы остановим и пересоздадим контейнер с новой конфигурацией сети.
Остановите запущенный контейнер mariadb_server:
podman stop mariadb_server
Удалите остановленный контейнер:
podman rm mariadb_server
Теперь пересоздайте контейнер MariaDB с новой сетью. Эта команда аналогична команде из предыдущего шага, но с добавлением флага --network webapp-network:
podman run -d \
--name mariadb_server \
--network webapp-network \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
Теперь давайте развернем наш веб-сервер. Мы будем использовать официальный образ Apache httpd. Во-первых, создайте каталог на хосте для хранения файлов вашего веб-сайта.
mkdir ~/project/webapp_content
Создайте простой файл index.html в этом новом каталоге. Это будет домашняя страница нашего веб-приложения.
echo "<h1>Welcome to My Web App</h1>" > ~/project/webapp_content/index.html
Установите правильные разрешения для каталога контента веб-приложения, чтобы контейнер Apache мог получить доступ к файлам:
chmod 755 ~/project/webapp_content
Теперь запустите контейнер Apache httpd. Мы подключим его к нашей webapp-network и смонтируем каталог webapp_content в качестве volume (тома). Это гарантирует, что веб-сервер сможет обслуживать файл index.html, который мы только что создали.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
httpd:2.4
Давайте разберем параметры:
--network webapp-network: Подключает новый контейнер к нашей пользовательской сети.-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z: Это монтирует наш локальный каталогwebapp_contentв контейнер в/usr/local/apache2/htdocs/, который является каталогом по умолчанию, из которого Apache обслуживает файлы. Суффикс:Zуказывает Podman перемаркировать содержимое с помощью частной неразделяемой метки для совместимости с SELinux.
Убедитесь, что оба контейнера запущены.
podman ps
Теперь вы должны увидеть как mariadb_server, так и web_server в списке запущенных контейнеров.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a3f46c0ab3a docker.io/library/mariadb:10.6 mariadbd 29 seconds ago Up 29 seconds 3306/tcp mariadb_server
da5d52ce9c41 docker.io/library/httpd:2.4 httpd-foreground 7 seconds ago Up 7 seconds 80/tcp web_server
Оба контейнера теперь находятся в одной пользовательской сети и могут взаимодействовать друг с другом по имени.
Открытие порта веб-сервера и проверка подключения
На этом шаге вы узнаете, как открыть порт контейнера для хост-машины, делая сервис доступным извне изолированной сети контейнера. Наш веб-сервер Apache запущен, но мы пока не можем получить к нему доступ из браузера или командной строки нашего хоста. Мы исправим это, опубликовав порт контейнера.
Сопоставления портов определяются при создании контейнера. Поэтому мы должны сначала остановить и удалить контейнер web_server, который мы создали на предыдущем шаге. Не беспокойтесь о содержимом веб-сайта; оно в безопасности в каталоге ~/project/webapp_content на нашем хосте, потому что мы использовали bind mount (монтирование).
Сначала остановите контейнер:
podman stop web_server
web_server
Далее удалите остановленный контейнер:
podman rm web_server
web_server
Теперь мы снова запустим контейнер web_server, но на этот раз мы добавим флаг -p (или --publish), чтобы сопоставить порт с хоста с портом в контейнере. Мы сопоставим порт 8080 на хосте с портом 80 (порт HTTP по умолчанию) внутри контейнера.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
httpd:2.4
Новый флаг -p 8080:80 указывает Podman перенаправлять весь трафик с порта 8080 на хосте на порт 80 внутри контейнера web_server.
Давайте проверим, что контейнер запущен и порт правильно сопоставлен, используя podman ps.
podman ps
Обратите внимание на столбец PORTS для контейнера web_server. Теперь он показывает сопоставление от 0.0.0.0:8080 к 80/tcp, указывая на то, что порт успешно открыт.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5d4e3f2a1b6 httpd:2.4 "httpd-foreground" 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 25 minutes ago Up 25 minutes 3306/tcp mariadb_server
Наконец, давайте проверим подключение с нашей хост-машины, используя команду curl. Это отправляет HTTP-запрос на localhost по порту 8080.
curl http://localhost:8080
Вы должны увидеть HTML-контент из вашего файла index.html в качестве вывода, подтверждающего, что ваш веб-сервер теперь доступен с хоста.
<h1>Welcome to My Web App</h1>
Вы успешно открыли свой контейнерный веб-сервер для хост-машины, что является критическим шагом для предоставления приложений пользователям.
Управление контейнером веб-сервера как службой systemd
На этом заключительном шаге вы узнаете, как настроить контейнер для автоматического запуска, обеспечивая устойчивость вашей службы к сбоям или перезагрузкам системы. В стандартной системе Red Hat Enterprise Linux systemd является основным инструментом для управления службами. Однако среда Podman в этой лаборатории не использует systemd для прямого управления контейнерами.
Вместо этого мы достигнем того же результата — автоматического перезапуска службы — используя встроенные restart policies (политики перезапуска) Podman. Это стандартный, контейнерно-ориентированный способ обеспечения автоматического запуска контейнера демоном Podman. Мы настроим наш web_server на постоянный перезапуск, если он остановится по какой-либо причине.
Сначала мы должны удалить существующий контейнер, так как политики перезапуска могут быть применены только при создании контейнера.
Остановите контейнер web_server:
podman stop web_server
web_server
А теперь удалите его:
podman rm web_server
web_server
Далее пересоздайте контейнер web_server с той же конфигурацией, что и раньше, но добавьте флаг --restart always. Этот флаг предписывает демону Podman отслеживать контейнер и перезапускать его, если он когда-либо завершит работу.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
--restart always \
httpd:2.4
Контейнер запустится как обычно. Чтобы подтвердить, что политика перезапуска активна, вы можете проверить конфигурацию контейнера.
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
Команда должна вернуть always, подтверждая, что политика установлена.
always
Теперь давайте продемонстрируем, как работает политика перезапуска, вручную перезапустив контейнер, чтобы смоделировать то, что произойдет после перезагрузки системы или сбоя контейнера.
Сначала давайте проверим текущую конфигурацию политики перезапуска:
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
Это должно показать always, подтверждая, что наша политика перезапуска настроена.
always
Теперь давайте протестируем ручной перезапуск, чтобы смоделировать восстановление после сбоя:
podman start web_server
web_server
Убедитесь, что контейнер запущен:
podman ps
Вы должны увидеть оба запущенных контейнера с действующей политикой перезапуска:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e7f6g5h4i3j2 httpd:2.4 "httpd-foreground" About a minute ago Up 5 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" About an hour ago Up About an hour 3306/tcp mariadb_server
Наконец, убедитесь, что служба доступна:
curl http://localhost:8080
<h1>Welcome to My Web App</h1>
Понимание политик перезапуска:
Настроенная вами политика --restart always гарантирует, что:
- Контейнер будет перезапускаться автоматически, если он неожиданно завершит работу
- Контейнер будет запускаться автоматически при запуске службы Podman (например, после перезагрузки системы)
- Это обеспечивает устойчивость для производственных развертываний
Примечание: В некоторых лабораторных средах автоматическое поведение перезапуска может варьироваться в зависимости от конфигурации Podman и от того, запущена ли системная служба Podman. Ключевой задачей обучения является понимание того, как настроить политики перезапуска для производственных развертываний.
Вы успешно настроили свой контейнер для управления как службой, обеспечив его автоматическую доступность. Это завершает базовое управление жизненным циклом контейнерного приложения.
Резюме
В этой лабораторной работе вы изучили фундаментальный процесс развертывания многоконтейнерного веб-приложения на RHEL с использованием Podman. Вы начали с запуска контейнера базы данных MariaDB, настраивая его начальное состояние — включая пароль root, новую базу данных и выделенного пользователя — путем передачи переменных окружения во время выполнения. Затем вы настроили постоянное хранилище для контейнера базы данных, обеспечив сохранение критически важных данных при перезапусках контейнера.
Чтобы завершить стек приложений, вы создали пользовательскую сеть для обеспечения безопасной, изолированной связи между контейнерами. Вы развернули контейнер веб-сервера Apache в этой сети и открыли его порт для обеспечения доступа внешних пользователей. Наконец, вы интегрировали контейнер веб-сервера с systemd, управляя им как системной службой, чтобы гарантировать его автоматический запуск при загрузке и надежную работу, демонстрируя шаблон развертывания, готовый к производству.



