Modul 9 · 9.1
Razumijevanje kontejnera
Modul 9: Docker i docker compose · Vrijeme čitanja: 10 minuta
Cilj učenja: Nakon ove lekcije moći ćete objasniti što je kontejner, po čemu se razlikuje od virtualnog stroja, gdje ostaju podaci kontejnera i kada Docker na Vašem poslužitelju ima smisla.
Ključni pojmovi: image, kontejner, sloj, registry (Docker Hub), tag, digest, namespaces, cgroups, zajednička jezgra (kernel), prolazni datotečni sustav, volume, bind mount, objavljivanje priključka, službeni image
Zašto kontejneri?
Zamislite da na svom VPS-u želite pokrenuti statusnu stranicu koja pokazuje radi li Vaša web-stranica. Program je napisan u Node.js-u, treba određenu verziju Node.js-a i još dvjestotinjak biblioteka. Bez kontejnera sve to instalirate na poslužitelj, uz web-poslužitelj i bazu podataka. Godinu dana kasnije želite drugi program kojem treba druga verzija Node.js-a. Tada počinju glavobolje.
Kontejner rješava taj problem. Autor programa isporučuje program zajedno sa svime što mu treba, u jednom paketu: imageu. Na poslužitelju taj image pokrećete kao kontejner. Program vidi vlastite datoteke, vlastiti Node.js, vlastite biblioteke i ne sukobljava se s ostatkom poslužitelja. Više Vam ne treba? Uklonite kontejner i image i u /usr ili /etc ne ostaje ništa.
Docker je najpoznatiji alat za preuzimanje imagea i pokretanje kontejnera. Postoje i alternative (Podman, sam containerd), ali pojmovi su posvuda isti.
Image, kontejner i registry
Tri riječi koje ćete stalno susretati:
- Image: predložak samo za čitanje s datotečnim sustavom (program, biblioteke, postavke) i naredbom koja se treba pokrenuti. Image se sastoji od slojeva: osnovni sloj (na primjer goli Debian), na njemu sloj s Node.js-om, a na njemu program. Dva imagea s istim osnovnim slojem dijele taj sloj na Vašem disku.
- Kontejner: pokrenuta (ili zaustavljena) instanca imagea. Iznad slojeva samo za čitanje kontejner dobiva vlastiti tanki sloj za pisanje. Iz jednog imagea možete pokrenuti deset kontejnera.
- Registry: mjesto na kojem se nalaze imagei, kao što je Docker Hub (
docker.io) ili GitHubov registry (ghcr.io). Docker preuzima image naredbomdocker pull.
Naziv imagea izgleda ovako:
louislam/uptime-kuma:2
caddy:2
vaultwarden/server:latestDio iza dvotočke je tag: oznaka za verziju. Tag se može promijeniti: caddy:2 danas pokazuje na drugi build nego za tri mjeseca, čim izađe nova verzija 2.x. Želite li točno zabilježiti koji image pokrećete, upotrijebite digest: otisak sadržaja, na primjer caddy@sha256:.... On se nikada ne mijenja. Tag latest samo je naziv koji odabire autor; ne znači automatski "najnovija stabilna verzija" i zato je loš izbor ako želite znati što se izvršava.
Nije virtualni stroj
Kontejner nalikuje malom virtualnom stroju, ali to nije. Ta je razlika važna za sigurnost.
| Virtualni stroj (kao Vaš VPS) | Kontejner | |
|---|---|---|
| Jezgra (kernel) | Vlastita jezgra | Dijeli jezgru hosta |
| Pokretanje | Od nekoliko sekundi do nekoliko minuta, cijeli operacijski sustav | Obično unutar sekunde, samo program |
| Odvajanje | Putem hipervizora, na razini hardvera | Putem jezgre: namespaces i cgroups |
| Veličina | Gigabajti | Često od nekoliko desetaka do nekoliko stotina megabajta |
Kontejner je zapravo običan proces na Vašem poslužitelju koji jezgra smješta u izolirano okruženje:
- namespaces osiguravaju da proces ima vlastiti pogled na datoteke, procese, mrežu i korisnike. U kontejneru se programu čini da je proces broj 1 i ne vidi ostatak Vašeg poslužitelja;
- cgroups ograničavaju koliko procesora i memorije smije koristiti.
Budući da svi kontejneri dijele istu jezgru, odvajanje je manje strogo nego između dvaju VPS-ova. Propust u jezgri ili kontejner koji dobije previše prava može ugroziti host. Zato vrijede pravila iz ovog modula: pokrećite samo imagee kojima vjerujete, ne dajte kontejnerima više prava nego što trebaju i nikada ne montirajte /var/run/docker.sock ili / u kontejner (lekcija 9.3 i 10.2).
Gdje ostaju Vaši podaci?
Ovo je klasična zamka za početnike. Sloj za pisanje kontejnera je prolazan: ako uklonite kontejner (na primjer pri ažuriranju, lekcija 9.4), nestaje sve što je program u njega zapisao. Podaci koji moraju ostati zato pripadaju izvan kontejnera:
- Volume: prostor za pohranu kojim upravlja sam Docker (pod
/var/lib/docker/volumes/). Dajete mu naziv, na primjeruptime-kuma, i povezujete ga s mapom u kontejneru:-v uptime-kuma:/app/data. - Bind mount: obična mapa na Vašem poslužitelju koju priključujete u kontejner:
-v /srv/vaultwarden:/data. Praktično je jer datoteke vidite izravno i lako ih uključujete u sigurnosnu kopiju (modul 8).
Kontejner s dobro postavljenim volumeima možete baciti i ponovno izraditi bez gubitka podataka. Upravo tako funkcionira ažuriranje: preuzmete novi image, uklonite stari kontejner i pokrenete novi kontejner na istim volumeima. Zato volumee uvrstite u svoj plan sigurnosnog kopiranja (lekcija 8.1).
Objavljivanje priključaka
Kontejner ima vlastitu mrežu. Web-program koji u kontejneru sluša na priključku 3001 nije dostupan izvan poslužitelja dok taj priključak ne objavite: -p 3001:3001 (priključak hosta:priključak kontejnera). Pazite: bez adrese Docker objavljuje priključak na svim adresama Vašeg poslužitelja, dakle 0.0.0.0 i [::]. To znači: dostupno s cijelog interneta, a Docker to postavlja zaobilazeći ufw (lekcija 9.3). Sigurna je navika objavljivati na loopback adresi, -p 127.0.0.1:3001:3001, uz reverse proxy s https-om ispred (lekcija 9.4).
Tko izrađuje image?
Image je tuđi softver koji se na Vašem poslužitelju može izvršavati kao root. Zato provjerite tko je autor:
- Docker Official Images (kao
caddy,nginx,postgres) održava Docker zajedno s autorima; - imagei samih autora (kao
louislam/uptime-kumaivaultwarden/server), prepoznatljivi po nazivu koji navodi web-stranica projekta; - imagei nepoznatih osoba s nazivima koji nalikuju pravima: ne koristite ih.
Uvijek koristite naziv naveden na službenoj web-stranici projekta, a ne prvi koji Vam izbaci pretraživanje.
Kada da, kada ne?
Docker je praktičan za programe koje autor isporučuje kao image, za usluge koje želite moći brzo ukloniti ili premjestiti te za pokretanje više programa s različitim zahtjevima jedan uz drugi. Za osnovu poslužitelja (SSH, vatrozid, ažuriranja) ne koristite kontejnere. Jedna web-stranica s nginxom i PHP-om iz repozitorija paketa (lekcija 7.2) odlično radi bez Dockera. Kontejner dodaje sloj koji morate razumjeti i ažurirati; koristite ga kada od toga imate koristi.
Sažetak
- Image je predložak samo za čitanje, izgrađen u slojevima; kontejner je pokrenuta instanca s vlastitim slojem za pisanje.
- Kontejneri dijele jezgru hosta i izolirani su pomoću namespaces i cgroups: lakši su od VM-a, ali manje strogo odvojeni.
- Sloj za pisanje je prolazan: trajni podaci pripadaju u volume ili bind mount, a oni pripadaju u Vašu sigurnosnu kopiju.
- Tag se može promijeniti, digest ne može;
latestgovori malo. - Objavljujte priključke na 127.0.0.1 i koristite samo imagee autora ili službene imagee.
Kviz
Zadatak
Zadatak O9.1: Kontejner ili ne? Odaberite dva programa koja želite pokrenuti na svom poslužitelju (ili kao primjer upotrijebite Uptime Kuma i WordPress stranicu). Za svaki program provjerite isporučuje li autor službeni image i pod kojim nazivom, koji biste tag odabrali, koja mapa sadrži trajne podatke i na kojem priključku program sluša. Zatim objasnite biste li ga pokretali u kontejneru ili iz repozitorija paketa te zašto.
Zadatak O9.1: Kontejner ili ne?
Ovaj zadatak rješavate sami; nitko ga ne provjerava. Označite što ste napravili i označite zadatak kao završen.
Uptime Kuma: louislam/uptime-kuma s oznakom verzije, podaci u /app/data, port 3001, objava na 127.0.0.1 iza reverse proxyja. Odaberite image autora ili Official Image, s oznakom verzije i imenovanom mapom za podatke.
Vaše kvačice i bilješke ostaju samo u ovom pregledniku; ne šaljemo ih nikamo. Ako ste prijavljeni, u Moji tečajevi čuvamo samo podatak da ste zadatak završili.
Dodatno štivo
- Docker dokumentacija, What is a container?: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Docker dokumentacija, Volumes: https://docs.docker.com/engine/storage/volumes/
- Docker dokumentacija, Port publishing and mapping: https://docs.docker.com/engine/network/port-publishing/
- Docker Official Images: https://docs.docker.com/docker-hub/repos/manage/trusted-content/official-images/
