Docker konteineriai: kam jie reikalingi

Kas tie Docker konteineriai ir kodėl visi apie juos kalba

Jei dirbate IT srityje ar bent šiek tiek domitės programavimu, tikriausiai jau girdėjote apie Docker. Šis įrankis per pastaruosius kelerius metus tapo beveik standartu programų kūrime ir diegime. Bet kas gi tie konteineriai ir kodėl jie tapo tokie populiarūs?

Paprasčiausiai tariant, Docker konteineriai – tai būdas supakuoti jūsų programą kartu su visomis jos priklausomybėmis į vieną standartizuotą vienetą. Įsivaizduokite, kad kuriate programą savo kompiuteryje. Ji puikiai veikia jūsų aplinkoje, bet kai bandote ją paleisti kolegos kompiuteryje arba serveryje – staiga kažkas nebeveikia. Skirtingos bibliotekų versijos, kitokia operacinė sistema, trūkstami paketai – klasikinė „pas mane veikia” situacija.

Docker sprendžia būtent šią problemą. Konteineris yra tarsi lengva virtuali mašina (nors techniškai tai ne tas pats), kurioje yra viskas, ko reikia jūsų programai veikti: kodas, bibliotekos, sisteminiai įrankiai, nustatymai. Ir svarbiausia – šis konteineris veiks vienodai bet kurioje sistemoje, kurioje įdiegtas Docker.

Virtualios mašinos vs konteineriai: kuo jie skiriasi

Daugelis žmonių, pirmą kartą susidūrę su Docker, galvoja: „Tai tiesiog virtualios mašinos, ką čia naujo?” Bet skirtumas yra esminis ir būtent jis daro konteinerius tokius patrauklius.

Virtuali mašina emuliuoja visą kompiuterį – su savo operacine sistema, branduoliu, virtualiais įrenginiais. Jei norite paleisti tris virtualias mašinas, jums reikės trijų pilnų operacinių sistemų kopijų. Tai reiškia daug resursų – disko vietos, operatyviosios atminties, procesoriaus galios.

Docker konteineriai veikia kitaip. Jie dalijasi pagrindinės sistemos branduoliu, bet turi izoliuotą failų sistemą, procesus ir tinklą. Rezultatas? Konteineris užsikrauna per kelias sekundes (o ne minutes kaip VM), užima šimtus megabaitų (o ne gigabaitus), ir galite paleisti dešimtis konteinerių toje pačioje aparatinėje įrangoje, kur tilptų tik kelios virtualios mašinos.

Žinoma, yra ir trūkumų. Konteineriai nėra tokie izoliuoti kaip virtualios mašinos. Jei reikia paleisti Windows programą Linux serveryje – konteineriai čia nepadės (nors Docker turi sprendimų ir šitai, bet tai jau sudėtingiau). Tačiau daugumai šiuolaikinių web aplikacijų konteineriai yra idealus pasirinkimas.

Realios problemos, kurias sprendžia Docker

Teorija teorija, bet pažiūrėkime, kokias konkrečias problemas Docker sprendžia kasdieniame darbe.

Priklausomybių pragaras. Turite projektą, kuris naudoja Python 3.7, specifinę NumPy versiją, PostgreSQL 11 ir dar keliolika bibliotekų. Kitas projektas reikalauja Python 3.10 ir PostgreSQL 14. Trečias – Node.js su MongoDB. Be Docker turėtumėte viską instaliuoti į savo sistemą, spręsti versijų konfliktus, naudoti virtualias aplinkas. Su Docker? Kiekvienas projektas turi savo konteinerį su tiksliai tomis priklausomybėmis, kurių reikia. Jokių konfliktų.

Naujų komandos narių įjungimas. Prisimenu projektą, kur naujo programuotojo aplinkos paruošimas užtrukdavo visą dieną. Instaliuoti duomenų bazę, konfigūruoti, užpildyti testiniais duomenimis, įdiegti cache serverį, message queue… Su Docker? Paleidi docker-compose up ir po penkių minučių viskas veikia. Dokumentacija tampa kodu.

