Razvoj

Demystify Docker: Ship Reliable Apps with Pragmatic Containerization

Demistificirajte Docker: Isporučujte pouzdane aplikacije uz pragmatičnu kontejnerizaciju

Docker se često predstavlja kao način za „pakiranje aplikacije”. To je točno, ali umanjuje stvarnu korist: spremnici čine pretpostavke vezane uz aplikaciju vidljivima. Verzija PHP-a, proširenja, paketi operacijskog sustava, konfiguracija web-poslužitelja, naredba radnika reda i slijed pokretanja mogu svi stajati uz kôd umjesto da budu raspršeni po wiki stranicama i dugotrajno pokrenutim poslužiteljima.

Upravo ta vidljivost čini Docker vrijednim za backend timove. Spremnik neće automatski stvoriti dobru arhitekturu, brze upite prema bazi podataka ni sigurne implementacije. Ali znatno otežava ignoriranje okruženja koje vaš softver zaista treba.

Zamislite spremnik kao izvršivi ugovor

Docker slika je nepromjenjivi predložak. Spremnik je pokrenuta instanca tog predloška. Slika opisuje datotečni sustav i zadani proces; konfiguracija zadana pri pokretanju pruža vrijednosti specifične za okruženje, kao što su vjerodajnice baze podataka, razine zapisivanja i URL-ovi usluga.

Ta je razlika važna. Kôd aplikacije i njegove ovisnosti tijekom izvođenja pripadaju slici. Tajne i postavke specifične za implementaciju ne pripadaju. Kada se te brige pomiješaju, navodno prenosiva slika postaje vezana uz jedno okruženje i teže ju je promicati iz razvoja u pripremno okruženje pa u produkciju.

Za PHP API koristan ugovor mogao bi glasiti: ova usluga pokreće PHP-FPM, uključuje potrebna PHP proširenja, sadrži kôd aplikacije, sluša putem svojeg upravitelja procesa i pri pokretanju očekuje URL baze podataka i krajnju točku predmemorije. Taj je ugovor dovoljno konkretan da ga prijenosno računalo programera i produkcijska platforma mogu ispuniti na različite načine.

Započnite s malom, eksplicitnom PHP slikom

Prvi Dockerfile trebao bi biti dosadan. Dosadno je dobro: recenzentima daje jasan uvid u to što ulazi u okruženje tijekom izvođenja i zašto.

FROM php:8.3-fpm

WORKDIR /var/www/app

RUN docker-php-ext-install pdo_mysql

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

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

COPY . .

RUN composer dump-autoload --optimize --no-dev

CMD ["php-fpm"]

Ovaj primjer pretpostavlja aplikaciju koja koristi MySQL putem PDO-a. Ako aplikacija treba drugo proširenje, dodajte ga promišljeno i provjerite njegove zahtjeve za izgradnju. Izbjegavajte instaliranje široke zbirke paketa „za svaki slučaj”. Svaka ovisnost povećava veličinu slike, opseg rada na zakrpama i broj načina na koje izgradnja može zakazati.

Redoslijed uputa je namjeran. Composer manifesti kopiraju se prije ostatka izvornog kôda kako bi Docker mogao ponovno upotrijebiti sloj instalacije ovisnosti kada se promijeni samo kôd aplikacije. To čini lokalnu iteraciju i kontinuiranu integraciju primjetno manje rasipnima bez zamagljivanja izgradnje.

U produkcijskoj slici isključene su ovisnosti namijenjene samo razvoju. To nije samo optimizacija: alati namijenjeni lokalnom otklanjanju pogrešaka ne bi smjeli potajno postati zahtjevi produkcijskog okruženja tijekom izvođenja. Ako implementacija treba resurse za izgradnju, generirani kôd ili zagrijavanje predmemorije, učinite te korake eksplicitnima i osigurajte da se mogu pokrenuti bez oslanjanja na lokalne datoteke koje nikada nisu kopirane u sliku.

Sastavite usluge, ali njihove odgovornosti držite odvojenima

Većina aplikacija nije jedan proces. Tipičan backend treba HTTP ulaznu točku, bazu podataka, predmemoriju i možda radnika. Docker Compose koristan je u razvoju jer bilježi kako se te usluge povezuju bez pretvaranja da su jedan stroj.

services:
  app:
    build: .
    environment:
      DATABASE_URL: mysql://app:secret@db:3306/app
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:8
    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:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:

Aplikacija se povezuje na db, a ne na localhost, jer svaka usluga ima vlastiti mrežni imenski prostor. To je jedno od najčešćih ranih iznenađenja. Unutar spremnika localhost znači sam taj spremnik.

