Налаштування Docker Layer Caching для прискорення збірки

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

Чому кешування шарів Docker перестає працювати: де втрачаються шари

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

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

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

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

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

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

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

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

Час збірки та частота відмов

Шари образу Docker кешуються за вмістом інструкцій: поки не змінювався файл залежностей, крок встановлення пакетів береться готовим. На типовому проєкті збірка скорочується з 8–12 хвилин до 2–3, а частка влучань у кеш тримається на рівні 80–90% за правок у коді застосунку.

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

Обсяг сховища та передбачуваність викочування

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

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

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

Ефект видно не в одній цифрі, а в зв'язці: що вища частка влучань, то коротший цикл правки і то менше приводів перезапускати викочування.

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

Способи кешування: локальний кеш, реєстр образів, спільний том

Кеш шарів Docker — це не галочка в налаштуваннях, а прив'язка до топології збірки. Локальний кеш збірки живе на конкретній машині й дає максимум на постійному вузлі, але обнуляється, щойно вузол перестворили.

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

Режим для однієї команди

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

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

Варіант Коли підходить Обмеження
Локальний кеш збірки один постійний вузол, часті перезбірки одного проєкту не переживає перестворення вузла, не ділиться між машинами
Кеш у реєстрі образів кілька вузлів і гілок, збірка в ізольованих середовищах потрібен доступ до реєстру та чистка тегів; приватні шари не повинні виходити назовні
Спільний том кешу парк вузлів збірки зі спільним мережевим сховищем блокування під час паралельного запису, мережа стає вузьким місцем

Коли вузлів кілька

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

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

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

Як ми налаштовуємо кеш збірки Docker: етапи робіт

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

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

Підготовка та перевірка

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

Викочування та передача

  • Викочуємо на робочі гілки поступово: спочатку основна, потім решта, стежимо за часом збірки та зростанням сховища кешу.
  • Передаємо регламенти збірки: правила правки опису образу, що не можна змінювати без погодження, пам'ятка для розробників і порядок повного скидання кешу.

Що залишається в репозиторії: конфігурації, схеми та регламенти

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

Код та інфраструктура

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

Документація та доступи

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

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

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

Що було до робіт

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

Шари із залежностями перезбиралися за будь-якої зміни в дереві — правка в одному сервісі тягла перевстановлення пакетів по всьому репозиторію, повний прохід займав 22–26 хвилин.

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

Частка відмов трималася на 18%, і клас збоїв «зібрано на застарілих залежностях» відтворювався регулярно.

Що змінилося після

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

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

Повний прохід скоротився з 22–26 до 6–8 хвилин, повторна збірка незміненого сервісу вкладається в хвилину. Частка відмов упала з 18% до 4%: той самий клас помилок закритий конструкцією кешу, а не регламентом.

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

Чим відрізняється кеш шарів від кешу залежностей і пакетів?

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

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

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

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

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

Монтований том під склад дає той самий ефект, але живе окремо від образу й переживає скидання кешу збірки та правки у файлі залежностей.

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

Тому потрібен окремий ключ на кожну гілку збірки — інакше паралельні збірки перетирають один одному склад і дають нестабільний результат.

Часті технічні сумніви щодо кешування збірок

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

Дві збірки йдуть одночасно — чи не перемішають вони кеш?

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

Оновився базовий образ — кеш залишиться валідним?

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

Чи перенесеться кеш на інший вузол або агент збірки?

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

Кеш безпечний? Чи не залишаться в ньому секрети?

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

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

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

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

Що віддаємо у відповідь:

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

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

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

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

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