ИТ развој

Dockerfiles Aren't Dead, They're Just Evolving

Dockerfile-овите не се мртви, само еволуираат

Dockerfile е прогласуван за застарен доволно често за тоа да се смета за повторлив индустриски ритуал. Се појавува нова алатка за градење, платформа ветува распоредување без конфигурација или на тимот му здосадува дебагирањето на слоеви на слики, и одеднаш Dockerfile е проблемот.

Не е. Dockerfile останува еден од најјасните начини да се опише како една апликација станува извршлив артефакт. Она што се менува е стандардот што треба да го очекуваме од него. Современиот Dockerfile е помалку список на shell команди, а повеќе намерно дизајнирана граница меѓу изворниот код, алатките за градење, зависностите за извршување и продукциските операции.

Контејнерите сè уште имаат потреба од експлицитен договор

PHP апликациите можат да се распоредуваат преку управувани платформи, Kubernetes, виртуелни машини или едноставен Docker Compose стек. Инфраструктурата се разликува, но повторлив артефакт сè уште е вреден. Тој им дава на локалниот развој, CI, staging и продукцијата заедничка дефиниција за извршната околина на апликацијата.

Dockerfile е особено корисен кога директно одговара на важни оперативни прашања:

  • Која PHP верзија и кои екстензии ѝ се потребни на апликацијата?
  • Што мора да се случи пред да можат да се инсталираат Composer зависностите?
  • Кои датотеки припаѓаат во конечната извршна слика?
  • Кој процес се стартува кога се извршува контејнерот?
  • Која конфигурација се обезбедува при извршување наместо да биде вградена во сликата?

Ако овие одговори се скриени во CI скрипта, контролна табла на платформа и вики за развивачи, распоредувањето може да изгледа лесно сè додека нешто не откаже. Експлицитната дефиниција на градењето не е бирократија. Таа е алатка за одржливост.

Важната еволуција е од „работи“ кон „намерно“

Раните Dockerfile-ови често го копираа целото складиште во слика, инсталираа сè како root и испорачуваа алатки за градење заедно со апликацијата. Тоа може да работи, но создава бавни градења, преголеми слики, непотребна површина за напад и збунувачко однесување во продукција.

Современото создавање слики ги раздвојува одговорностите. Зависностите за градење припаѓаат во builder фаза. Извршните слики треба да содржат само она што ѝ е потребно на апликацијата за да опслужува барања. Composer кешовите треба да се користат без да станат дел од испорачаниот артефакт. Тајните треба да се обезбедуваат при извршување или преку механизмите за тајни на системот за градење, никогаш да не се копираат во слој на слика.

Разгледајте конвенционална PHP апликација што користи Composer и PHP-FPM:

FROM composer:2 AS vendor

WORKDIR /app

COPY composer.json composer.lock ./
RUN composer install \
    --no-dev \
    --no-interaction \
    --no-progress \
    --prefer-dist \
    --optimize-autoloader

COPY . .
RUN composer dump-autoload --no-dev --classmap-authoritative

FROM php:8.3-fpm-alpine

WORKDIR /var/www/html

COPY --from=vendor /app /var/www/html

RUN addgroup -S app && adduser -S app -G app \
    && chown -R app:app /var/www/html

USER app

CMD ["php-fpm"]

Ова не е универзален шаблон. Нативните екстензии, градењата на средства базирани на Node, queue worker-ите и загревањето на кешот на framework-от може да бараат различни фази и команди. Поентата е во обликот на решението: прво изградете ги артефактите, потоа копирајте го само потребниот резултат во помала извршна слика.

Редоследот на слоевите е инженерска одлука

Кешот за градење на Docker наградува стабилни влезови. Composer манифестите обично се менуваат поретко од кодот на апликацијата, па копирањето на composer.json и composer.lock пред остатокот од изворниот код овозможува инсталацијата на зависностите да остане кеширана кога се менува само контролер, миграција или тест.