Vienodumas tarp aplinkų. Kūrėjo kompiuteris, testavimo serveris, produkcinė aplinka – visur tas pats konteineris. Jokių „keistų” klaidų, kurios pasirodo tik produkcijoje, nes ten šiek tiek kitokia aplinka.

Kaip praktiškai pradėti naudoti Docker

Gana teorijos – pažiūrėkime, kaip tai atrodo praktikoje. Tarkime, turite paprastą Python Flask aplikaciją.

Be Docker turėtumėte paaiškinti kolegai: „Instaliuok Python 3.9, tada pip install flask, redis, psycopg2, dar reikia PostgreSQL serverio, Redis serverio…” Ir taip toliau.

Su Docker sukuriate Dockerfile:

FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]

Ir docker-compose.yml:

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: slaptazodis
  redis:
    image: redis:6

Dabar bet kas gali paleisti visą jūsų aplikaciją su duomenų baze ir Redis viena komanda: docker-compose up. Jokių instrukcijų, jokio konfigūravimo – tiesiog veikia.

Docker mikroservisų architektūroje

Viena sritis, kur Docker tikrai sušvinta, yra mikroservisai. Vietoj vienos didelės monolitinės aplikacijos, kuriate keliolika mažų servisų, kiekvienas atsakingas už savo funkcionalumą.

Pavyzdžiui, e-parduotuvė galėtų turėti: autentifikacijos servisą, produktų katalogo servisą, krepšelio servisą, mokėjimų servisą, pranešimų servisą. Kiekvienas – atskiras konteineris, galbūt net rašytas skirtinga programavimo kalba, jei tai turi prasmę.

Kodėl tai naudinga? Galite atnaujinti mokėjimų servisą neliesdami kitų dalių. Jei produktų katalogas gauna daug apkrovos – galite paleisti daugiau jo konteinerių. Vienas servisas sugedo? Kiti tęsia darbą. Skirtingos komandos gali dirbti su skirtingais servisais netrukdydamos viena kitai.

Žinoma, mikroservisai turi ir savo iššūkių – tarpservisinis komunikavimas, duomenų konsistencija, monitoringas tampa sudėtingesni. Bet Docker bent jau palengvina pačių servisų valdymą ir diegimą.

Saugumo aspektai ir geriausia praktika

Docker konteineriai nėra magiškas saugumo sprendimas. Tiesą sakant, neteisingai naudojami jie gali sukurti papildomų saugumo problemų.

Dažniausia klaida – paleisti konteinerius su root teisėmis. Daugelis oficialių Docker image’ų pagal nutylėjimą veikia kaip root, o tai reiškia, kad jei užpuolikas įsilaužtų į konteinerį, jis turėtų pilnas administratoriaus teises jame. Geriau sukurti atskirą vartotoją Dockerfile:

RUN useradd -m appuser
USER appuser

Kita problema – pasenę base image’ai. Jei jūsų Dockerfile prasideda FROM ubuntu:18.04, o tas image’as nebuvo atnaujintas porą metų, jame gali būti žinomų saugumo spragų. Reguliariai atnaujinkite base image’us ir naudokite įrankius kaip Trivy ar Snyk, kurie nuskenuoja konteinerius ieškodami pažeidžiamumų.

Taip pat venkite įdėti slaptažodžius ir API raktus tiesiai į Dockerfile ar image’us. Naudokite Docker secrets arba aplinkos kintamuosius, kurie perduodami runtime metu, ne build metu.

Ir dar vienas patarimas – naudokite .dockerignore failą. Panašiai kaip .gitignore, jis nurodo, ko nekopijuoti į konteinerį. Nereikia ten jūsų node_modules, .git katalogo ar lokalių konfigūracijos failų.

Orkestracija: kai vieno konteinerio nebepakanka

Kai jūsų aplikacija auga, vien Docker nebepakanka. Reikia valdyti dešimtis ar šimtus konteinerių, automatiškai juos masteliuoti, paskirstyti apkrovą, atstatyti sugedusius. Čia į sceną įžengia orkestratoriai.

