ИТ развој

Dockerized PHP: Streamline Development and Isolate Environments

PHP во Docker: Рационализирајте го развојот и изолирајте ги околините

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

Docker ја менува таа граница. Наместо секој развивач рачно да репродуцира околина, тимот ја опишува околината како код. PHP runtime-от, веб-серверот, базата на податоци и придружните услуги се извршуваат во изолирани контејнери со експлицитни верзии и конфигурација. Резултатот не е магија, но значително ја намалува варијабилноста што може да се избегне.

Зошто контејнеризирањето на PHP се исплати

Непосредната придобивка е конзистентноста. Развивач што се приклучува на проектот може да ја извршува истата PHP верзија и екстензии што ги користи остатокот од тимот, без да го менува оперативниот систем на домаќинот. CI задача може да се изгради од истиот Dockerfile. Продукциска слика може да се изведе од истите runtime претпоставки, а сепак да добие сопствена безбедна конфигурација и процес на распоредување.

Таа конзистентност е особено важна кај PHP бидејќи екстензиите се дел од runtime договорот. Апликацијата може да работи со локално инсталирана PHP бинарна датотека, но да откаже на друго место бидејќи pdo_pgsql, intl, gd или потребна системска библиотека недостасува. Во Dockerfile, тие зависности стануваат видливи и проверливи.

Изолацијата исто така ја олеснува паралелната работа. Еден проект може да користи PHP 8.2 со PostgreSQL, додека друг користи различно поддржано PHP издание и MySQL, без едното поставување да го презапишува другото. Домаќинот ја задржува својата улога на домаќин; проектот го поседува својот runtime.

Започнете со мала, експлицитна PHP слика

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

FROM php:8.3-fpm

RUN docker-php-ext-install pdo_mysql opcache

WORKDIR /var/www/html

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

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

COPY . .

CMD ["php-fpm"]

Овој пример е намерно ограничен. Ја инсталира MySQL PDO екстензијата, го овозможува Opcache и ги инсталира PHP зависностите пред да го копира остатокот од апликацијата. Првото копирање на composer.json и composer.lock му овозможува на Docker повторно да го користи слојот со зависности кога кодот на апликацијата се менува, а зависностите не.

Точната PHP ознака треба да ја одразува верзијата што ја поддржува вашата апликација. „Latest“ е практично сè додека тивко не стане различен runtime. Фиксирањето на соодветна главна и споредна верзија ги прави надградбите намерна задача за одржување, наместо изненадување.

Компонирајте ги услугите, не само апликацијата

На повеќето backend апликации им треба повеќе од PHP-FPM. Локалниот стек вообичаено вклучува reverse proxy, база на податоци и можеби Redis за кеширање или редици. Docker Compose обезбедува читлив начин за дефинирање на тие односи.

services:
  app:
    build: .
    volumes:
      - .:/var/www/html
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: app
      MYSQL_USER: app
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: root-secret
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 3s
      retries: 10
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:

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

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

Одделете ја развојната практичност од продукциската дисциплина

Bind-mounting на изворниот директориум во контејнерот е одлично за локална итерација: уредете датотека на домаќинот и дозволете PHP да го сервира изменетиот код. Тоа обично е погрешен модел за продукција. Продукциската слика треба да го содржи точниот артефакт на апликацијата што ќе го извршува, изграден од заклучен сет зависности.

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

Продукциските контејнери треба да работат и со најмалиот практичен привилегиум, да изложуваат само неопходни порти и да избегнуваат вклучување компајлери или алатки за дебагирање во конечната runtime слика. Повеќефазно градење често е најчистиот пристап кога се потребни компилација на средства или пакети само за градење.

Не мешајте ги контејнерите со целосен безбедносен модел

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

Направете го работниот тек предвидлив

Контејнеризираното поставување стекнува доверба кога неговите секојдневни команди се едноставни. Развивачите треба да можат да стартуваат услуги, да извршуваат тестови, да извршуваат миграции и да прегледуваат логови без да паметат патеки специфични за домаќинот или PHP инсталации.

  • Користете docker compose up --build кога се менува дефиницијата на сликата или зависностите.
  • Извршувајте команди на апликацијата во услугата на апликацијата, како docker compose exec app php artisan migrate за Laravel апликација.
  • Чувајте ги командите специфични за framework-от во документирани скрипти или Makefile, за тимот да користи конзистентни влезни точки.
  • Проверете ги логовите на услугите кога стартувањето не успева; грешка при автентикација на база на податоци и грешка на PHP екстензија бараат различни поправки.

Внимавајте на дозволите на датотечниот систем кај bind mounts. Процесот во контејнерот може да создаде датотеки во сопственост на кориснички ID што е незгоден на домаќинот. Наместо постојано да применувате широки дозволи, дефинирајте соодветна стратегија за развоен корисник за проектот и потврдете дека директориумите за кеш, логови и прикачувања остануваат запишливи.

Оптимизирајте само откако границите се јасни

Контејнерите можат да откријат проблеми со перформансите што биле скриени од великодушно конфигурирана локална машина, но не ги предизвикуваат автоматски. Профилирајте ги бавните endpoint-и, проверете ги барањата кон базата на податоци и измерете ја употребата на меморија пред да го менувате бројот на процеси или да додавате слоеви за кеширање. За PHP-FPM, поставките за workers треба да се засноваат на достапната меморија и набљудуваното однесување на барањата, а не слепо да се копираат од друга апликација.

Opcache е корисна основа за продукција, додека развојот обично има корист од поставки што сигурно откриваат изменети изворни датотеки. Тоа се различни цели. Третирајте ја runtime конфигурацијата како дел од договорот за околината и држете ги развојните и продукциските поставки намерно различни.

Подобра граница за подобро инженерство

Трајната вредност на PHP со Docker не е во тоа секоја машина да изгледа идентично. Таа е во тоа што вистинските барања на апликацијата престануваат да бидат племенско знаење. Runtime-от станува проверлив, репродуцибилен и полесен за развивање.

Започнете мало: една PHP услуга, една база на податоци, експлицитни екстензии и сигурна патека за команди. Потоа додавајте услуги само кога архитектурата ги бара. Добро дизајнираното поставување со контејнери не ја прави PHP апликацијата посложена; ја прави сложеноста што веќе ја има видлива, контролирана и многу полесна за одржување.

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

Mihajlo

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