Не кладіть жирові банки на зображення Docker

Опубліковано 14 жовтня 2019 р. Оновлено 10 червня 2020 р

Покласти банку з жиром у контейнер Docker - це марні витрати на зберігання, пропускну здатність та час. На щастя, ми можемо використати шарування зображень та кешування реєстру для створення додаткових збірок та дуже малих артефактів. Наприклад, ми могли б зменшити фактичний розмір нових артефактів з 75 МБ до лише одного МБ! І найкраще те, що є плагін для Maven і Gradle, який обробляє все за нас.

залежностей ресурсів

  • Жирна банка містить усі залежності, які зазвичай не змінюються між випусками. Але ці залежності копіюються знову і знову в кожну жирову банку, що призводить до втрати місця, пропускної здатності та часу.
  • Наприклад, баночка нашого додатка Spring Boot була 72 Мб, але містила лише 2 МБ коду. Зазвичай код є єдиною частиною, яку змінили.
  • На щастя, ми можемо використати шарування зображень Docker: розмістивши залежності та ресурси в різних шарах, ми можемо використовувати їх повторно і лише оновити код для кожного артефакту/випуску.
  • Jib надає простий у використанні плагін для Maven та Gradle для реалізації цього підходу. Не потрібно писати файл Docker вручну.

Механізм шару Docker потужний. Якщо всі ваші програми використовують одне і те ж базове зображення (наприклад, openjdk: 11.0.4-jre-slim), Docker повторно використовує шари ОС та JRE. Таким чином, ми економимо пам’ять у реєстрі Docker і пришвидшуємо завантаження та завантаження з реєстру, оскільки потрібно передавати менше МБ (Docker передає лише нові рівні до реєстру).

На жаль, багато додатків не використовують цей потужний механізм повністю, оскільки вони використовують жирові банки в контейнері Docker.

Кожен новий випуск створює новий рівень Docker розміром 72 МБ

Припустимо, наш додаток Spring Boot упакований у жирову банку. Ця жирова баночка розміром 72 Мб і додана в останньому рядку файлу Docker. Це означає, що кожен новий випуск займе 72 Мб пам’яті, а 72 Мб потрібно завантажувати та завантажувати з реєстру.

Тепер важливо уважніше розглянути ці 72 МБ:

Вміст жирної банки. Більшість його вмісту змінюється рідко, але він копіюється знову і знову в кожен артефакт.

Баночка містить три частини:

  • Залежності: Використані бібліотеки займають більшу частину розміру, але вони змінюються рідко. Більшу частину часу, коли ми створюємо випуск, ми торкалися лише нашого коду, а не залежностей. Проте залежності копіюються в кожен випуск.
  • Ресурси: В основному, тут та сама проблема. Хоча ресурси (HTML, CSS, зображення, файли конфігурації тощо) змінюються частіше, ніж залежності, вони все одно змінюються не так часто, як змінюється код. Але вони також дублюються в кожному випуску.
  • Код: Код містить лише невелику частку від загального розміру жирової банки (300 КБ - 2 МБ), але є найбільш часто змінюваною її частиною.

Тож код, який зазвичай змінюється для нового випуску, становить лише кілька МБ. І все-таки ми копіюємо всі залежності та ресурси знову і знову в кожному артефакті. Це втрата місця, пропускної здатності та часу.

Більше того, втрата місця стає ще гіршою, коли ви створюєте унікальний артефакт, який можна розгорнути для кожного коміту (використовуючи хеш коміту git як номер версії артефакту). Це має сенс для постійної доставки, але призводить до великого споживання пам’яті, оскільки кожен коміт займає додаткові 72 МБ.

Які корисні інструменти для аналізу зображень докера та візуалізації впливу жирових банок на зображення докерів? Це історія дайвінгу та докера .

Інтерактивне занурення з командного рядка показує шар жиру.

Історія docker також показує шар жирових банок:

На щастя, ми можемо скористатися механізмом шарування Docker; так само, як ми це вже робимо для ОС та рівня JRE. Ми розширюємо цей підхід, вводячи різні рівні для залежностей, ресурсів та коду. І ми впорядковуємо шари за частотою змін.

Розбиття програми на три різні рівні Docker для залежностей, ресурсів та коду. Зазвичай випуск тепер займе лише 2 МБ замість 72 МБ.

Тепер, якщо ми створюємо випуск, який складається лише із змін коду, нам потрібно лише 2 МБ пам’яті, оскільки шари для ресурсів та залежностей можна використовувати повторно. Вони вже є в реєстрі, і їх не потрібно переносити до нього знову.

Хороша новина: нам не потрібно вручну писати файли Docker для наших програм Java. Ми можемо використовувати Jib Google. Jib доступний як плагін для Maven і Gradle і спрощує контейнеризацію програм Java. Приємний крок для Jib можна знайти в блозі Google, але одна з характеристик для нас найважливіша: Jib сканує наш проект Java і створює різні рівні для залежностей, ресурсів та коду. Чудово, як Джиб працює нестандартно.

Які кроки?

  1. Додайте конфігурацію плагіна до нашого pom.xml:

  1. Прибуток. Історія дайвінгу та докера показує нову блискучу структуру шарів.

Три різні рівні залежностей, ресурсів та коду у нашому вбудованому образі докера за допомогою Jib

Необов’язкове прибирання

Очищення 1) Вимкніть плагін maven-deploy-plugin, maven-install-plugin та plugin maven-jar-plugin. Ці кроки більше не потрібні і не повинні виконуватися, навіть якщо розробник вводить mvn розгортання за незвичкою.

Очищення 2) Видаліть плагін spring-boot-maven-plugin, якщо ви використовуєте Spring Boot. Більше немає потреби створювати жирну баночку.

Jib дозволяє конфігурувати прапори JVM та аргументи програми в pom.xml. Але зазвичай ми не хочемо встановлювати ці речі під час збірки. Натомість конфігурація залежить від середовища розгортання (локального, контролю якості, виробничого). Тут ми хочемо встановити конфігурацію Spring та розмір JVM Heap.

  • Прапори JVM: Ми використовуємо змінну середовища JAVA_TOOL_OPTIONS, щоб додати прапори JVM, як розмір купи.
  • Весняна конфігурація: ми монтуємо зовнішній конфігураційний файл для розгортання в контейнер Docker і передаємо розташування як аргумент програми. Крім того, ви також можете використовувати для цього змінні середовища.

Номери версій для безперервної доставки з Maven та Docker

Підручник: Безперервна доставка з Докером та Дженкінсом

Створення мікросервісу Dropwizard за допомогою Docker та Maven

Не використовуйте для тестування бази даних в пам'яті (H2, Fongo)

Я - Філіп Хауер, і працюю керівником команди з футболки у Лейпцигу, Німеччина. Я зосереджуюсь на розробці веб-додатків на основі JVM, і я в захваті від Kotlin, чистого коду, розподілених систем, тестування та соціології розробки програмного забезпечення. Я пишу в Twitter під @philipp_hauer, і час від часу проводжу переговори.

  • Докер (11)
  • Котлін (11)
  • Кращі практики (8)
  • Відпочинок (8)
  • Збірка (7)
  • Чистий код (7)
  • Мейвен (7)
  • Ваадін (7)
  • MongoDB (6)
  • Тестування (6)
  • Мікропослуги (5)
  • Контейнери для випробувань (5)