Тој мал избор на редослед е важен во CI. Ги скратува циклусите на повратни информации без да ја жртвува репродуктивноста, под услов lock датотеката да е зачувана во складиштето и да се почитува. За продукциски градења, composer install обично е соодветната операција бидејќи го инсталира разрешениот сет на зависности. Замената со composer update би направила градењата на слики неочекувано да избираат понови пакети и би ги поткопала повторливите распоредувања.

Истата дисциплина важи и за пакетите на оперативниот систем. Инсталирајте само пакети потребни за градењето или извршувањето и направете го тој избор видлив. Клиент за база на податоци може да биде корисен за слика за задача со миграции, но не припаѓа автоматски во секоја веб-слика.

Една слика не мора да значи еден процес

Често поедноставување е дека на секоја апликација ѝ е потребна посебна слика за секој процес. Обично покорисното правило е следново: создадете една слика на апликацијата што може да извршува еден примарен процес по контејнер.

Истата PHP кодна база може да создаде веб-контејнер, queue worker и scheduler контејнер. Тие можат да ја споделуваат истата слика додека користат различни команди:

services:
  web:
    image: example-app
    command: php-fpm

  worker:
    image: example-app
    command: php artisan queue:work

  scheduler:
    image: example-app
    command: php artisan schedule:work

Ова ги одржува зависностите и распоредениот код конзистентни, додека дозволува секој процес независно да се скалира, рестартира и набљудува. Исто така, се избегнува кревката практика на користење process supervisor само за да се задржат неповрзани долготрајни услуги во еден контејнер.

Конфигурацијата припаѓа надвор од сликата

Сликата треба да биде пренослива низ средини. Ингеренциите за база на податоци, API токените, крајните точки специфични за средината и клучевите за потпишување не треба да се копираат при градењето. Штом тајна влезе во слој на слика, подоцнежното отстранување на датотеката не ја отстранува сигурно од историјата на сликата.

Наместо тоа, конфигурацијата треба да се вметнува при извршување преку можностите за конфигурација и тајни на средината за распоредување. Апликацијата треба да ја валидира суштинската конфигурација при стартување, јасно да откаже кога таа недостига и да изложува здравствени проверки што одразуваат дали процесот навистина е подготвен да прими работа.

Тука постои практична разлика. Веб-процесот може да биде активен пред неговата конекција со базата на податоци да биде употреблива. Worker може да работи, но да не може да ја достигне својата queue. Подготвеноста и активноста треба да се дизајнираат според однесувањето што секој процес мора да го обезбеди, а не да се додаваат како генерички boilerplate.

Dockerfile-овите се архитектонски документи

Најдобрите Dockerfile-ови откриваат корисни вистини за системот. Тие ги прават зависностите експлицитни, ја раздвојуваат работата во време на градење од однесувањето при извршување и покажуваат каде почнува оперативната одговорност. Кога Dockerfile станува тежок за разбирање, тоа може да биде сигнал дека и границите на апликацијата имаат потреба од внимание.

Алатките ќе продолжат да генерираат Dockerfile-ови, да ги апстрахираат зад buildpacks и автоматски да ги оптимизираат нивните слоеви. Тоа се корисни подобрувања. Но апстракциите не ги елиминираат основните одлуки за репродуктивност, зависности, процеси, конфигурација и безбедност.

Dockerfile-овите не се мртви. Тие созреваат заедно со системите што ги пакуваат. Третирајте ги како продукциски код: мали, прегледливи, репродуктивни и искрени за тоа што ѝ е потребно на вашата апликација. Тоа е многу поиздржливо од кој било аргумент за тоа дали самата датотека е модерна.

Портрет на автор на блогот

Mihajlo

Јас сум Михајло - развивач поттикнат од љубопитност, дисциплина и постојаната желба да создадам нешто значајно. Споделувам увиди, упатства и бесплатни услуги за да им помогнам на другите да ја поедностават својата работа и да растат во постојано развивачкиот свет на софтверот и вештачката интелигенција.