Шо по докерфайлам?

💡 Усі статті, обговорення, новини про DevOps — в одному місці. Приєднуйтесь до DevOps спільноти!

(Якщо ваш Dockerfile починається з FROM node:20 і закінчується COPY . . без .dockerignore, то це пост для вас. Ще більше таких дискусійних тем на каналі @mamkin_architect.)

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

1. Пхати всюди Alpine не варто. Так, воно мале, це зрозуміло. Але Alpine на musl libc, а не на glibc, ми можемо не розуміти цю різницю, але наші Python або Node її відчують на собі. Нативні залежності або перекомпілюються з нуля, або мовчки працюють повільніше, бо готових wheels під musl часто просто немає. Краще брати -slim (типу debian-slim), розмір приблизно такий же, проблем нуль. Але якщо у вас Go-бінарники чи подібні статично злінковані речі, то там Alpine рулить.

2. Порядок команд має значення. Спочатку COPY lock файлу, потім install, і тільки потім COPY решти коду. В результаті залежності не будуть зтягуватись кожного разу, як ви поміняєте таби на пробіли.

3. Multi-stage білди це не просто «best practice заради галочки», а реальна причина, чому прод-образ не тягне за собою gcc, хедери і 400 мегабайт тулчейну. В білдер-стейдж навалюємо все що треба для збірки, а потім звідти у фінальний стейдж переносимо лише артефакти та рантайм. Маємо на виході маленький образ, який швидко деплоїться.

4. COPY . . насправді нормально, якщо ваш .dockerignore написано по-людськи. Більшість болю зазвичай від того, що люди забувають виключити node_modules, .git, локальні логи і купу сміття. Фіксити треба ignore, а не COPY.

5. Піньте базовий образ по digest, а не по тегу. node:20 сьогодні і node:20 через пів року це два різних образи. Прод впав через оновлення тега, на яке ви не підписувались, а як же так сталось?! Digest тримає все під вашим контролем, все оновиться саме коли ви вирішите, а не о другій ночі першого січня.

6. BuildKit cache mounts (--mount=type=cache) це та фіча, про яку чомусь майже ніхто не говорить. Кеш pip, apt, cargo, npm живе між білдами і при цьому не потрапляє у фінальний шар, тобто образ залишається чистим, а повторні білди прискорюються в рази. Люди годинами тюнять CI/CD пайплайни, виносять кеш в окремі воркери, пишуть костилі, а одна директива в RUN робить те саме зрозумілішим і швидшим способом. Якщо ви про це ще не чули, то це, мабуть, та єдина порада з усіх тут, яку справді варто спробувати сьогодні ввечері.

Шо скажете? Дізнались щось нове?

👍ПодобаєтьсяСподобалось5
До обраногоВ обраному3
LinkedIn
Ctrl + Enter
Ctrl + Enter
Фіксити треба ignore, а не COPY.

Ем. Використовувати ignore замість копіювати ТІЛЬКИ потрібне — обов’язково колись призведе до витоку небажаних локальних файлів в докер імідж.

Це як використовувати в файрволі «deny ... / allow any» замість правильного «allow ... / deny any»

Ще одна стаття про Docker і знову нічого про distroless.

Але якщо у вас Go-бінарники чи подібні статично злінковані речі, то там Alpine рулить.

Ні, там рулить FROM scratch

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

якщо у вашому докерфайлі немає --only-binary=:all:, то це набагато більша проблема, ніж просто Alpine :)

COPY . . насправді нормально, якщо ваш .dockerignore написано по-людськи.

Насправді це ніколи не нормально — це стандартна проблема blacklist vs whitelist. Якщо хтось забуде проапдейтити blacklist, все буде працювати як раніше і цього ніхто не побачить. Якщо хтось забуде проапдейтити whitelist для СВОЇХ змін, то це відразу впаде і, відповідно, буде відразу вилікувано тим, хто ці зміни робив

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

Підписатись на коментарі