Docker: enkapsulirana aplikacija
NAS ne mora da bude samo skladište fajlova – možete da mu dodelite i funkciju pokretanja virtuelnih mašina enkapsuliranih u docker-e. Videćete da je to čitav jedan novi svet…
Dugo sam planirao nabavku NAS uređaja za lokalnu mrežu, a godinama se nagomilalo raznog sadržaja koji negde treba čuvati. Dokumenta i slike su mi svakako na glavnom računaru, ali zgodno je imati još jedan uređaj u blizini na koji se može smestiti rezervna kopija, pa i neki video-zapis koji treba pogledati na televizoru. Osnovna potreba koju sam hteo da rešim bio je dodatni prostor za dokumenta u lokalnoj mreži, uglavnom slike i filmove napravljene u digitalno doba. Znao sam da uređaj koji planiram da kupim neće biti otvoren za druge instalacije i servise, a to mi nije ni bio cilj. Zbog toga nisam obraćao pažnju koji procesor i koliko radne memorije ima. Plan je bio da ima najmanje četiri hot-swap diska i barem dve mrežne kartice koje mogu da se povežu u tim. Neki stariji i jeftiniji NAS modeli koje sam probao bili su veoma spori, iako su imali gigabitnu mrežnu kartu. Prema tom iskustvu, kopiranje podataka izgledalo je kao da im je mrežna kartica 100 ili čak 10 megabita.
Zbog prethodnog iskustva, izabrao sam QNAP, bez mnogo poređenja s drugim proizvodima. Kvalitet i brzina su mi bili poznati, baš kao i mogućnost kreiranja RAID-a. Kriterijum mi je bio maksimalni broj diskova, brz uređaj i dve mrežne kartice. Spletom raznih okolnosti, došao sam do modela TS-431KX-2G, ubacio stare diskove da vidim kako to radi i bio sam zadovoljan izborom. Pristup podacima, naročito čitanje, zadovoljilo je moje potrebe.
U početku me nije mnogo zanimalo šta se dešava u slučaju otkaza uređaja jer plan mi je bio da na njemu čuvam samo rezervne kopije raznih datoteka i poneki manje bitan sadržaj. Računao sam da mogu da podnesem gubitak rezervne kopije tih podataka i tu sam pogrešio. Redundansa je odlična stvar, ako se tačno zna gde se nalazi original, a gde kopija. Toj granici sam vrlo brzo smanjio važnost, pa su se među kopijama našli i originali. Za neke stvari tako je bilo najjednostavnije, pa je umesto da backup bude jednosmeran ka QNAP-u, sada dvosmeran.
Virtuelna mašina na NAS-u?
Jedan od prvih servisa koje sam počeo da koristim u lokalnoj mreži pre mnogo godina bilo je deljenje dokumenata. Na taj način sam mogao sadržajima da pristupam s drugih uređaja, mobilnih telefona i tableta, a prioritet je imao KODI instaliran na televizoru. S vremenom se povećavao broj servisa, pa je postalo jasno da ih je potrebno grupisati na drugi računar koji neću povremeno isključivati. Taj problem sam rešio prilikom prvog sledećeg upgrade-a glavnog računara, kada sam stari preimenovao u „server“ i povećavao broj servisa. Prvo je došao FTP, pa SyncTrayzor (zapravo „upakovani“ syncthing), zatim jDownloader i drugo.
Docker je način da određeni servis pokrenete u okruženju koje nema dodira sa spoljnim svetom, tj. operativnim sistemom na kome se izvršava. Nešto kao sandbox, kada programu nije dozvoljen pristup nijednom resursu
Na samom početku podešavanja NAS-a pogledao sam spisak dostupnih programa koji se na njemu mogu izvršavati. Iako je lista velika, nije mogla da pokrije sve moje potrebe. Tada mi je jedan kolega dao predlog da podignem virtuelnu mašinu na NAS-u. Uvek sam NAS smatrao mestom za čuvanje podataka, ne za pružanje drugih usluga. Ideja je bila odlična, hardver je prilično napredovao, pa zašto jedan NAS ne bi dobio još neku funkciju.
Naravno da je bilo moguće, pod uslovom da je procesor kompatibilan sa x86. U modelu koji sam kupio ugrađen je AnnapurnaLabs AL-214 procesor i to je raspršilo moje oduševljenje. Prvo što sam pomislio bilo je: „Promašaj“. No, uteha je bila da NAS treba da ostane u okviru svoje namene, a to je uređaj za smeštanje podataka. Gorak ukus je ostao još neko vreme, podsećajući me da sam napravio loš izbor platforme – do trenutka kada sam otkrio da je na tom uređaju moguće koristiti docker.
Šta je to docker?
O docker-u sam znao veoma malo. Interesovanje mi je pobudilo predavanje održano pre više godina, pa sam dodatne informacije pronalazio u tekstovima na Internetu. Pratio sam dešavanja u toj oblasti, kako rastu baze programa, i svaki put iznova zaključivao da je to odličan i dobro osmišljen sistem, koji u mom slučaju nema upotrebnu vrednost. Dokumentacija koja se može naći na Internetu je obimna, a do potrebnih informacija se dolazi lako.
Bez praktičnog iskustva s docker-om i s ograničenim poznavanjem Linux-a, krenuo sam u avanturu instalacije „samo jednog servisa“ na QNAP, jer mu je tamo najbolje mesto: Syncthing. Procesor ima četiri jezgra i radi na 1,7 GHz, to će sigurno biti dovoljno! Dakle, otvaram još jedan projekat za koji tek treba da pronađem malo vremena. Dodatni podsticaj je bio mogućnost da uz praktično iskustvo naučim nešto novo. Nadam se da će tekst pomoći nekome čiji je svakodnevni posao baziran na Windows operativnim sistemima, da sagledaju mogućnosti docker-a i počnu da ga koriste.
Za moje potrebe, bilo je dovoljno da koristim gotove docker image, pa su svi kontejneri koje sam instalirao preuzeti sa https://hub.docker.com/. Ako se nekome dopadne način kako se instaliraju, pokreću i koriste kontejneri, a ne pronađu popularno i gotovo rešenje za problem koji imaju, vrlo lako će naučiti i docker compose.
Bilo kako bilo, pre samog početka očekivao sam da će ugrađena 2 Gb memorije biti malo, pa sam je odmah zamenio sa 8 Gb. Nakon svih instalacija i podešavanja prema potrebama lokalnih uređaja, pokazalo se da to možda nije bilo potrebno jer je najčešće zauzeto tek 20 odsto memorije.
Server, klijent i drugi termini
Docker je način da određeni servis pokrenete u okruženju koje nema dodira sa spoljnim svetom, tj. operativnim sistemom na kome se izvršava. Najbliže poređenje je sandbox, kada se pokrenut program izvršava na istom operativnom sistemu kao i drugi programi, samo mu nije dozvoljen pristup nijednom resursu (koristi se najčešće za proveru rada programa s nepouzdanog izvora, da li je maliciozan itd.) Iako postoji izvesna sličnost s virtuelnim mašinama, glavna razlika je ujedno i najveća prednost: umesto instaliranja operativnog sistema u svaku virtuelnu mašinu, ovde se koristi operativni sistem domaćina. Tako se ne rasipaju resursi na virtuelizaciju uređaja i izvršavanje dodatnog operativnog sistema.
Listing 1
docker run –name=portainer -d \
–restart=unless-stopped \
-p 8000:8000 \
-p 9000:9000 \
-p 9443:9443 \
-v /share/CACHEDEV1_DATA/docker/portainer:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:latest
U docker svetu, virtuelne mašine se nazivaju kontejneri (containers). Oni se pokreću na osnovu kreiranih šablona (image) koje možete praviti sami ili preuzeti gotove iz nekog registra (registry). Pretpostavljam da nećete imati potrebu da menjate unapred podešen registar – Docker Hub, baš kao što u početku neće ni biti potrebe da ih sami kreirate. Napravljen je u duhu Linux-a i srodnih operativnih sistema. Koristi klijent-server arhitekturu, mada će u najvećem broju slučajeva i server (dockerd) i klijent (docker) biti na istom računaru. Komunikacija između njih se u opštem slučaju vrši kroz mrežu (IP Socket), ali ako se nalaze na istom računaru, biće korišćen Unix Socket, uslovno rečeno „datoteka na disku“ (/var/run/docker.sock).
Lokacija i naziv navedene datoteke biće važni za instalaciju prvog kontejnera opisanog u ovom tekstu. Docker kontejner se može pokrenuti, pauzirati i zaustaviti. Programi koji se izvršavaju unutar kontejnera su isti kao oni koji bi se izvršavali na samom računaru gde je docker instaliran. Postoji skup potrebnih datoteka i direktorijuma, ali sve izmene koje programi u kontejneru naprave, biće izbrisane nakon njegovog zaustavljanja. Možda na prvi pogled ne izgleda tako, ali ovo pravilo je zapravo dobro iz nekoliko razloga. Prvo, razdvaja se važno od nevažnog, a drugo, lako se pokreće nova verzija programa, ona nema uticaj na druge programe i kontejnere na istom računaru.
Da bi neke datoteke „preživele“ isključivanje, one se moraju nalaziti van kontejnera. Kreiranjem kontejnera, definiše se jedna ili više lokacija na disku gde je kontejneru dozvoljen pristup da može kreirati i menjati datoteke. To je sve definisano u šablonu (volumes), a mi kao korisnici treba da pročitamo uputstvo i pripremimo tražene lokacije za svaki kontejner. Ako to ne uradimo, ti podaci će se izgubiti nakon zaustavljanja kontejnera.
Postoji izvesna sličnost s virtuelnim mašinama, ali se umesto instaliranja operativnog sistema u svaku virtuelnu mašinu, ovde za rad koristi operativni sistem domaćina
Osim datoteka, za vezu sa spoljnim svetom, kontejneru može biti dodeljena i mreža. Kroz mrežu se može upravljati programom u kontejneru (npr. Web based UI), a njemu će biti omogućena veza ka drugim uređajima i servisima. U tu svrhu, kontejneru se može dozvoliti pristup određenoj mreži, dodeliti zasebna IP adresa ili iskoristiti IP adresa domaćina, a preusmeriti mu samo saobraćaj koji na tu adresu dolazi po određenom portu. U primeru koji ću opisati kasnije, može se omogućiti pristup različitim mrežama, tako da kontejner dobije pristup/izlaz na više strana. Docker server (daemon: docekrd) se izvršava s najvišim pravima (root) na sistemu. To je potrebno zbog upravljanja procesima, mrežom i datotekama na disku.
Kontejneri svakako nemaju prava pristupa ničemu osim precizno dozvoljenim resursima (mreža, prostor na disku), ali sa stanovišta bezbednosti, bolje je da rade s manjim skupom dozvola, „u ime“ nekog korisnika. Takođe, prava pristupa datotekama kreiranim iz kontejnera biće usklađena s ovim korisnikom i grupom.
Korisnici
Instalacija docker-a na QNAP se svodi na instalaciju Container Station (kroz App Center). Prve korake možete napraviti odmah, iz browser-a i videti kako je sistem organizovan. Tu će biti dostupan ograničen skup kontejnera koje možete napraviti (Create), lista preuzetih i pokrenutih kontejnera i drugo.
U mom slučaju nije sve bilo podešeno kako se očekuje. Na primer, UID i GID (ID korisnika i grupe, kontekst u kome se izvršava kontejner) nije bio podešen. Zapravo, nije ni postojao odgovarajući korisnik (i grupa), a to sam otkrio tek kada sam instalirao Syncthing.
Namena ovog kontejnera je da sinhronizuje podatke s drugim uređajima, a koristim ga za vezu s prenosivim uređajima i računarima mojih prijatelja. Na primer, jedan folder sam podelio s mobilnim telefonom i sve što tu snimim, pojaviće se ubrzo na tom uređaju. Slike s mobilnog telefona će se jednosmerno kopirati na drugo mesto, potpuno automatski. Ovaj kontejner može da menja datoteke na disku, ali ako nije dobro podešen kontekst u kome se kontejner izvršava, neću imati prava da menjam ili brišem te datoteke s računara.
Podrazumevana vrednost za UID i GID je 1000, pa je dovoljno u konzoli pokrenuti komandu:
sudo adduser -u 1000 dockeruser
Tako će biti kreirana i grupa i korisnik dockeruser, a po želji u tu grupu možete dodati druge korisnike kojima treba dozvoliti pristup datotekama:
sudo usermod -a -G dockeruser
Na QNAP-u sam na samom početku kreirao nekoliko korisnika i dodelio im prava pristupa podacima. Ako je potrebno razdvojiti podatke po važnosti, ograničiti neke korisnike a drugima dati slobodu, onda je najbolje o tome razmišljati pre podešavanja NAS-a.
Mreža
Svaki kontejner može biti povezan na neku (docker) mrežu. Instalacijom docker-a biće kreirane tri mreže: none, host i bridge (default), čija imena su opisna prema „dometu“ koji će kontejner imati. Ako nije drugačije navedeno pri kreiranju kontejnera, biće povezani na bridge. To znači da će kontejner deliti adresu s računarom na kome se nalazi, po definisanom portu.
Prema potrebama, moguće je docker-u dodati druge mreže. Ako ste IoT uređaje odvojili od računarske mreže, onda bi trebalo pokrenuti komandu poput ove:
docker network create -d \
ipvlan \
–subnet=192.168.222.0/24 \
–gateway=192.168.222.254 \
-o parent=eth1[.VLAN] \
Prilagodite IP opseg, upišite VLAN i ime mreže.
Šta prvo pokrenuti?
Na početku treba napraviti plan gde će se na disku nalaziti podaci koje koriste kontejneri. Nakon nekoliko dana premeštanja kontejnera po diskovima, zaključio sam da je najbolje napraviti jedan folder u kome će svi kontejneri imati svoj prostor. Tu će čuvati svoja podešavanja (razne config datoteke) i podatke koje obrađuju, a procedura za pravljenje rezervne kopije biće jednostavnija. Tako sam došao do zaključka da je dobro mesto na volumenu /data/docker/, gde će u zasebnim folderima biti smešteni podaci za kontejnere. (Putanja do te lokacije iz komandne linije je malo drugačija: /share/CACHEDEV1_DATA/docker/.)
Iako je moguće pokretati kontejnere kroz GUI, Container Station nije baš najbolji izbor. Ne samo da je teško ili nemoguće podesiti sve potrebne parametre pri pokretanju, već za svako novo pokretanje kontejnera treba kliktati i paziti da se nešto ne zaboravi. Mnogo je brže i lakše copy / paste već pripremljene komandne linije. Za sve kontejnere koje koristim imam sačuvane recepte za njihovo pokretanje, po nekoliko redova u tekst datoteci…
Listing 2
docker run -d –name homeassistant \
–restart=unless-stopped \
–net qnet-static-bond0-e5ddec \
–ip 192.168.0.3 \
-e TZ=Europe/Belgrade \
-v /share/CACHEDEV1_DATA/docker/homeassistant:/config \
homeassistant/home-assistant:latest
Za nadgledanje rada docker-a lakše je koristiti GUI. Tako dolazimo do prvog kontejnera koji instaliram: Portainer (https://www.portainer.io/). Ovom kontejneru je potreban pristup serveru, a kako će biti na istom računaru, onda samo treba navesti lokaciju gde se nalazi docker.sock, kao u listingu 1.
Komanda kojom klijent kreira i pokreće kontejner (zapravo, predefinisanu komandu u njemu) jeste docker run. Ime kontejnera je nešto čime ćemo ga prepoznati u listi, proslediti mu neke informacije, zaustaviti ga ili ukloniti:
docker stop portainer
docker rm portainer
Portainer-u se pristupa po portu https://:9443 (ima lokalni sertifikat koji neće zadovoljiti Firefox i druge browser-e) ili bez sertifikata po portu 9000. U navedenom primeru je mapiran direktorijum gde će biti čuvani podaci ovog kontejnera:
-v /share/CACHEDEV1_DATA/docker/portainer:/data
Kada program u kontejneru želi da pristupi direktorijumu /data, on će biti povezan na lokalni direktorijum /share/CACHEDEV1_DATA/docker/portainer (host:container). U sledećem redu je povezan docker.sock, čija putanja je ista na obe lokacije – baš tu datoteku Portainer koristi za komunikaciju s docker serverom.
Docker network
Moje putovanje u docker svet je zapravo nastalo zbog Home Assistant-a, servera za kontrolu i automatizaciju rada kućnih uređaja i senzora. Ova tema je suviše kompleksna i pomalo bolna jer verzija kernela na mom QNAP-u nije dovoljno sveža, pa sam ovaj kontejner premestio na drugi uređaj. No, za potrebe ovog teksta zanemarimo taj problem i pogledajmo kako treba ovaj kontejner pokrenuti na QNAP-u, što je prikazano u listingu 2.
Docker kontejneri se lako mogu premestiti na drugi računar, a da bi se sačuvali podaci i podešavanja, potrebno je preneti sadržaj direktorijuma u kome čuva podatke. Da bih očuvao adresu ovog servera, plan mi je bio da on dobije IP adresu iz opsega lokalne mreže, ali da se razlikuje od domaćina. Kada se podesi ceo sistem, adresa Home Assistant-a će biti upisana u neke uređaje, pa bi promena njegove IP adrese uzrokovala potrebu da se razni IoT uređaji ponovo podešavaju. Zbog toga želim da izdvojim posebnu adresu za ovaj server koja će moći da ga prati u lokalnoj mreži, bez obzira na to gde je kontejner pokrenut.
Veza kontejnera sa svetom obavlja se preko mreže, jednako stvarne kao i virtuelni svet u kome se izvršava kontejner. Instalacijom docker-a biće postavljene mreže opisnih imena: none, host i bridge. Na QNAP-u treba da bude kreirana i mreža koja ima ime u formatu qnet-static-eth1-e5ddec ili, ako su mrežne kartice povezane u tim, qnet-static-bond0-e5ddec. Ove dve mreže su povezane na LAN, tako da jednu od te dve mreže treba da dodelimo kontejneru i željenu IP adresu. Ukoliko ovih mreža nema na listi, napravite ih komandom poput ove:
docker network create -d \
qnet \
–subnet=192.168.0.0/24 \
–gateway=192.168.0.254 \
-o parent=eth1 qnet-static-eth1-e5ddec
Ovde treba voditi računa koji mrežni interfejs treba izabrati, na osnovu podešavanja QNAP-a. Dodatni problem koji sam želeo da rešim jeste pravljenje guest mreže za sve uređaje i senzore koje sam zbog bezbednosti lokalne mreže odvojio u drugi VLAN i IP opseg. Mrežu sam kreirao komandom:
docker network create \
-d ipvlan \
–subnet=192.168.211.0/24 \
–gateway=192.168.211.254 \
-o parent=bond0.2021 guest
Mreža nazvana guest imaće VLAN ID: 2021 i opseg 192.168.211.0/24. Da bi Home Assistant bio dostupan i preko ove mreže, potrebno je povezati ga i dodeliti mu IP adresu iz tog opsega:
docker network connect –ip 192.168.211.9 guest homeassistant
Uz ostala potrebna podešavanja VLAN-a na ruteru, Home Assistant je postao vidljiv na obe mreže.
Za kraj
Evo još nekoliko predloga šta možete instalirati kao docker kontejner. Prva preporuka je rešenje za uklanjanje reklama – AdGuard (adguard/adguardhome:latest). Osim što više nećete videti reklame na uređajima koji ga koriste kao DNS, možete pratiti i statistiku najposećenijih Internet lokacija, kontrolisati pristup i slično.
Veza kontejnera sa svetom obavlja se preko mreže, jednako stvarne kao i virtuelni svet u kome se izvršava kontejner
Druga preporuka je već pomenuti Syncthing (syncthing/syncthing:latest). Podešavanje je nešto složenije, ali vredi uloženog truda. Godinama ga koristim na raznim platformama i veoma sam zadovoljan. Sličan je Dropbox-u i OneDrive-u, samo što se sadržaj ne kopira na server u cloud-u, već se nalazi na onim računarima i mobilnim uređajima gde je instaliran. Podaci mogu biti kopirani u jednom smeru (na primer, nove slike s mobilnog telefona se snimaju na QNAP, a nikad ne brišu), ili dvosmerno. Odlično rešenje za sinhronizaciju podataka između svih uređaja koje koristite.
Treće, kada se lista aktivnih kontejnera poveća, dobro će doći automatska instalacija novih verzija. Prvi koji sam koristio je Watchtower (containrrr/watchtower). Samo treba pokrenuti kontejner i ostaviti ga da radi:
docker run -d –name \
watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
Kasnije sam umesto njega počeo da koristim drugi kontejner koji mi šalje obaveštenja na Telegram o svakom update-u koji napravi – Ouroboros (pyouroboros/ouroboros). Autor ga više ne održava, ali je još uvek operativan.
Korisna adresa: docs.docker.com/get-started/overview/
Autor: Miljan Jovanović