Оптимізація Docker-образів: скорочуємо розмір і прискорюємо деплой

Docker-образи непомітно розростаються, і кожна збірка займає дедалі більше часу, а викочування версії перетворюється на довге очікування. Ми переробляємо збірку під ключ: скорочуємо розмір образів і час їх підготовки, прибираємо зайві шари та залишки попередніх версій. Результат — викочування версії прискорюється в рази, а збої під час оновлення перестають бути нормою.
Часті запитання

Оптимізація docker-образів: де інфраструктура втрачає час

Перше вузьке місце — збірка. Якщо в образ копіюється весь проєкт цілком до встановлення залежностей, будь-яка правка в коді обнуляє кеш шарів, і встановлення пакетів запускається заново.

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

Звідси другий ефект — розмір образу. База загального призначення з повним набором утиліт нерідко переважує сам застосунок у рази.

Тоді кожна викатка змушує кожну ноду заново тягнути цю вагу з реєстру: час деплою зростає, автоматичне масштабування не встигає за навантаженням, а сам реєстр розростається.

Третя проблема — розбіжність середовищ. Коли образи збираються «приблизно однаково», у прод їдуть різні версії базового шару й різний набір системних бібліотек, і помилка відтворюється лише на бойовому контурі.

Зворотний бік — відкат: без незмінних тегів і зрозумілого зв'язку образу з релізом повернення до попередньої версії перетворюється на години ручної роботи під тиском.

Оптимізація docker-образів закриває все це одним контуром: багатоетапна збірка, порядок шарів під кеш, тонка база й фіксовані теги. Нижче розбираємо, як це влаштовано, що саме змінюється в часі збірки, доставки й відкату та з чого почати, якщо контур уже працює.

Що змінюється після переробки збірки: швидкість і стабільність

Переробка збірки контейнерних образів Docker не змінює функціональність продукту, але рухає три вимірювані величини: розмір артефакту, тривалість релізного вікна й час повернення до попередньої версії.

Перше видно в логах вивантаження на вузли, друге — у тривалості викатки, третє — у тому, як швидко сервіс піднімається після невдалого релізу.

Розмір образу й швидкість вивантаження

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

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

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

Передбачуваний відкат — наслідок того ж: попередня версія залишається в локальному кеші вузлів, повернення до неї йде без перезбирання, і час відновлення вимірюється хвилинами, а не завантаженням реєстру.

Клас відмов через розбіжність оточень зникає

Середовища перестають розходитися, коли версії системних бібліотек, налаштування локалі, непривілейований користувач і робочі шляхи задані в одному базовому шарі, а не підтягуються з того, що виявилося на вузлі.

Однаковий набір файлів у збірці й у середовищі виконання прибирає розриви виду «у мене працює, а в середовищі падає»: така відмова тепер ловиться максимум на тестовому контурі й не доходить до продуктивного середовища.

Разом із цим змінюється ціна аварії. Аварійних викаток стає менше, а сервіс повертається в стрій за хвилини — на версію, яка вже перевірена.

Порівняння підходів до збірки образів: що і коли підходить

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

Варіант Коли підходить Обмеження
Встановлення залежностей поверх готового базового образу Прототипи, внутрішні сервіси з коротким життєвим циклом В образ потрапляють компілятори й заголовні файли; кешування шарів ламається за будь-якої зміни манифесту залежностей
Багатоступенева збірка Більшість сервісів на компільованих мовах Потрібно стежити, щоб артефакт збірки копіювався, а не перезбирався заново
Перепакування застосунку на мінімальний базовий образ Сервіси з жорсткими вимогами до поверхні атаки Потребує перевірки сумісності бібліотек часу виконання, налагодження ускладнюється
Збірка без мережі з готового артефакту Регулярні релізи, відтворювані збірки Потрібен окремий крок підготовки артефакту в конвеєрі збірки

Критерії вибору

Дивіться на три речі: частка незмінних шарів між релізами, вимоги безпеки до вмісту образу й частота правок у залежностях. Якщо манифест залежностей змінюється рідше за код, основний виграш дає кешування шарів — і багатоступенева збірка окупається одразу.

Гібридний режим

На практиці найчастіше працює комбінація: збірка на окремому етапі, копіювання артефакту в мінімальний базовий образ і кеш на шарі залежностей.

Такий варіант закриває і розмір, і швидкість повторних збірок, а відкат залишається передбачуваним: образ попереднього релізу вже лежить у реєстрі.

