Рубрики
Без рубрики

Повторное использование слоев Docker с пружинной загрузкой

В этом уроке мы увидим, как использовать новые возможности Spring Boot для повторного использования слоев Docker.

Автор оригинала: baeldung.

1. введение

Docker-это фактический стандарт для создания автономных приложений. Начиная с версии 2.3.0, Spring Boot включает в себя несколько улучшений, которые помогут нам создавать эффективные образы Docker. Таким образом, он позволяет декомпозировать приложение на разные слои .

Другими словами, исходный код находится в своем собственном слое. Поэтому его можно самостоятельно перестраивать, повышая эффективность и время запуска. В этом уроке мы увидим, как использовать новые возможности Spring Boot для повторного использования слоев Docker.

2. Многослойные банки в докере

Контейнеры Docker состоят из базового изображения и дополнительных слоев. Как только слои будут построены, они останутся в кэше. Поэтому последующие поколения будут намного быстрее:

Изменения в слоях нижнего уровня также перестраивают слои верхнего уровня. Таким образом, нечасто меняющиеся слои должны оставаться внизу, а часто меняющиеся-сверху.

Точно так же Spring Boot позволяет отображать содержимое артефакта в слои. Давайте посмотрим на отображение слоев по умолчанию:

Как мы видим, приложение имеет свой собственный слой. При изменении исходного кода перестраивается только независимый слой. Загрузчик и зависимости остаются в кэше, что сокращает время создания и запуска образа Docker. Давайте посмотрим, как это сделать с помощью Spring Boot!

3. Создание эффективных образов Docker с помощью Spring Boot

В традиционном способе создания образов Docker Spring Boot использует подход fat jar . В результате один артефакт встраивает все зависимости и исходный код приложения. Таким образом, любое изменение в нашем исходном коде приводит к перестройке всего слоя.

3.1. Конфигурация слоев с пружинной загрузкой

Spring Boot версии 2.3.0 вводит две новые функции для улучшения генерации образа Docker:

  • Поддержка Buildpack обеспечивает среду выполнения Java для приложения, поэтому теперь можно пропустить файл Docker и автоматически создать образ Docker
  • Многослойные банки помогите нам получить максимальную отдачу от генерации слоев Docker

В этом уроке мы расширим подход многоуровневой банки.

Сначала мы установим многослойную банку в Maven . При упаковке артефакта мы создадим слои. Давайте проверим файл jar:

jar tf target/spring-boot-docker-0.0.1-SNAPSHOT.jar

Как мы видим, создается новый файл layers .idx в папке BOOT-INF внутри fat jar. Конечно, он сопоставляет зависимости, ресурсы и исходный код приложения с независимыми слоями:

BOOT-INF/layers.idx

Аналогично, содержимое файла разбивает различные сохраненные слои:

- "dependencies":
  - "BOOT-INF/lib/"
- "spring-boot-loader":
  - "org/"
- "snapshot-dependencies":
- "application":
  - "BOOT-INF/classes/"
  - "BOOT-INF/classpath.idx"
  - "BOOT-INF/layers.idx"
  - "META-INF/"

3.2. Взаимодействие со слоями

Давайте перечислим слои внутри артефакта:

java -Djarmode=layertools -jar target/docker-spring-boot-0.0.1.jar list

Результат обеспечивает упрощенное представление содержимого файла layers.idx :

dependencies
spring-boot-loader
snapshot-dependencies
application

Мы также можем извлечь слои в папки:

java -Djarmode=layertools -jar target/docker-spring-boot-0.0.1.jar extract

Затем мы можем повторно использовать папки внутри файла Dockerfile, как мы увидим в следующем разделе:

$ ls
application/
snapshot-dependencies/
dependencies/
spring-boot-loader/

3.3. Конфигурация файла Dockerfile

Чтобы получить максимальную отдачу от возможностей Docker, нам нужно добавить слои к нашему изображению.

Во-первых, давайте добавим файл fat jar в базовое изображение:

