Оптимізація docker-образів: де інфраструктура втрачає час
Перше вузьке місце — збірка. Якщо в образ копіюється весь проєкт цілком до встановлення залежностей, будь-яка правка в коді обнуляє кеш шарів, і встановлення пакетів запускається заново.
Шари образу перезбираються повністю, час збірки зростає з кожною ітерацією, а в проміжних шарах залишаються компілятори, заголовні файли й кеш пакетного менеджера, якому в проді робити нічого.
Звідси другий ефект — розмір образу. База загального призначення з повним набором утиліт нерідко переважує сам застосунок у рази.
Тоді кожна викатка змушує кожну ноду заново тягнути цю вагу з реєстру: час деплою зростає, автоматичне масштабування не встигає за навантаженням, а сам реєстр розростається.
Третя проблема — розбіжність середовищ. Коли образи збираються «приблизно однаково», у прод їдуть різні версії базового шару й різний набір системних бібліотек, і помилка відтворюється лише на бойовому контурі.
Зворотний бік — відкат: без незмінних тегів і зрозумілого зв'язку образу з релізом повернення до попередньої версії перетворюється на години ручної роботи під тиском.
Оптимізація docker-образів закриває все це одним контуром: багатоетапна збірка, порядок шарів під кеш, тонка база й фіксовані теги. Нижче розбираємо, як це влаштовано, що саме змінюється в часі збірки, доставки й відкату та з чого почати, якщо контур уже працює.
Що змінюється після переробки збірки: швидкість і стабільність
Переробка збірки контейнерних образів Docker не змінює функціональність продукту, але рухає три вимірювані величини: розмір артефакту, тривалість релізного вікна й час повернення до попередньої версії.
Перше видно в логах вивантаження на вузли, друге — у тривалості викатки, третє — у тому, як швидко сервіс піднімається після невдалого релізу.
Розмір образу й швидкість вивантаження
Основний виграш дає розділення збірки на етапи: залежності ставляться окремим шаром і беруться з кешу, поки не змінився їхній список, а вихідний код лягає зверху й оновлюється щоразу.
З фінальної стадії прибираємо все, що потрібне лише для збірки: компілятори, заголовні файли, проміжні артефакти й службовий кеш.
Артефакт зменшується в рази, вивантаження на кожен вузол і підготовка до запуску займають менше часу — прискорення деплою помітне вже на першому релізі.
Передбачуваний відкат — наслідок того ж: попередня версія залишається в локальному кеші вузлів, повернення до неї йде без перезбирання, і час відновлення вимірюється хвилинами, а не завантаженням реєстру.
Клас відмов через розбіжність оточень зникає
Середовища перестають розходитися, коли версії системних бібліотек, налаштування локалі, непривілейований користувач і робочі шляхи задані в одному базовому шарі, а не підтягуються з того, що виявилося на вузлі.
Однаковий набір файлів у збірці й у середовищі виконання прибирає розриви виду «у мене працює, а в середовищі падає»: така відмова тепер ловиться максимум на тестовому контурі й не доходить до продуктивного середовища.
Разом із цим змінюється ціна аварії. Аварійних викаток стає менше, а сервіс повертається в стрій за хвилини — на версію, яка вже перевірена.
Порівняння підходів до збірки образів: що і коли підходить
Вибір способу збірки задає три параметри: розмір образу, швидкість повторної збірки й те, скільки часу команда витрачає на розбір розбіжностей між оточеннями. Нижче — чотири варіанти, між якими реально обирають на проєктах, і межі застосовності кожного.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Встановлення залежностей поверх готового базового образу | Прототипи, внутрішні сервіси з коротким життєвим циклом | В образ потрапляють компілятори й заголовні файли; кешування шарів ламається за будь-якої зміни манифесту залежностей |
| Багатоступенева збірка | Більшість сервісів на компільованих мовах | Потрібно стежити, щоб артефакт збірки копіювався, а не перезбирався заново |
| Перепакування застосунку на мінімальний базовий образ | Сервіси з жорсткими вимогами до поверхні атаки | Потребує перевірки сумісності бібліотек часу виконання, налагодження ускладнюється |
| Збірка без мережі з готового артефакту | Регулярні релізи, відтворювані збірки | Потрібен окремий крок підготовки артефакту в конвеєрі збірки |
Критерії вибору
Дивіться на три речі: частка незмінних шарів між релізами, вимоги безпеки до вмісту образу й частота правок у залежностях. Якщо манифест залежностей змінюється рідше за код, основний виграш дає кешування шарів — і багатоступенева збірка окупається одразу.
Гібридний режим
На практиці найчастіше працює комбінація: збірка на окремому етапі, копіювання артефакту в мінімальний базовий образ і кеш на шарі залежностей.
Такий варіант закриває і розмір, і швидкість повторних збірок, а відкат залишається передбачуваним: образ попереднього релізу вже лежить у реєстрі.
Порядок робіт: від аудиту збірки до передачі регламентів
Перш ніж щось міняти, фіксуємо точку відліку: розмір образу, час збірки й викатки, частку шарів, які перезбираються за правки одного рядка коду. Без цих цифр оптимізація перетворюється на суперечку про смаки, тому аудит збірки йде першим кроком.
Проєктування
- Аудит збірки — знімаємо метрики по кожному сервісу, розбираємо склад образу й знаходимо, що потрапляє в прод із тестових залежностей і кешу пакетного менеджера.
- Схема конвеєра — описуємо шлях від коміту до викатки, відзначаємо, де збірка дублюється, а кеш не перевикористовується між запусками.
- Налаштування реєстру — задаємо правила зберігання й тегування: старі шари не накопичуються, відкат на попередню збірку залишається доступним.
Збірка, перевірка, передача
- Переробка опису збірки — багатоступенева збірка, у фінальний образ лише рантайм-залежності, порядок шарів за частотою змін.
- Перевірка образу — сканування на вразливості, порівняння розміру й часу старту до і після, прогін на стенді.
- Викатка — поступове перемикання сервісів із можливістю повернутися на попередній тег.
- Передача регламентів — правила тегування, чек-лист для нових сервісів та інструкція з локальної збірки, щоб команда підтримувала результат сама.
Конфігурації, схеми та регламенти: що передаємо команді
Усе, що робиться в ході робіт, залишається у вашої команди файлами в репозиторії, а не усними домовленостями. Передаємо два блоки: як образ збирається і як він потрапляє в продакшн.
Конфігурація й схема збірки
- Багатоступеневий Dockerfile з розділенням збірки й рантайму: у фінальний образ потрапляють лише артефакти й залежності часу виконання.
.dockerignoreі порядок інструкцій, за якого шари, що рідко змінюються, кешуються, а правка коду не тягне перезбирання залежностей.- Конфігурація збірки в конвеєрі: параметри збирача, тегування за комітом і міткою оточення, перевірка образу на вразливості до публікації.
- Схема збірки й доставки — діаграма «коміт → збірка → перевірки → реєстр → оточення» з відзначеними точками відкату.
- Базові образи: обране сімейство, спосіб закріплення версії за дайджестом і порядок заміни.
Реєстр, документація й регламенти
- Політика доступу до реєстру: ролі на збірку, читання й публікацію, окремий обліковий запис для конвеєра, заборона анонімного завантаження.
- Правила зберігання: скільки образів на тег залишається, що чиститься автоматично, як виконується повернення на попередній реліз.
- Документація: структура шарів, де лежать конфігурації, як відтворити збірку локально й куди дивитися при падінні.
- Регламент оновлення базових образів і залежностей: періодичність, відповідальний, перевірка сумісності після оновлення.
Документи живуть поруч із кодом — за наступної зміни команда править конфігурацію, а не відновлює логіку з листування.
Кейс: як переробка збірки змінила метрики експлуатації
Сервіс із релізами двічі на день, і один образ на весь застосунок: рантайм, залежності збірки й тестові утиліти в спільному шарі. За будь-якої зміни коду образ перезбирався цілком, кеш шарів не працював, бо залежності й вихідники лежали в одному кроці. Збірка йшла на спільній складальній машині разом із чужими задачами.
Вихідні метрики
- Повна збірка — 14 хвилин, із них 9 на перевстановлення залежностей.
- Частка успішних збірок — 6 із 10: конвеєр падав на завантаженні пакетів і на нестачі ресурсів.
- Час відкату — близько 40 хвилин, бо попередній образ збирали заново, а тег перезаписувався.
- Простій під час інциденту — до години, поки новий артефакт не проходив перевірки.
Результат впровадження
Рознесли збірку й рантайм на багатоетапну схему в Docker: залежності окремим шаром, який змінюється рідко, код — поверх нього. Базовий образ замінили на мінімальний, тег стали прив'язувати до коміту, а не до «останнього».
Розмір артефакту зменшився в шість разів, збірка займає 4 хвилини, частка успішних збірок зросла до 19 із 20. Відкат звели до перемикання тегу — менше хвилини, простій на інцидент скоротився в рази.
Метрики експлуатації тепер знімаються автоматично: тривалість збірки, частка успішних викаток і час відкату видно по кожному релізу.
Що робити, якщо збірка вже йде в робочому контурі?
Зупиняти релізи заради переходу не можна, тому ми не замінюємо складальний контур, а піднімаємо поруч другий. Обидва маршрути якийсь час працюють паралельно: старий продовжує збирати й викладати поточні версії, новий збирає ті самі сервіси компактнішими шарами.
Порівняння йде на живому трафіку, а не на стенді, тому розбіжності в поведінці випливають до того, як старий контур виключать.
Поетапний перехід іде по одному сервісу — починаючи з тих, що не тримають критичний шлях. Сумісність перевіряємо до перемикання: базовий шар, користувач усередині контейнера, точки монтування, змінні оточення, liveness-перевірка, обробка сигналу зупинки. Застосунок не повинен помічати підміни образу, інакше це вже не міграція, а переписування.
Закритий реєстр тримає обидві гілки образів поруч, тому перемикання відбувається на рівні посилання, а не нової збірки. Точка повернення є на кожному кроці: попередній тег залишається доступним, відкат займає хвилини й не потребує участі розробників. Політика зберігання в реєстрі при цьому стежить, щоб старі шари не накопичувалися безкінечно.
План міграції фіксуємо до старту: порядок сервісів, критерій готовності кожного етапу, хто відповідає за перемикання, у який момент старий контур виводиться з роботи. Зазвичай повний перехід займає кілька тижнів, і жоден реліз за цей час не зупиняється.
Часті технічні питання про переробку збірки
Питання, які найчастіше випливають до старту, стосуються не самого стиснення, а того, як перероблена збірка лягає на поточний процес: закритий контур без зовнішніх дзеркал, необхідність правити код, поведінка відкатів. Нижче — відповіді на інженерні сумніви, які ми розбираємо з командою замовника на етапі оцінки.
Як збірка живе в закритому контурі без зовнішніх дзеркал?
Базові шари й залежності один раз переносяться у внутрішній реєстр образів, збірка йде на своїх агентах і назовні не звертається. Кеш шарів зберігається локально, тому повторні збірки не ходять у зовнішню мережу й не залежать від доступності чужих репозиторіїв.
Чи доведеться змінювати код застосунку?
У більшості випадків правки обмежені файлом збірки й порядком шарів — логіка застосунку не зачіпається. Код змінюється лише там, де знайдеться зайва залежність або важкий артефакт, який можна винести з фінального образу.
Що відбувається з відкатом на попередній реліз?
Образи версіонуються незмінними мітками, відкат — це перемикання на попередню мітку без перезбирання. Ми налаштовуємо правило зберігання, яке тримає останні збірки кожного релізу й чистить решту: реєстр не зростає безконтрольно, а точка повернення завжди є.
Наскільки скоротиться розмір образу й час збірки?
Розмір падає в рази, коли складальні інструменти й проміжні файли йдуть в окремий етап і не потрапляють у фінальний образ. Час збірки скорочується завдяки порядку шарів і кешу — повторні збірки без змін у залежностях проходять у 2-4 рази швидше.
Хто підтримує збірку після передачі?
Ми віддаємо регламент оновлення базових шарів, перевірки вразливостей і контролю зростання реєстру, щоб команда вела це сама. Далі — супровід за договором: оновлення, розбір збоїв збірки, ревізія правил при зміні стеку.
Обговоримо задачу: надішлемо оцінку й план робіт
Щоб оцінка була предметною, а не «на око», нам потрібен мінімум вихідних даних по вашій збірці. Ми дивимося Dockerfile і шари, кеш, базові образи, реєстр і пайплайн, після чого повертаємося з планом впровадження й строками — за етапами, з точками відкату. Нижче те, що прискорює розбір; чогось може не бути, частину зберемо на дзвінку.
- Схема поточної збірки: Dockerfile (або кілька), порядок шарів, multi-stage збірка, як влаштований кеш і чим він зараз інвалідується.
- Обмеження контуру: де зберігаються образи, чи є приватний реєстр, вимоги безпеки й підпису, ліміти на розмір артефакту, доступність зовнішніх базових образів.
- Вимоги до строків викатки: поточний час збірки й деплою, що вважається прийнятним, наскільки критичний cold start і час відкату на попередній реліз.
- Ролі й доступи: хто володіє пайплайном, хто погоджує зміни базових образів і політик реєстру, кому віддаємо результат.
- Очікуваний ефект: що важливіше — скоротити розмір образів, прискорити збірку завдяки кешу чи знизити ризики вразливостей; як плануєте це вимірювати.
- Обмеження середовища: архітектури (amd64/arm64), ОС, оркестратор, режим запуску, вимоги до недоторканності продакшену.
- Що вже пробували і чому не злетіло — це економить нам етап гіпотез.
Напишіть у двох словах, яка у вас задача і що з переліченого є під рукою, — повернемося з оцінкою, планом впровадження й строками за етапами.







