Контейнеризация приложения Java

Завершено

В этом уроке вы контейнеризируете приложение Java.

Как упоминалось ранее, контейнеры выполняются непосредственно поверх хост-системы, ядра и оборудования как обычные системные процессы. Контейнеры требуют меньше системных ресурсов, что приводит к меньшему объему ресурсов, меньшему объему затрат и более быстрому времени запуска приложения. Эти преимущества являются отличными вариантами использования для масштабирования по требованию.

Существуют контейнеры Windows и контейнеры Linux. В этом модуле используется широко используемая среда выполнения Docker для создания образа контейнера Linux. Затем вы развернете образ контейнера Linux в операционной системе узла локального компьютера. Наконец, вы развернете образ контейнера Linux в службе Azure Kubernetes.

Обзор Docker

Среда выполнения 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.

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:

Схема, на которой показана сборка Docker multistage.

На этапе 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 Описание
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat задает базовый образ Microsoft Build of OpenJDK 17 на Ubuntu и называет этот этап tomcat. Здесь устанавливается Tomcat.
    ENV ENV CATALINA_HOME=/usr/local/tomcat задает переменную среды для каталога установки Tomcat.
    ENV ENV TOMCAT_VERSION=10.1.33 задает установленную версию Tomcat. При необходимости его следует обновить до последней версии.
    RUN Команда RUN обновляет список пакетов, устанавливает curl, загружает указанную версию Tomcat, извлекает его, перемещает его в указанный каталог и очищает ненужные файлы и пакеты. Это гарантирует, что изображение остается легким.
  • Этап сборки, который компилируется с помощью Java 17:

    Команда Docker Описание
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build задает базовый образ Microsoft Build of OpenJDK 17 на Ubuntu и называет этот этап build. Этот этап используется для компиляции приложения Java.
    WORKDIR WORKDIR /build задает рабочий каталог внутри контейнера /build, где исходный код копируется и компилируется.
    RUN RUN apt-get update && apt-get install -y maven && mvn --version устанавливает Maven, средство автоматизации сборки, используемое для проектов Java, и проверяет его установку.
    COPY COPY pom.xml . копирует файл конфигурации Maven в рабочий каталог. Этот файл необходим для создания проекта.
    COPY COPY src ./src копирует каталог исходного кода в контейнер. Здесь находится код приложения Java.
    COPY COPY web ./web копирует каталог веб-ресурсов в контейнер. Сюда входят ресурсы веб-приложения, необходимые для сборки.
    RUN RUN mvn clean package выполняет процесс сборки Maven, который компилирует приложение Java и упаковает его в WAR-файл.
  • Заключительный этап пакета:

    Команда Docker Описание
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-mariner задает базовый образ на Microsoft Build OpenJDK 17 на CBL-Mariner, который используется для окончательного развертывания приложения.
    ENV ENV CATALINA_HOME=/usr/local/tomcat задает переменную среды для каталога установки Tomcat, аналогичную этапу установки.
    ENV ENV PATH=$CATALINA_HOME/bin:$PATH добавляет каталог bin Tomcat в систему PATH, позволяя командам Tomcat легко выполняться.
    USER USER app указывает пользователя, под которым выполняется процесс Tomcat, что повышает безопасность, так как процесс не выполняется от имени корневого пользователя.
    COPY COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME} копирует установку Tomcat с этапа tomcat, устанавливая право владения для пользователя app.
    COPY COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf копирует файл конфигурации пользователя Tomcat в контейнер, задав пользователю право владения app .
    COPY COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war копирует скомпилированный WAR-файл из build этапа в каталог веб-приложений Tomcat, задав пользователю право владения app .
    EXPOSE EXPOSE 8080 предоставляет порт 8080, порт по умолчанию для Tomcat, разрешающий внешний доступ к приложению.
    CMD CMD ["catalina.sh", "run"] указывает команду для запуска Tomcat при запуске контейнера.

Дополнительные сведения о построении Dockerfile см. в справочнике по Dockerfile.