Перейти к основному содержимому

Создание Docker Image из Java Application

Profile picture
Автор
Harpal Singh
Software Engineer
Profile picture
Автор
Namastecode
Оглавление

1. Введение

Docker — хороший вариант, когда речь идёт о том, чтобы сделать приложения годными для развертывания в разных средах. В этом руководстве мы научимся упаковывать наши Java-приложения в Docker image, который будет одинаково работать в любой среде.

Мы будем использовать наше file-upload application, созданное ранее, и настроим его для сборки executable JAR file. Затем упакуем его в Docker image.

Давайте начнём.

2. Настройка нашего Java-проекта

Для этого руководства мы будем использовать Maven, чтобы управлять dependencies и build processes нашего проекта.

2.1 Конфигурация Maven (pom.xml)

Сначала давайте настроим наш файл pom.xml, чтобы упаковать jar file вместе со всеми его зависимостями. Для этого мы будем использовать maven-assembly-plugin, добавленный в секцию plugins в разделе <build>:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.5.0</version>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.namastecode.SpringBoot3ThymeleafApplication</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Давайте разберём важные части:

  • <mainClass> указывает entrypoint нашего приложения.
  • <descriptorRefs>, сконфигурированный с jar-with-dependencies, упакует наше приложение и все его зависимости в один JAR-файл.
  • <execution> указывает Maven запускаться во время фазы package Maven lifecycle.

Теперь, когда мы запускаем mvn package, Maven создаст два JAR-файла в директории target — один с dependencies и один без. JAR с dependencies будет иметь суффикс jar-with-dependencies.

Мы можем проверить, что приложение работает правильно, используя команду:

java -jar target/spring-boot-3-thymeleaf-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Теперь мы готовы создать Docker image.

3. Dockerize Java Application

Containers — отличный способ упаковать Java applications. Они обеспечивают согласованную среду для запуска приложений, независимо от того, где они развёрнуты. Давайте посмотрим, как создать Docker image для нашего Java application.

3.1 Создаём Dockerfile

Мы начинаем с добавления Dockerfile в корень нашего проекта:

spring-boot-3-thymeleaf/
├── src/
│   ├── main/
│   │   └── java/
│   │       └── com/namastecode/
|   |           |   -- Other files        
│   │           └── SpringBoot3ThymeleafApplication.java
│   └── test/
│       └── java/
├── pom.xml
└── Dockerfile

Файл Dockerfile — это просто текстовый файл, содержащий инструкции для Docker по сборке image. Каждая инструкция создаёт новый неизменяемый layer, который строится поверх предыдущего.

Мы начнём с определения нашего base image и working directory, куда мы хотим поместить наше приложение внутри container. Затем мы скопируем JAR file и добавим инструкции для его запуска:

FROM eclipse-temurin:23-jre-alpine

WORKDIR /app

COPY target/spring-boot-3-thymeleaf-0.0.1-SNAPSHOT-jar-with-dependencies.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

Для нашего базового образа мы используем eclipse-temurin:23-jre-alpine, который является лёгкой версией JRE (Java Runtime Environment), основанной на Alpine Linux. Это отличный выбор для запуска Java-приложений в контейнере, когда не требуются какие-либо специфические зависимости.

Мы определяем /app как working directory внутри container. Здесь наше приложение будет скопировано с помощью команды COPY. Наконец, мы задаём entrypoint для запуска нашего приложения командой java -jar. Entrypoint — это команда, которая будет выполняться при старте контейнера.

3.2 Создание Docker Image

Теперь мы запускаем команду build, чтобы создать новый image из корня нашего проекта:

docker build -t spring-boot-3-thymeleaf .
Убедимся, что у нас запущен Docker daemon для этого шага — иначе мы получим ошибку. Также не забудьте . в конце command, он указывает Docker искать Dockerfile в current directory.

После того как образ создан, мы можем просто выполнить docker image ls, чтобы убедиться, что образ был успешно собран.

3.3 Запуск Docker Image

Наконец, давайте запустим наше Dockerized Java-приложение:

docker run -p 8090:8090 spring-boot-3-thymeleaf:latest

Это запустит новый container и выполнит наш Java application внутри него. Мы должны увидеть logs от нашего Spring Boot application в terminal. Также мы сопоставляем порт 8090 на host с портом 8090 в container — это port, который использует наш Spring Boot application. Чтобы проверить, что приложение запущено, мы можем открыть http://localhost:8090 в нашем web browser.

4. Заключение

В этом руководстве мы научились создавать Docker image из Java-приложения. Мы начали с настройки нашего Maven-проекта, чтобы упаковать приложение вместе со всеми его dependencies, затем создали Dockerfile для определения образа и, наконец, собрали и запустили Docker image.

Вы можете найти полный code on GitHub.

Related

Как загрузить файл в Spring Boot
Давайте узнаем, как реализовать file uploads в Spring Boot, настроить size limits и аккуратно обрабатывать потенциальные ошибки с помощью Thymeleaf и Spring MVC.
Как выполнять повторные попытки с помощью Restclient
Давайте узнаем, как реализовать retryable calls с помощью RestClient при поддержке spring-retry. Систематически обрабатываем временные сбои при выполнении HTTP-запросов.
Http Requests с Rest Client в Spring Framework 6
В этом руководстве объясняется, как использовать RestClient API в Spring 6.1 для выполнения HTTP-запросов. Мы рассматриваем настройку и кастомизацию RestClient, обработку запросов (GET, POST, PUT, DELETE) и приводим пример его использования с OpenAI API. Также мы обсуждаем обработку ошибок. К концу руководства мы будем знать, как эффективно использовать RestClient в наших проектах и понимать его преимущества по сравнению с RestTemplate.