Kubernetes yra de facto standartas šioje srityje. Tai galinga, bet ir sudėtinga sistema. Jei tik pradedate, ji gali atrodyti kaip bandymas užmušti musę bazuka. Bet kai jūsų infrastruktūra auga, Kubernetes funkcionalumas tampa neįkainojamas: automatinis masteliavimas, self-healing (automatiškai perkelia konteinerius, jei serveris sugenda), rolling updates, service discovery ir daug daugiau.

Yra ir paprastesnių alternatyvų. Docker Swarm yra integruotas į patį Docker ir daug lengviau pradėti naudoti. Nomad nuo HashiCorp yra kitas geras pasirinkimas. Jei naudojate cloud platformas – AWS ECS, Google Cloud Run ar Azure Container Instances gali būti paprastesni variantai nei pilnavertis Kubernetes.

Bet nesvarbu, kurį orkestratorių pasirinksite, principas tas pats: deklaratyviai aprašote, kaip norite, kad jūsų aplikacija veiktų (kiek konteinerių, kokia konfigūracija, kaip jie tarpusavyje komunikuoja), o orkestratoriaus darbas – užtikrinti, kad realybė atitiktų šį aprašymą.

Kas toliau: konteinerių ateitis ir alternatyvos

Docker revoliucionizavo programų kūrimą ir diegimą, bet technologijos nestovi vietoje. Jau dabar matome įdomių pokyčių.

Pirma, pats Docker nebėra vienintelis žaidėjas. Podman yra alternatyva, kuri neturi daemon proceso ir gali veikti be root teisių – tai saugumo privalumas. BuildKit pagerina image’ų kūrimo procesą. Containerd ir CRI-O yra lightweight runtime’ai, kuriuos naudoja Kubernetes.

Antra, serverless ir funkcijos kaip paslauga (FaaS) iš dalies konkuruoja su konteineriais. Vietoj to, kad valdytumėte konteinerius, tiesiog įkeliate kodą, o platforma pasirūpina viskuo kitu. AWS Lambda, Google Cloud Functions, Azure Functions – visi jie leidžia paleisti kodą nereikalaujant galvoti apie infrastruktūrą.

Bet konteineriai niekur nedingsta. Jie tapo fundamentalia šiuolaikinės infrastruktūros dalimi. Net serverless platformos už kulisų dažnai naudoja konteinerius. WebAssembly gali ateityje pakeisti kai kuriuos konteinerių naudojimo atvejus, bet tai dar toli.

Kodėl verta išmokti Docker dabar

Grįžtant prie pradinio klausimo – kam gi tie Docker konteineriai reikalingi? Atsakymas paprastas: jie sprendžia realias, kasdienes problemas programų kūrime ir diegime.

Jie leidžia kurti nuoseklias, atkuriamas aplinkas. Jie supaprastina priklausomybių valdymą. Jie daro CI/CD procesus patikimesnius. Jie palengvina perėjimą į mikroservisų architektūrą ir cloud platformas.

Bet svarbiausia – Docker tapo industrijos standartu. Dauguma šiuolaikinių darbo skelbimų DevOps, backend ar net frontend srityse mini Docker kaip reikalavimą ar bent privalumą. Tai įgūdis, kuris tikrai atsipirks.

Pradėti nėra sunku. Įdiekite Docker Desktop, pereikite kelis tutorial’us, pabandykite sukonteineriuoti savo projektą. Padarykite klaidas, pasiskaitykite dokumentaciją, paklauskite bendruomenės. Po kelių savaičių praktikos Docker taps natūralia jūsų workflow dalimi, ir stebėsitės, kaip anksčiau be jo išsiversdavote.

Konteineriai nėra tobulas sprendimas visoms problemoms, bet jie tikrai yra vienas svarbiausių įrankių šiuolaikinio programuotojo arsenale. Ir geriausia žinia – jie tikrai ne tokie bauginantys, kaip gali atrodyti iš pradžių.

Daugiau

Istio service mesh Kubernetes klasteriuose