Порядок робіт: від аудиту збірки до передачі регламентів

Перш ніж щось міняти, фіксуємо точку відліку: розмір образу, час збірки й викатки, частку шарів, які перезбираються за правки одного рядка коду. Без цих цифр оптимізація перетворюється на суперечку про смаки, тому аудит збірки йде першим кроком.

Проєктування

  1. Аудит збірки — знімаємо метрики по кожному сервісу, розбираємо склад образу й знаходимо, що потрапляє в прод із тестових залежностей і кешу пакетного менеджера.
  2. Схема конвеєра — описуємо шлях від коміту до викатки, відзначаємо, де збірка дублюється, а кеш не перевикористовується між запусками.
  3. Налаштування реєстру — задаємо правила зберігання й тегування: старі шари не накопичуються, відкат на попередню збірку залишається доступним.

Збірка, перевірка, передача

  • Переробка опису збірки — багатоступенева збірка, у фінальний образ лише рантайм-залежності, порядок шарів за частотою змін.
  • Перевірка образу — сканування на вразливості, порівняння розміру й часу старту до і після, прогін на стенді.
  • Викатка — поступове перемикання сервісів із можливістю повернутися на попередній тег.
  • Передача регламентів — правила тегування, чек-лист для нових сервісів та інструкція з локальної збірки, щоб команда підтримувала результат сама.

Конфігурації, схеми та регламенти: що передаємо команді

Усе, що робиться в ході робіт, залишається у вашої команди файлами в репозиторії, а не усними домовленостями. Передаємо два блоки: як образ збирається і як він потрапляє в продакшн.

Конфігурація й схема збірки

  • Багатоступеневий Dockerfile з розділенням збірки й рантайму: у фінальний образ потрапляють лише артефакти й залежності часу виконання.
  • .dockerignore і порядок інструкцій, за якого шари, що рідко змінюються, кешуються, а правка коду не тягне перезбирання залежностей.
  • Конфігурація збірки в конвеєрі: параметри збирача, тегування за комітом і міткою оточення, перевірка образу на вразливості до публікації.
  • Схема збірки й доставки — діаграма «коміт → збірка → перевірки → реєстр → оточення» з відзначеними точками відкату.
  • Базові образи: обране сімейство, спосіб закріплення версії за дайджестом і порядок заміни.

Реєстр, документація й регламенти

  • Політика доступу до реєстру: ролі на збірку, читання й публікацію, окремий обліковий запис для конвеєра, заборона анонімного завантаження.
  • Правила зберігання: скільки образів на тег залишається, що чиститься автоматично, як виконується повернення на попередній реліз.
  • Документація: структура шарів, де лежать конфігурації, як відтворити збірку локально й куди дивитися при падінні.
  • Регламент оновлення базових образів і залежностей: періодичність, відповідальний, перевірка сумісності після оновлення.

Документи живуть поруч із кодом — за наступної зміни команда править конфігурацію, а не відновлює логіку з листування.

Кейс: як переробка збірки змінила метрики експлуатації

Сервіс із релізами двічі на день, і один образ на весь застосунок: рантайм, залежності збірки й тестові утиліти в спільному шарі. За будь-якої зміни коду образ перезбирався цілком, кеш шарів не працював, бо залежності й вихідники лежали в одному кроці. Збірка йшла на спільній складальній машині разом із чужими задачами.

Вихідні метрики

  • Повна збірка — 14 хвилин, із них 9 на перевстановлення залежностей.
  • Частка успішних збірок — 6 із 10: конвеєр падав на завантаженні пакетів і на нестачі ресурсів.
  • Час відкату — близько 40 хвилин, бо попередній образ збирали заново, а тег перезаписувався.
  • Простій під час інциденту — до години, поки новий артефакт не проходив перевірки.

Результат впровадження

Рознесли збірку й рантайм на багатоетапну схему в Docker: залежності окремим шаром, який змінюється рідко, код — поверх нього. Базовий образ замінили на мінімальний, тег стали прив'язувати до коміту, а не до «останнього».

Розмір артефакту зменшився в шість разів, збірка займає 4 хвилини, частка успішних збірок зросла до 19 із 20. Відкат звели до перемикання тегу — менше хвилини, простій на інцидент скоротився в рази.

Метрики експлуатації тепер знімаються автоматично: тривалість збірки, частка успішних викаток і час відкату видно по кожному релізу.