FROM adoptopenjdk:11-jre-hotspot as builder
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar

Во-вторых, давайте извлекем слои артефакта:

RUN java -Djarmode=layertools -jar application.jar extract

Наконец, давайте скопируем извлеченные папки, чтобы добавить соответствующие слои Docker:

FROM adoptopenjdk:11-jre-hotspot
COPY --from=builder dependencies/ ./
COPY --from=builder snapshot-dependencies/ ./
COPY --from=builder spring-boot-loader/ ./
COPY --from=builder application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

При такой конфигурации, когда мы изменим наш исходный код, мы только перестроим уровень приложения. Остальное останется в кэше.

4. Пользовательские слои

Кажется, все работает как по волшебству. Но если мы внимательно посмотрим, уровень зависимостей не разделяется между нашими сборками . То есть все они сводятся к одному слою, даже внутренние. Поэтому, если мы изменим класс внутренней библиотеки, мы снова перестроим все слои зависимостей.

4.1. Настройка пользовательских слоев с помощью Spring Boot

В Spring Boot можно настроить пользовательские слои через отдельный файл конфигурации:


    
        
            org/springframework/boot/loader/**
        
        
    
    
        
            *:*:*SNAPSHOT
        
        
    
    
        dependencies
        spring-boot-loader
        snapshot-dependencies
        application
    

Как мы видим, мы сопоставляем и упорядочиваем зависимости и ресурсы по слоям. Кроме того, мы можем добавить столько пользовательских слоев, сколько захотим.

Давайте назовем наш файл layers.xml . Затем в Maven мы можем настроить этот файл для настройки слоев:


    org.springframework.boot
    spring-boot-maven-plugin
    
        
            true
            ${project.basedir}/src/layers.xml
        
    

Если мы упакуем артефакт, результат будет похож на поведение по умолчанию.

4.2. Добавление Новых Слоев

Давайте создадим внутреннюю зависимость, добавив наши классы приложений:


    com.baeldung.docker:*:*

Кроме того, мы закажем новый слой:


    internal-dependencies

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

dependencies
spring-boot-loader
internal-dependencies
snapshot-dependencies
application

4.3. Конфигурация файла Dockerfile

После извлечения мы можем добавить новый внутренний слой в наш образ Docker:

COPY --from=builder internal-dependencies/ ./

Итак, если мы создадим изображение, мы увидим, как Docker создает внутреннюю зависимость в качестве нового слоя:

$ mvn package
$ docker build -f src/main/docker/Dockerfile . --tag spring-docker-demo
....
Step 8/11 : COPY --from=builder internal-dependencies/ ./
 ---> 0e138e074118
.....

После этого мы можем проверить в истории состав слоев в изображении Docker:

$ docker history --format "{{.ID}} {{.CreatedBy}} {{.Size}}" spring-docker-demo
c0d77f6af917 /bin/sh -c #(nop)  ENTRYPOINT ["java" "org.s… 0B
762598a32eb7 /bin/sh -c #(nop) COPY dir:a87b8823d5125bcc4… 7.42kB
80a00930350f /bin/sh -c #(nop) COPY dir:3875f37b8a0ed7494… 0B
0e138e074118 /bin/sh -c #(nop) COPY dir:db6f791338cb4f209… 2.35kB
e079ad66e67b /bin/sh -c #(nop) COPY dir:92a8a991992e9a488… 235kB
77a9401bd813 /bin/sh -c #(nop) COPY dir:f0bcb2a510eef53a7… 16.4MB
2eb37d403188 /bin/sh -c #(nop)  ENV JAVA_HOME=/opt/java/o… 0B

Как мы видим, слой теперь включает в себя внутренние зависимости проекта.

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

В этом уроке мы показали, как создавать эффективные образы Docker. Короче говоря, мы использовали новые функции Spring Boot для создания многослойных банок. Для простых проектов мы можем использовать конфигурацию по умолчанию. Мы также продемонстрировали более продвинутую конфигурацию для повторного использования слоев.

Как всегда, код доступен на GitHub .