Provjera stanja također je značajnija od jednostavnog pravila redoslijeda pokretanja. Proces baze podataka može postojati prije nego što može prihvatiti veze. Unatoč tomu, kôd aplikacije i dalje bi trebao rukovati prolaznim neuspjesima povezivanja: provjere stanja ovisnosti poboljšavaju ponašanje pri pokretanju, ali ne uklanjaju prekide mreže, ponovna pokretanja baze podataka ni događaje održavanja.

Učinite pokretanje sigurnim za ponavljanje

Orkestracija spremnika očekuje da se procesi zaustavljaju i pokreću. Implementacije zamjenjuju instance. Platforme ih ponovno raspoređuju. Radnik može biti ponovno pokrenut nakon rušenja. To znači da zadaci pri pokretanju trebaju pažljivo definirane granice.

Migracije sheme klasičan su primjer. Njihovo automatsko pokretanje u svakom web-spremniku može stvoriti utrke kada se nekoliko replika pokrene zajedno. Sigurniji je pristup pokrenuti migracije kao jedan kontrolirani korak implementacije, koristeći istu izgrađenu sliku i istu konfiguraciju tijekom izvođenja kao aplikacija. Same migracije trebaju biti dizajnirane tako da, gdje je praktično, podnose ponovne pokušaje, a velike promjene podataka treba planirati odvojeno od uvođenja koje poslužuje zahtjeve.

Isto načelo vrijedi za redove. Pokrenite radnika reda kao zasebnu uslugu s jasnom naredbom, ograničenjem resursa, pravilima ponovnog pokušaja i ponašanjem pri gracioznom gašenju. Nemojte skrivati radnika iza pozadinske naredbe ljuske u web-spremniku. Docker može dobro nadzirati jedan primarni proces; kombiniranje nepovezanih dugotrajnih procesa čini zapise, signale, skaliranje i neuspjehe dvosmislenima.

Koristite spremnike za poboljšanje operacija, ne samo uvođenja novih članova

Slika spremnika postaje najvrjednija kada je artefakt testiran u kontinuiranoj integraciji artefakt koji se implementira. Izgradite je jednom, označite nepromjenjivom oznakom, prema potrebi pokrenite testove nad njom, a zatim promaknite upravo tu sliku. Ponovna izgradnja iz iste Git revizije u svakom okruženju uvodi varijable koje je moguće izbjeći: repozitoriji paketa se mijenjaju, osnovne slike se ažuriraju, a izgradnja možda nije toliko reproducibilna koliko se čini.

Opservabilnost bi trebala slijediti isti pragmatičan pristup. Zapisujte dnevnike aplikacije na standardni izlaz i standardnu pogrešku kako bi ih okruženje tijekom izvođenja moglo prikupljati. Konfiguraciju držite u varijablama okruženja ili odobrenom mehanizmu konfiguracije. Pošaljite signale prekida procesu aplikacije i dopustite mu vrijeme da dovrši aktivan rad. Ti su izbori jednostavni, ali čine neuspjehe dijagnosticiranima kada se dogode izvan računala programera.

  • Upotrijebite datoteku .dockerignore za isključivanje direktorija ovisnosti, testnih artefakata, lokalne konfiguracije i drugih datoteka koje slici nisu potrebne.
  • Pokrenite aplikaciju kao korisnik koji nije root kada to dopuštaju osnovna slika i implementacija.
  • Fiksirajte važne verzije osnovne slike i pregledavajte ažuriranja kao dio redovitog održavanja.
  • Trajne podatke čuvajte u upravljanoj pohrani ili imenovanim volumenima, nikada u zapisivom datotečnom sustavu spremnika.
  • Dokumentirajte nekoliko naredbi koje programeri zaista trebaju, poput izgradnje, testiranja, migracije i pristupa ljusci.

Pragmatično mjerilo uspjeha

Docker nije značka inženjerske zrelosti. Koristan je kada smanjuje neizvjesnost: novi programer može pouzdano pokrenuti cijeli skup usluga, CI zadatak pokreće se u očekivanom okruženju tijekom izvođenja, a produkcija dobiva artefakt čiji je sadržaj poznat.

Neka Dockerfile ostane čitljiv, slika usmjerena, usluge odvojene, a koraci implementacije eksplicitni. Kada spremnici otkriju krhku ovisnost ili nejasan slijed pokretanja, tretirajte to kao korisnu povratnu informaciju o sustavu. Najsnažnija strategija spremnika nije najsloženija; to je ona koja pouzdanu isporuku čini rutinom.

Portret autora bloga

Mihajlo

Ja sam Mihajlo — programer vođen znatiželjom, disciplinom i stalnom željom da stvorim nešto smisleno. Dijelim uvide, tutorijale i besplatne usluge kako bih pomogao drugima da pojednostave svoj rad i rastu u svijetu softvera i umjetne inteligencije koji se neprestano razvija.