Що робити, якщо збірка вже йде в робочому контурі?

Зупиняти релізи заради переходу не можна, тому ми не замінюємо складальний контур, а піднімаємо поруч другий. Обидва маршрути якийсь час працюють паралельно: старий продовжує збирати й викладати поточні версії, новий збирає ті самі сервіси компактнішими шарами.

Порівняння йде на живому трафіку, а не на стенді, тому розбіжності в поведінці випливають до того, як старий контур виключать.

Поетапний перехід іде по одному сервісу — починаючи з тих, що не тримають критичний шлях. Сумісність перевіряємо до перемикання: базовий шар, користувач усередині контейнера, точки монтування, змінні оточення, liveness-перевірка, обробка сигналу зупинки. Застосунок не повинен помічати підміни образу, інакше це вже не міграція, а переписування.

Закритий реєстр тримає обидві гілки образів поруч, тому перемикання відбувається на рівні посилання, а не нової збірки. Точка повернення є на кожному кроці: попередній тег залишається доступним, відкат займає хвилини й не потребує участі розробників. Політика зберігання в реєстрі при цьому стежить, щоб старі шари не накопичувалися безкінечно.

План міграції фіксуємо до старту: порядок сервісів, критерій готовності кожного етапу, хто відповідає за перемикання, у який момент старий контур виводиться з роботи. Зазвичай повний перехід займає кілька тижнів, і жоден реліз за цей час не зупиняється.

Часті технічні питання про переробку збірки

Питання, які найчастіше випливають до старту, стосуються не самого стиснення, а того, як перероблена збірка лягає на поточний процес: закритий контур без зовнішніх дзеркал, необхідність правити код, поведінка відкатів. Нижче — відповіді на інженерні сумніви, які ми розбираємо з командою замовника на етапі оцінки.

Як збірка живе в закритому контурі без зовнішніх дзеркал?

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

Чи доведеться змінювати код застосунку?

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

Що відбувається з відкатом на попередній реліз?

Образи версіонуються незмінними мітками, відкат — це перемикання на попередню мітку без перезбирання. Ми налаштовуємо правило зберігання, яке тримає останні збірки кожного релізу й чистить решту: реєстр не зростає безконтрольно, а точка повернення завжди є.

Наскільки скоротиться розмір образу й час збірки?

Розмір падає в рази, коли складальні інструменти й проміжні файли йдуть в окремий етап і не потрапляють у фінальний образ. Час збірки скорочується завдяки порядку шарів і кешу — повторні збірки без змін у залежностях проходять у 2-4 рази швидше.

Хто підтримує збірку після передачі?

Ми віддаємо регламент оновлення базових шарів, перевірки вразливостей і контролю зростання реєстру, щоб команда вела це сама. Далі — супровід за договором: оновлення, розбір збоїв збірки, ревізія правил при зміні стеку.

Обговоримо задачу: надішлемо оцінку й план робіт

Щоб оцінка була предметною, а не «на око», нам потрібен мінімум вихідних даних по вашій збірці. Ми дивимося Dockerfile і шари, кеш, базові образи, реєстр і пайплайн, після чого повертаємося з планом впровадження й строками — за етапами, з точками відкату. Нижче те, що прискорює розбір; чогось може не бути, частину зберемо на дзвінку.

  • Схема поточної збірки: Dockerfile (або кілька), порядок шарів, multi-stage збірка, як влаштований кеш і чим він зараз інвалідується.
  • Обмеження контуру: де зберігаються образи, чи є приватний реєстр, вимоги безпеки й підпису, ліміти на розмір артефакту, доступність зовнішніх базових образів.
  • Вимоги до строків викатки: поточний час збірки й деплою, що вважається прийнятним, наскільки критичний cold start і час відкату на попередній реліз.
  • Ролі й доступи: хто володіє пайплайном, хто погоджує зміни базових образів і політик реєстру, кому віддаємо результат.
  • Очікуваний ефект: що важливіше — скоротити розмір образів, прискорити збірку завдяки кешу чи знизити ризики вразливостей; як плануєте це вимірювати.
  • Обмеження середовища: архітектури (amd64/arm64), ОС, оркестратор, режим запуску, вимоги до недоторканності продакшену.
  • Що вже пробували і чому не злетіло — це економить нам етап гіпотез.

Напишіть у двох словах, яка у вас задача і що з переліченого є під рукою, — повернемося з оцінкою, планом впровадження й строками за етапами.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139