Контейнеризация приложения Java
В этом уроке вы контейнеризируете приложение Java.
Как упоминалось ранее, контейнеры выполняются непосредственно поверх хост-системы, ядра и оборудования как обычные системные процессы. Контейнеры требуют меньше системных ресурсов, что приводит к меньшему объему ресурсов, меньшему объему затрат и более быстрому времени запуска приложения. Эти преимущества являются отличными вариантами использования для масштабирования по требованию.
Существуют контейнеры Windows и контейнеры Linux. В этом модуле используется широко используемая среда выполнения Docker для создания образа контейнера Linux. Затем вы развернете образ контейнера Linux в операционной системе узла локального компьютера. Наконец, вы развернете образ контейнера Linux в службе Azure Kubernetes.
Обзор Docker
Среда выполнения Docker используется для создания, извлечения, запуска и отправки образов контейнеров, как показано на следующей схеме:
В следующей таблице описана каждая команда Docker:
| Команда Docker | Описание |
|---|---|
docker build |
Создает образ контейнера, состоящий из инструкций или слоев, необходимых для Docker, чтобы создать запущенный контейнер из образа. Результатом этой команды является изображение. |
docker pull |
Контейнеры инициализированы из образов, которые извлекаются из реестров, таких как Реестр контейнеров Azure. В этом реестре служба Azure Kubernetes Service осуществляет загрузку. Результатом этой команды является извлечение образа в сети, которое происходит в Azure. При необходимости можно извлечь изображения локально. Этот параметр часто возникает при создании образов, требующих зависимостей или слоев, которые может потребоваться приложению, например на сервере приложений. |
docker run |
Запущенный экземпляр образа — это контейнер, и эта команда выполняет все уровни, необходимые для запуска и взаимодействия с запущенным приложением контейнера. Результатом этой команды является запущенный процесс приложения в операционной системе узла. |
docker push |
Реестр контейнеров Azure хранит образы так, чтобы они были легко доступны и находились близко к сети для развертывания и масштабирования Azure. |
Клонирование приложения Java
Сначала клонируйте репозиторий Flight Booking System for Airline Reservations и перейдите в папку проекта веб-приложения авиакомпаний.
Заметка
Если создание службы Azure Kubernetes завершено на вкладке CLI, используйте её. Если она всё ещё выполняется, откройте новую вкладку и перейдите к расположению, где вы хотите клонировать систему бронирования авиабилетов.
Выполните следующие команды:
git clone https://github.com/Azure-Samples/containerize-and-deploy-Java-app-to-Azure.git
cd containerize-and-deploy-Java-app-to-Azure/Project/Airlines
При необходимости при установке Java и Maven можно выполнить следующую команду в консоли терминала, чтобы получить представление о создании приложения без Docker. Если у вас нет java и Maven, вы можете безопасно перейти к следующему разделу, создайте файл Docker. В этом разделе вы используете Docker для загрузки Java и Maven, чтобы автоматически выполнять сборки.
mvn clean package
Заметка
Мы использовали mvn clean package команду, чтобы проиллюстрировать операционные проблемы, связанные с неиспользованием многоэтапных сборок Docker, которые мы рассмотрим далее. Опять же, этот шаг является необязательным. В любом случае можно безопасно продолжить без выполнения команды Maven.
Если процесс был успешным, Maven успешно собрал архивный артефакт веб-приложения для системы бронирования авиабилетов AirlinesReservationSample-0.0.1-SNAPSHOT.war, как показано в следующем выводе:
[INFO] Building war: $PROJECT_PATH/containerize-and-deploy-Java-app-to-Azure/Project/Airlines/target/AirlinesReservationSample-0.0.1-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.776 s
[INFO] Finished at: 2024-11-15T09:33:26+09:00
[INFO] ------------------------------------------------------------------------
Представьте, что вы разработчик Java, и вы только что создали AirlinesReservationSample-0.0.1-SNAPSHOT.war. Следующий шаг, вероятно, заключается в работе с инженерами эксплуатации, чтобы развернуть этот артефакт на локальном сервере или виртуальной машине. Для успешного запуска и запуска приложения серверы и виртуальные машины должны быть доступны и настроены с необходимыми зависимостями. Этот процесс является сложным и трудоемким, особенно в моменты повышенной нагрузки на приложение. С помощью контейнеров эти проблемы устраняются.
Создайте Dockerfile
Теперь вы готовы создать Dockerfile. Dockerfile — это текстовый документ, содержащий все команды, которые пользователь выполнит в командной строке для сборки образа контейнера. Каждый образ — это слой, который можно кэшировать для повышения эффективности. Слои создаются поверх друг друга.
Например, система бронирования полетов для резервирования авиакомпаний должна развертываться и запускаться внутри сервера приложений. Сервер приложений не упакован внутри AirlinesReservationSample-0.0.1-SNAPSHOT.war. Это внешняя зависимость, необходимая для AirlinesReservationSample-0.0.1-SNAPSHOT.war для запуска, прослушивания и обработки HTTP-запросов, управления сеансами пользователей и обеспечения бронирования рейсов. Если вы использовали традиционное развертывание без использования контейнеров, то инженеры по эксплуатации устанавливают и настраивают сервер приложений на физическом сервере или виртуальной машине перед развертыванием AirlinesReservationSample-0.0.1-SNAPSHOT.war. Инженеры по операциям также должны убедиться, что JDK, используемый на вашем компьютере, с помощью которого mvn clean package производится компиляция WAR-файла, соответствует тому же JRE, который используется сервером приложений. Управление этими зависимостями является сложным и трудоемким.
С помощью Dockerfile вы можете автоматически составить инструкции или уровни, необходимые для достижения этой цели, поэтапно добавляя шаги, чтобы убедиться, что система бронирования авиабилетов имеет все необходимые зависимости для развертывания в среде выполнения контейнеров Docker. Это решение представляет собой убедительное решение при работе с масштабированием по запросу в незапланированные моменты времени. Каждый слой использует кэш Docker, содержащий состояние образа контейнера на каждой вехе инструкции, оптимизируя время вычислений и повторное использование. Если слой не изменяется, используются кэшированные слои. Распространенные варианты использования кэшированных уровней — это среда выполнения Java, сервер приложений и другие зависимости для веб-приложения "Резервирование рейсов для резервирования авиакомпаний". Если и когда версия изменяется на ранее кэшированном слое, создается новая кэшированная запись.
На следующей схеме показаны слои образа контейнера. При выполнении команд в Dockerfile создаются слои. Верхний уровень — это система чтения и записи системы резервирования полетов для веб-приложения резервирования авиакомпаний. Этот слой построен поверх предыдущих слоев, которые являются только для чтения.
Docker имеет концепцию многоэтапных сборок, функцию, которая позволяет создавать меньший образ контейнера с улучшенным кэшированием и меньшим объемом безопасности, что позволяет повысить оптимизацию и обслуживание Dockerfile с течением времени. Например, можно разделить этап сборки контейнера для компиляции и создания приложения с этапа запуска приложения. Эта функция позволяет копировать только артефакты, созданные во время сборки, в производственный контейнерный образ, что уменьшает занимаемое пространство. Так как образы контейнеров кэшируются, если изменения отсутствуют, кэшированные образы можно повторно использовать, уменьшая затраты и время загрузки из сети.
Службы, предоставляемые в рабочей среде, должны тщательно контролироваться для обеспечения безопасности. Поэтому в рабочей среде используется и работает защищенный образ контейнера. В примере используется образ, предоставленный корпорацией Microsoft.
CBL-Mariner Linux — это упрощенная операционная система, содержащая только пакеты, необходимые для облачной среды. Его можно настроить с помощью пользовательских пакетов и инструментов в соответствии с требованиями приложения. CBL-Mariner проходит проверку Azure и совместима с агентами Azure. Корпорация Майкрософт создает и тестирует CBL-Mariner для использования различных вариантов использования, начиная от служб Azure до инфраструктуры Интернета вещей. Это внутренне рекомендуемый дистрибутив Linux для использования с облачными службами Майкрософт и связанными продуктами.
Заметка
Корпорация Майкрософт предоставляет образы контейнеров, упакованные с OpenJDK, включая Ubuntu, CBL-Marinerи distroless образы. Изображение distroless имеет наименьший размер, но запуск Tomcat на нем представляет сложность. Чтобы достичь упрощенного дизайна, distroless изображение удаляет множество команд и инструментов, включая оболочку, что означает, что вы не можете вызвать catalina.sh для запуска Tomcat. Образ distroless подходит для запуска исполняемых файлов JAR, таких как те, которые используются с Spring Boot или Quarkus.
В следующем примере одна и та же версия Microsoft Build OpenJDK используется как на этапе сборки, так и на последнем этапе. Этот подход гарантирует, что исходный код создается с той же версией JDK, что используется в развертывании службы Tomcat, что помогает избежать непредвиденного поведения из-за несоответствия версий.
На следующем рисунке показана многоэтапная сборка и то, что происходит на каждом этапе на основе команд, указанных в Dockerfile:
На этапе 0 Tomcat скачивается и распаковывается в каталог, указанный переменной окружения в образе Ubuntu. Переменная TOMCAT_VERSION указывает версию Tomcat для скачивания. Если выпущена новая версия Tomcat, следует обновить номер версии, так как новый образ извлекается только при изменении номера версии. В противном случае используется кэшированный образ. Скачанный Tomcat копируется в среду финальной стадии для использования.
На этапе 1 Maven устанавливается на образ Ubuntu, а созданные исходные коды и файлы конфигурации копируются перед созданием проекта Maven. Каждый из слоев кэшируется, поэтому слои образов ОС и Maven используют повторно этот кэш. Если файлы конфигурации, файлы исходного кода или веб-каталог обновляются, слои будут перестроены с этого момента. Если сборка успешно завершается без ошибок во время компиляции, создается артефакт с именем AirlinesReservationSample-0.0.1-SNAPSHOT.war в целевом каталоге. Этот артефакт копируется в последнюю среду этапа для использования.
На последнем этапе безопасный CBL-Mariner образ, предоставленный корпорацией Майкрософт, используется для копирования артефактов сборки Tomcat и Java с этапа 0 и этапа 1 соответственно. Пользователь с именем app владеет всеми файлами, используемыми в проекте, и приложение также запускается под пользователем app вместо использования привилегий root. Эта настройка гарантирует, что образ контейнера можно безопасно использовать без предоставления ненужных разрешений. Наконец, предоставляется номер порта 8080, и скрипт catalina.sh выполняется для запуска Tomcat. При запуске на локальном компьютере Docker Desktop вы можете получить доступ к нему по URL-адресу http://localhost:8080/AirlinesReservationSample.
В корневой папке проекта containerize-and-deploy-Java-app-to-Azure/Project/Airlines используйте следующую команду, чтобы создать файл с именем Dockerfile:
vi Dockerfile
Добавьте следующее содержимое в Файл Dockerfile, а затем сохраните и закройте его. Чтобы сохранить и выйти, нажмите клавишу ESC, введите :wq!, а затем нажмите клавишу ВВОД.
############################################
# Tomcat Intall stage
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat
ENV CATALINA_HOME=/usr/local/tomcat
# Configure Tomcat Version (Be sure to use the latest version)
ENV TOMCAT_VERSION=10.1.33
# Install Tomcat and required packages
RUN apt-get update ; \
apt-get install -y curl ; \
curl -O https://downloads.apache.org/tomcat/tomcat-10/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz ; \
tar xzf apache-tomcat-${TOMCAT_VERSION}.tar.gz ; \
mv apache-tomcat-${TOMCAT_VERSION} ${CATALINA_HOME} ; \
rm apache-tomcat-${TOMCAT_VERSION}.tar.gz && \
apt-get remove --purge -y curl && \
apt-get autoremove -y && \
apt-get clean
############################################
# Build stage (Compiles with Java 17)
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build
WORKDIR /build
# Install Maven
RUN apt-get update && apt-get install -y maven && mvn --version
# Copy source code
COPY pom.xml .
COPY src ./src
COPY web ./web
# Build the project
RUN mvn clean package
############################################
# Package final stage
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-mariner
# Configure the location of the Tomcat installation
ENV CATALINA_HOME=/usr/local/tomcat
# Configure the path to the Tomcat binaries
ENV PATH=$CATALINA_HOME/bin:$PATH
# This is the user that runs the Tomcat process
USER app
# Copy the Tomcat installation from the Tomcat stage
COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}
# Copy the Tomcat configuration files
COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf
# Copy the compiled WAR file from the build stage
COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war
# Expose the default Tomcat port
EXPOSE 8080
# Start Tomcat
CMD ["catalina.sh", "run"]
Заметка
При необходимости можно использовать файл Dockerfile_Solution в корне проекта, который содержит нужное содержимое.
Dockerfile разделен на три этапа, которые описаны в следующих таблицах:
Этап установки Tomcat:
Команда Docker Описание FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcatзадает базовый образ Microsoft Build of OpenJDK 17 на Ubuntu и называет этот этапtomcat. Здесь устанавливается Tomcat.ENVENV CATALINA_HOME=/usr/local/tomcatзадает переменную среды для каталога установки Tomcat.ENVENV TOMCAT_VERSION=10.1.33задает установленную версию Tomcat. При необходимости его следует обновить до последней версии.RUNКоманда RUNобновляет список пакетов, устанавливаетcurl, загружает указанную версию Tomcat, извлекает его, перемещает его в указанный каталог и очищает ненужные файлы и пакеты. Это гарантирует, что изображение остается легким.Этап сборки, который компилируется с помощью Java 17:
Команда Docker Описание FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS buildзадает базовый образ Microsoft Build of OpenJDK 17 на Ubuntu и называет этот этапbuild. Этот этап используется для компиляции приложения Java.WORKDIRWORKDIR /buildзадает рабочий каталог внутри контейнера/build, где исходный код копируется и компилируется.RUNRUN apt-get update && apt-get install -y maven && mvn --versionустанавливает Maven, средство автоматизации сборки, используемое для проектов Java, и проверяет его установку.COPYCOPY pom.xml .копирует файл конфигурации Maven в рабочий каталог. Этот файл необходим для создания проекта.COPYCOPY src ./srcкопирует каталог исходного кода в контейнер. Здесь находится код приложения Java.COPYCOPY web ./webкопирует каталог веб-ресурсов в контейнер. Сюда входят ресурсы веб-приложения, необходимые для сборки.RUNRUN mvn clean packageвыполняет процесс сборки Maven, который компилирует приложение Java и упаковает его в WAR-файл.Заключительный этап пакета:
Команда Docker Описание FROMFROM mcr.microsoft.com/openjdk/jdk:17-marinerзадает базовый образ на Microsoft Build OpenJDK 17 наCBL-Mariner, который используется для окончательного развертывания приложения.ENVENV CATALINA_HOME=/usr/local/tomcatзадает переменную среды для каталога установки Tomcat, аналогичную этапу установки.ENVENV PATH=$CATALINA_HOME/bin:$PATHдобавляет каталог bin Tomcat в системуPATH, позволяя командам Tomcat легко выполняться.USERUSER appуказывает пользователя, под которым выполняется процесс Tomcat, что повышает безопасность, так как процесс не выполняется от имени корневого пользователя.COPYCOPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}копирует установку Tomcat с этапаtomcat, устанавливая право владения для пользователяapp.COPYCOPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/confкопирует файл конфигурации пользователя Tomcat в контейнер, задав пользователю право владенияapp.COPYCOPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.warкопирует скомпилированный WAR-файл изbuildэтапа в каталог веб-приложений Tomcat, задав пользователю право владенияapp.EXPOSEEXPOSE 8080предоставляет порт 8080, порт по умолчанию для Tomcat, разрешающий внешний доступ к приложению.CMDCMD ["catalina.sh", "run"]указывает команду для запуска Tomcat при запуске контейнера.
Дополнительные сведения о построении Dockerfile см. в справочнике по Dockerfile.