Dockeriziranje PHP mikroservisa: Orkestriranje za besprijekornu implementaciju
Mikrousluge ne postaju spremne za implementaciju samo zato što su podijeljene u manje repozitorije ili direktorije. Pravi test dolazi kada svaka usluga treba vlastito vrijeme izvođenja, konfiguraciju, mrežni pristup, vezu s bazom podataka, provjeru stanja i put izdanja. Docker PHP timovima pruža discipliniran način pakiranja tih elemenata kako bi se usluga ponašala predvidljivo, od prijenosnog računala razvojnog programera do produkcijske platforme.
Cilj nije radi njega samog smjestiti svaki pokretni dio u spremnike. Cilj je stvoriti ponovljivu operativnu granicu: ista verzija PHP-a, potrebna proširenja, aplikacijski kôd i naredba za pokretanje putuju zajedno. Ta dosljednost smanjuje poznatu vrstu neuspjeha: kôd koji je bio ispravan, ali se izvršavao u suptilno drukčijem okruženju.
Započnite s malom, eksplicitnom PHP slikom
Slika mikrousluge trebala bi sadržavati ono što usluzi treba za rad i malo toga drugoga. Za tipičnu PHP HTTP uslugu to znači PHP vrijeme izvođenja, potrebna proširenja, Composer ovisnosti, aplikacijski kôd i naredbu za pokretanje. Alati namijenjeni samo razvoju ne bi smjeli nepromišljeno završiti u produkcijskoj slici.
Višefazna izgradnja omogućuje dostupnost Composera tijekom instalacije ovisnosti, a da ne postane dio konačne slike vremena izvođenja.
FROM composer:2 AS dependencies
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist --no-interaction --no-scripts
FROM php:8.3-cli
WORKDIR /app
COPY --from=dependencies /app/vendor /app/vendor
COPY . .
EXPOSE 8080
CMD ["php", "-S", "0.0.0.0:8080", "-t", "public"]
Ovaj je primjer namjerno jednostavan. Ugrađeni PHP poslužitelj može biti koristan za malu uslugu ili lokalni radni tijek, ali produkcijsko HTTP rukovanje često koristi PHP-FPM iza web-poslužitelja ili model procesa kojim upravlja platforma. Važan je dizajnerski odabir da je naredba spremnika eksplicitna i odgovara načinu na koji je usluga namijenjena za rad.
Kopirajte manifeste ovisnosti prije izvornog koda aplikacije. Docker tada može ponovno upotrijebiti sloj za instalaciju ovisnosti kada se promijeni samo aplikacijski kôd. To ubrzava iterativne izgradnje uz očuvanje ponovljivosti putem composer.lock.
Definirajte ugovore između usluga
Spremnici olakšavaju pokretanje usluga; ne definiraju kako bi usluge trebale ovisiti jedna o drugoj. To je arhitektonska odgovornost. PHP usluga trebala bi poznavati svoje uzvodne ovisnosti putem konfiguracije, a ne putem tvrdo kodiranih naziva hostova, vjerodajnica ili pretpostavki o lokalnoj infrastrukturi.
Za lokalni razvoj Docker Compose koristan je za opisivanje malog sustava i njegove mreže između usluga.
services:
orders:
build: ./orders
environment:
DATABASE_URL: "mysql://app:secret@db:3306/orders"
INVENTORY_BASE_URL: "http://inventory:8080"
depends_on:
db:
condition: service_healthy
ports:
- "8080:8080"
inventory:
build: ./inventory
db:
image: mysql:8
environment:
MYSQL_DATABASE: orders
MYSQL_USER: app
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root-secret
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 10
Unutar ove mreže inventory i db nazivi su usluga koji se razrješavaju kao nazivi hostova. To je praktično lokalno, ali šira je pouka važnija: konfiguracija bi trebala izražavati krajnje točke ovisnosti, a okruženja za implementaciju trebala bi pružiti ispravne vrijednosti.
Također razlikujte između „spremnik se pokrenuo” i „ovisnost je spremna”. Proces baze podataka može postojati dok se još inicijalizira. Compose provjere stanja mogu poboljšati ponašanje pri lokalnom pokretanju, ali aplikacija bi i dalje trebala upravljati prolaznim pogreškama povezivanja. Kratak, ograničen ponovni pokušaj s postupnim povećanjem čekanja razuman je tijekom pokretanja; beskonačni ponovni pokušaji koji skrivaju lošu konfiguraciju nisu.
Održavajte uslugu bez stanja
Spremnici su prema dizajnu zamjenjivi. Tretiranje njihova lokalnog datotečnog sustava kao trajne pohrane stvara probleme tijekom skaliranja, ponovnih implementacija i oporavka. Trajne podatke pohranjujte u odgovarajući vanjski sustav: relacijske podatke u bazu podataka, zajedničke datoteke u objektnu ili mrežnu pohranu, a prolazno stanje koordinacije u namjensku uslugu kada je potrebno.
Ovo načelo također razjašnjava migracije baze podataka. Nemojte dopustiti da se svaka replika aplikacije natječe u pokretanju migracija tijekom pokretanja. Migracije pokrenite kao zaseban korak implementacije ili namjenski jednokratni zadatak, a zatim pokrenite novu verziju aplikacije. To razdvajanje čini neuspjehe vidljivima i sprječava da događaj horizontalnog proširenja postane događaj upravljanja shemom.
Konfiguracija je sučelje, a ne pogodnost
Varijable okruženja praktičan su mehanizam isporuke za netajnu konfiguraciju poput portova, razina zapisivanja, prekidača značajki i URL-ova usluga. Tajne zahtijevaju strože rukovanje: umetnite ih putem platforme za implementaciju ili odobrenog mehanizma za upravljanje tajnama, izbjegavajte njihovo spremanje u Compose datoteke i nikada ih nemojte ugraditi u sloj slike.
Provjerite obaveznu konfiguraciju pri pokretanju procesa. Usluga koja se ne može povezati jer nedostaje DATABASE_URL trebala bi jasno prekinuti rad, umjesto da nastavi s implicitnom zamjenom. Jasni neuspjesi skraćuju odgovor na incidente i održavaju usklađenost ponašanja u razvoju i produkciji.
Gradite za opažljivost i graciozan neuspjeh
U distribuiranom sustavu zahtjev može ne uspjeti nakon što napusti vašu uslugu. Vremenska ograničenja, strukturirani zapisi, identifikatori korelacije i smisleni krajnji ciljevi za provjeru stanja pretvaraju tu neizvjesnost u nešto što operateri mogu dijagnosticirati. Svaki odlazni HTTP poziv trebao bi imati vremensko ograničenje. Bez njega spora nizvodna ovisnost može zauzeti kapacitet radnika dok usluga ne izgleda nedostupno.
Ponovni pokušaji zahtijevaju procjenu. Ponovni pokušaj zahtjeva za čitanje nakon privremenog mrežnog neuspjeha može biti primjeren. Ponovni pokušaj neidemponentne operacije, kao što je stvaranje narudžbe, može proizvesti duplikate ako primajuća usluga ne podržava ključ idempotentnosti. Sigurna je zadana postavka pokušavati ponovno samo kada operacija i način neuspjeha dopuštaju prihvatljivo dvostruko izvršavanje.
Pažljivo izložite informacije o stanju. Krajnja točka za živost trebala bi odgovoriti može li proces nastaviti s radom. Krajnja točka za spremnost trebala bi odgovoriti može li sigurno primati promet. Ako usluga mora dosegnuti bazu podataka prije posluživanja zahtjeva, spremnost može odražavati tu ovisnost; živost privremeni prekid rada baze podataka obično ne bi trebala pretvoriti u neprekidna ponovna pokretanja spremnika.
Namjerno učinite implementaciju dosadnom
Pouzdan cjevovod implementacije izgrađuje jednu nepromjenjivu sliku, testira je, označava je verzijskim identifikatorom koji se može pratiti i promiče taj točan artefakt kroz okruženja. Ponovna izgradnja iz grane za svako okruženje uvodi neizbježnu nesigurnost: navodno isto izdanje može sadržavati drukčije razrješavanje ovisnosti, sadržaj osnovne slike ili stanje izvornog koda.
- Pokrenite jedinične i integracijske testove prije objavljivanja slike izdanja.
- Skenirajte i ažurirajte osnovne slike kroz promišljen proces održavanja.
- Koristite konfiguraciju i tajne koje pruža svako okruženje, a ne izmijenjeni sadržaj slike.
- Implementirajte kompatibilne promjene aplikacije i sheme u slijedu koji podržava vraćanje na prethodnu verziju.
- Pratite stopu pogrešaka, latenciju i zapise tijekom uvođenja prije povećanja prometa.
Kompatibilnost sheme zaslužuje posebnu pozornost. Sigurniji je obrazac najprije dodavanje: dodajte stupac koji dopušta NULL ili novu tablicu, implementirajte kôd koji može raditi i sa starim i s novim oblicima, po potrebi popunite podatke, a zatim u kasnijem izdanju uklonite zastarjele strukture. Docker standardizira vrijeme izvođenja, ali ne može nekompatibilnu promjenu baze podataka učiniti reverzibilnom.
Spremnik je početak operativnog dizajna
Dockeriziranje PHP mikrousluga vrijedno je jer pretvara pretpostavke o vremenu izvođenja u konkretne elemente. Potiče male slike, eksplicitne ovisnosti, ponovljive izgradnje i prenosive artefakte implementacije. Ali spremnici ne uklanjaju probleme distribuiranih sustava. Čine ih dovoljno vidljivima da se mogu dobro dizajnirati.
Najjači rezultat nije domišljata Compose datoteka ni najmanja moguća slika. To je usluga koja se predvidljivo pokreće, jasno ne uspijeva, svoje stanje čuva na pravom mjestu i može se zamijeniti bez drame. Kada svaka PHP mikrousluga slijedi te navike, orkestracija se manje svodi na borbu s platformom, a više na pouzdanu isporuku promjena.