{"id":32526,"date":"2019-10-31T21:47:32","date_gmt":"2019-10-31T18:47:32","guid":{"rendered":"https:\/\/prohoster.info\/blog\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\/"},"modified":"2019-10-31T21:47:32","modified_gmt":"2019-10-31T18:47:32","slug":"protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","title":{"rendered":"Postopek razvoja in testiranja z Docker in Gitlab CI","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Predlagam, da se seznanite s transkripcijo poro\u010dila Alexandera Sigacheva iz Inventos \u201ePostopek razvoja in testiranja s Docker + Gitlab CI\u201c<\/strong><\/p>\n<p><\/p>\n<p>Tisti, ki \u0161ele za\u010denjajo uvajati postopek razvoja in testiranja na osnovi Docker + Gitlab CI, pogosto postavljajo osnovna vpra\u0161anja. Kje za\u010deti? Kako organizirati? Kako testirati?<\/p>\n<p><\/p>\n<p>To poro\u010dilo je dobro, ker strukturirano opisuje postopek razvoja in testiranja z uporabo Docker in Gitlab CI. Samo poro\u010dilo je iz leta 2017. Mislim, da lahko iz tega poro\u010dila pridobite osnove, metodologijo, idejo, izku\u0161nje z uporabo. <\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"lJsqRwULRVA\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/lJsqRwULRVA\/hqdefault.jpg\" alt=\"Predvajaj video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p>Kdor je zainteresiran, naj se preseli pod kat. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Moje ime je Aleksandr Siga\u010dev. Delam v podjetju Inventos. Povedal bom o svojih izku\u0161njah z uporabo Dockerja in o tem, kako ga postopoma uvajamo v projekte v podjetju.<\/p>\n<p><\/p>\n<p>Tema poro\u010dila: Postopek razvoja z uporabo Docker in Gitlab CI. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e30c4757e4bda1bcc3e20b16e8e2709e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To je moje drugo poro\u010dilo o Dockerju. Ob \u010dasu prvega poro\u010dila smo uporabljali Docker zgolj v razvoju na ra\u010dunalnikih razvijalcev. \u0160tevilo zaposlenih, ki so uporabljali Docker, je bilo okoli 2-3 osebe. Postopoma smo pridobili izku\u0161nje in nekoliko napredovali. Povezava na na\u0161e <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">prvo poro\u010dilo<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Kaj bo v tem poro\u010dilu? Delili bomo izku\u0161nje o tem, katere pasti smo naleteli, kako smo re\u0161evali te\u017eave. Ni vedno potekalo gladko, a nam je omogo\u010dilo, da smo napredovali.<\/p>\n<p><\/p>\n<p>Na\u0161a deviza: dockeriziraj vse, do \u010desar lahko pridemo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25ae4f97f1c502384abfe697bac502b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Katere te\u017eave re\u0161ujemo?<\/p>\n<p><\/p>\n<p>Ko je v podjetju ve\u010d ekip, je programer deljena sredstva. V\u010dasih pride do faz, ko programerja preusmerijo iz enega projekta na drugega za dolo\u010den \u010das.<\/p>\n<p><\/p>\n<p>Da se programer hitro vklju\u010di, mora prenesti izvorno kodo projekta in \u010dim hitreje zagnati okolje, ki mu omogo\u010da nadaljnje napredovanje pri re\u0161evanju nalog tega projekta.<\/p>\n<p><\/p>\n<p>Obi\u010dajno, \u010de za\u010dnemo od za\u010detka, je dokumentacije v projektu malo. Informacije o tem, kako nastaviti, ima samo nekaj starej\u0161ih uslu\u017ebencev. Zaposleni si obi\u010dajno nastavijo svoje delovno mesto v enem do dveh dneh. Da bi to pospe\u0161ili, smo uporabili Docker.<\/p>\n<p><\/p>\n<p>Naslednji razlog \u2014 standardizacija nastavitev v razvoju. Po mojem mnenju razvijalci vedno izra\u017eajo pobudo. V vsakem petem primeru se uvede po meri prirejen domen, na primer vasja.dev. Ob njem je sosed Petja, ki ima domeno petja.dev. Razvijajo spletno mesto ali nek komponent sistema, ki uporablja to domeno.<\/p>\n<p><\/p>\n<p>Ko se sistem raz\u0161iri in ta imena domen za\u010dnejo prihajati v konfiguracije, nastane konflikt razvojnih okolij in pot do spletne strani se prepisuje.<\/p>\n<p><\/p>\n<p>Enako se dogaja z nastavitvami baze podatkov. Nekdo ne posve\u010da pozornosti varnosti in dela s praznim geslom za root. Drugemu je med namestitvijo MySQL geslo povzro\u010dilo zahtevo in ugotovil je, da je geslo 123. Pogosto se zgodi, da se konfiguracija baze podatkov neprestano spreminja glede na commit razvijalca. Nekdo je popravljen, nekdo ni. Bili so triki, ko smo prenesli neko testno konfiguracijo v <code>.gitignore<\/code> in vsak razvijalec je moral namestiti bazo podatkov. To je ote\u017eilo postopek pri zagonu. Poleg vsega je treba pomisliti tudi na bazo podatkov. Bazo podatkov je treba inicializirati, vnesti geslo, vnesti uporabnika, ustvariti tabelo in tako naprej.<\/p>\n<p><\/p>\n<p>\u0160e ena te\u017eava so razli\u010dne razli\u010dice knji\u017enic. Pogosto se zgodi, da razvijalec dela na razli\u010dnih projektih. Obstaja projekt z dedovanjem, ki smo ga za\u010deli pred petimi leti (od 2017 \u2014 opomba uredni\u0161tva). Ob za\u010detku smo za\u010deli z MySQL 5.5. Obstajajo tudi sodobni projekti, kjer se trudimo vpeljati novej\u0161e razli\u010dice MySQL, na primer 5.7 ali starej\u0161e (v 2017 \u2014 opomba uredni\u0161tva).<\/p>\n<p><\/p>\n<p>Tisti, ki dela z MySQL, ve, da te knji\u017enice prina\u0161ajo s sabo odvisnosti. Zagon dveh baz skupaj je precej zapleten. Vsaj stari odjemalci se te\u017eko pove\u017eejo z novo bazo podatkov. To pa povzro\u010da ve\u010d te\u017eav.<\/p>\n<p><\/p>\n<p>Naslednja te\u017eava je, ko razvijalec dela na lokalnem ra\u010dunalniku, uporablja lokalne vire, lokalne datoteke, lokalni RAM. Vse interakcije med razvojem re\u0161itev potekajo v okviru delovanja na enem ra\u010dunalniku. Primer je, ko imamo v produkciji 3 backend stre\u017enike, razvijalec pa shranjuje datoteke v korenski imenik in od tam nginx pridobiva datoteke za odgovore na zahteve. Ko tak\u0161na koda pride v produkcijo, se izka\u017ee, da je datoteka prisotna na enem od treh stre\u017enikov.<\/p>\n<p><\/p>\n<p>Trenutno se razvija pravac mikroservisa. Kada delimo na\u0161e velike aplikacije na manje komponente koje me\u0111usobno komuniciraju. To omogu\u0107ava da se za odre\u0111eni skup zadataka izaberu tehnologije. Tako\u0111e, to omogu\u0107ava podelu rada i odgovornosti me\u0111u programerima.<\/p>\n<p><\/p>\n<p>Frontend programer, rade\u0107i na JS-u, prakti\u010dno ne uti\u010de na Backend. Backend programer, s druge strane, razvija, u na\u0161em slu\u010daju, Ruby on Rails i ne ometa Frontend. Interakcija se ostvaruje putem API-ja.<\/p>\n<p><\/p>\n<p>Kao bonus, pomo\u0107u Dockera uspeli smo da optimizujemo resurse na Staging-u. Svaki projekat, s obzirom na svoju specifi\u010dnost, zahtevao je odre\u0111ena pode\u0161avanja. Fizi\u010dki je bilo potrebno odvojiti ili po jedan virtualni server i posebno ih konfigurisati, ili deliti neko promenljivo okru\u017eenje, a projekti su mogli zavisiti jedni od drugih u zavisnosti od verzije biblioteka.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/fa5c99f90faef84a356d4791fd915830.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alati. \u0160ta koristimo? <\/p>\n<p><\/p>\n<ul>\n<li>Sama Docker tehnologija. U Dockerfile-u se opisuju zavisnosti jedne aplikacije. <\/li>\n<li>Docker-compose je veza koja povezuje nekoliko na\u0161ih Docker aplikacija.<\/li>\n<li>GitLab koristimo za \u010duvanje izvornog koda.<\/li>\n<li>GitLab-CI koristimo za sistemsku integraciju.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/b6041827a6ba928e0d33add6b79c581c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Izve\u0161taj se sastoji iz dva dela.<\/p>\n<p><\/p>\n<p>Prvi deo \u0107e govoriti o tome kako smo pokretali Docker na ra\u010dunarima programera.<\/p>\n<p><\/p>\n<p>Drugi deo \u0107e govoriti o tome kako se interaguje sa GitLab-om, kako pokre\u0107emo testove i kako implementiramo na Staging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/45746d3323d35e0d18f066c8bfcb2214.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker je tehnologija koja omogu\u0107ava (koriste\u0107i deklarativni pristup) da se opi\u0161u potrebne komponente. Ovo je primer Dockerfile-a. Ovde objavljujemo da nasle\u0111ujemo od zvani\u010dne Docker slike Ruby:2.3.0. Ona ve\u0107 sadr\u017ei instalirani Ruby verzije 2.3. Postavljamo potrebne biblioteke za kompilaciju i NodeJS. Opi\u0161emo \u0161ta kreiramo katalog <code>\/app<\/code>. Postavljamo katalog app kao radnu direktoriju. U ovu direktoriju stavljamo potrebni minimalni Gemfile i Gemfile.lock. Zatim vr\u0161imo izgradnju projekata koji instaliraju zavisnosti ovog imagea. Uvode\u0107i da \u0107e kontejner biti spreman da slu\u0161a na spolja\u0161njem portu 3000. Poslednja komanda je ona koja direktno pokre\u0107e na\u0161u aplikaciju. Ako izvr\u0161imo komandu za pokretanje projekta, aplikacija \u0107e poku\u0161ati da se izvr\u0161i i pokrenu\u0107e navedenu komandu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ba503c305ae90f49b39f4ae2cbda1668.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>To je minimalni primer docker-compose datoteke. V tem primeru prikazujemo, kako se pove\u017eeta dva kontejnerja. To je neposredno v storitvi baze podatkov in storitvi web. Na\u0161e web aplikacije v ve\u010dini primerov potrebujejo kot backend za shranjevanje podatkov kak\u0161no bazo podatkov. Ker uporabljamo MySQL, imamo primer z MySQL \u2014 a ni\u010d ne prepre\u010duje, da bi uporabili kak\u0161no drugo bazo podatkov (PostgreSQL, Redis).<\/p>\n<p><\/p>\n<p>Iz uradnega vira z Docker Hub jemljemo sliko MySQL 5.7.14 brez sprememb. Slika, ki odgovarja za na\u0161o web aplikacijo, se gradi iz trenutne mape. Ob prvem zagonu se gradi slika. Po tem se za\u017eene ukaz, ki ga tukaj izvajamo. \u010ce se vrnemo nazaj, bomo videli, da je bila dolo\u010dena ukaz za zagon preko Pume. Puma je storitev, napisana v Rubyju. V drugem primeru prepisujemo. Ta ukaz je lahko poljuben, odvisno od na\u0161ih potreb in nalog.<\/p>\n<p><\/p>\n<p>Prav tako opisujemo, da je treba preusmeriti vrata na na\u0161i host napravi razvijalca z 3000 na 3000 vrata kontejnerja. To se avtomatsko izvede s pomo\u010djo iptables in svojega mehanizma, ki je neposredno vgrajen v Docker. <\/p>\n<p><\/p>\n<p>Razvijalec se lahko, tako kot prej, pove\u017ee na kateri koli dostopni IP naslov, na primer, 127.0.0.1 lokalni ali zunanji IP naslov naprave.<\/p>\n<p><\/p>\n<p>Zadnja vrstica pravi, da kontejner web odvisen od kontejnerja db. Ko pokli\u010demo zagon kontejnerja web, bo docker-compose najprej zagnal na\u0161o bazo podatkov. Po zagonu baze podatkov (v resnici \u2014 po zagonu kontejnerja! Pripravljenost Baze podatkov to ne zagotavlja) bo zagnal na\u0161o aplikacijo, na\u0161 backend.<\/p>\n<p><\/p>\n<p>To prepre\u010duje napake, ko baza podatkov ni zagnana, in omogo\u010da var\u010devanje z viri, ko zaustavimo kontejner baz podatkov, s \u010dimer sprostimo vire za druge projekte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4acbcf5de89b98db055e8abc419202de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kaj nam prina\u0161a uporaba dockerizacije baze podatkov v projektu. Vsem razvijalcem zabele\u017eimo razli\u010dico MySQL. To prepre\u010duje nekatere napake, ki se lahko pojavijo pri neskladju verzij, ko se spreminja sintaksa, konfiguracija, privzete nastavitve. To omogo\u010da, da navedemo skupne hostname za bazo podatkov, login, geslo. Odmikamo se od tistega vrve\u017ea imen in konfliktov v config datotekah, ki so bili prej. <\/p>\n<p><\/p>\n<p>Imamo mo\u017enost koristiti optimiziranji config za razvojno okru\u017eenje, koji \u0107e se razlikovati od zadanog. MySQL je po defaultu postavljen na slabe ma\u0161ine i njegova performansa iz kutije je vrlo niska.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/417d77a06b18e2df9b71440c0f2a1653.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker omogu\u0107ava kori\u0161tenje interpretera Python, Ruby, NodeJS, PHP potrebne verzije. Osloba\u0111amo se potrebe kori\u0161tenja nekog upravitelja verzija. Ranije smo koristili rpm paket za Ruby koji je omogu\u0107avao promjenu verzije u zavisnosti od projekta. Tako\u0111er, omogu\u0107ava nam da zahvaljuju\u0107i Docker kontejneru glatko migriramo kod i verzioniramo ga zajedno sa zavisnostima. Ne postoji problem razumjeti verziju kako interpretera, tako i koda. Za a\u017euriranje verzije treba isklju\u010diti stari kontejner i podi\u0107i novi kontejner. Ako ne\u0161to po\u0111e po zlu, mo\u017eemo isklju\u010diti novi kontejner i podi\u0107i stari kontejner.<\/p>\n<p><\/p>\n<p>Nakon izgradnje slike, kontejneri u razvoju i produkciji bit \u0107e identi\u010dni. Ovo je posebno va\u017eno za velike instalacije.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/185a1bfe257f7e3e0eecdc6e0e0d330f.jpg\" style=\"display:block;margin: 0 auto;\" \/> Na frontend-u koristimo JavaScript i NodeJS.<\/p>\n<p><\/p>\n<p>Trenutno je na\u0161 posljednji projekt na ReactJS. Programer je pokrenuo sve kontejneri i razvijao koriste\u0107i hot-reload.<\/p>\n<p><\/p>\n<p>Zatim se pokre\u0107e zadatak za izgradnju JavaScript-a i kod, gra\u0111evinski u statiku, isporu\u010duje se putem nginx-a, \u0161tede\u0107i resurse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4c2e28319d56d7fc81845b4133a1bfe6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovdje sam prikazao shemu na\u0161eg posljednjeg projekta.<\/p>\n<p><\/p>\n<p>Koje zadatke smo rje\u0161avali? Na\u0161a potreba je bila izgraditi sustav s kojim sura\u0111uju mobilne ure\u0111aje. Oni primaju podatke. Jedna od mogu\u0107nosti je slati push obavijesti na ovaj ure\u0111aj. <\/p>\n<p><\/p>\n<p>\u0160to smo za to u\u010dinili?<\/p>\n<p><\/p>\n<p>Podijelili smo aplikaciju na takve komponente kao \u0161to su: admin dio na JS, backend koji radi putem REST su\u010delja pod Ruby on Rails. Backend sura\u0111uje s bazom podataka. Rezultat koji se generira predaje se klijentu. Admin su\u010delje s backend-om i bazom podataka sura\u0111uje preko REST su\u010delja.<\/p>\n<p><\/p>\n<p>Tako\u0111er smo imali potrebu slati push obavijesti. Prije toga smo imali projekt u kojem je realiziran mehanizam koji je odgovoran za dostavu obavijesti na mobilne platforme. <\/p>\n<p><\/p>\n<p>Razvili smo takvu shemu: operater iz preglednika sura\u0111uje s admin su\u010deljem, admin su\u010delje sura\u0111uje s backend-om, postavlja se zadatak za slanje push obavijesti.<\/p>\n<p><\/p>\n<p>Push obavijesti sura\u0111uju s drugim komponentom koji je realiziran na NodeJS-u.<\/p>\n<p><\/p>\n<p>Queues are being built, and notifications are sent according to their mechanism.<\/p>\n<p><\/p>\n<p>Here are two databases illustrated. Currently, we use 2 independent databases through Docker, which are not related to each other in any way. Apart from sharing a common virtual network, the physical data is stored in different directories on the developer's machine.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>The same thing but in numbers. Here, code reuse is important.<\/p>\n<p><\/p>\n<p>If we previously discussed code reuse in the form of libraries, in this example our service that handles Push notifications is reused as a full server. It provides an API. Our new development interacts with it.<\/p>\n<p><\/p>\n<p>At that time, we were using version 4 of NodeJS. Now (in 2017 \u2014 ed. note), in recent developments, we use version 7 of NodeJS. There are no issues in new components attracting new versions of libraries. <\/p>\n<p><\/p>\n<p>If necessary, refactoring can be done to upgrade the NodeJS version of the Push notification service. <\/p>\n<p><\/p>\n<p>If we can maintain API compatibility, it can be replaced in other projects that were used earlier.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5c58c65be078a5a1b9fc17ee2e7b4ad4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>What is needed to add Docker? We add a Dockerfile to our repository that describes the necessary dependencies. In this example, components are divided by logic. This is a minimal set for a backend developer.<\/p>\n<p><\/p>\n<p>When creating a new project, we create a Dockerfile, describing the required ecosystem (Python, Ruby, NodeJS). In the docker-compose, we describe the necessary dependency \u2014 the database. We specify that a database of a certain version is needed, storing data at specified locations.<\/p>\n<p><\/p>\n<p>We use a separate third container with nginx for serving static files. There is a provision for uploading images. The backend places them in a pre-prepared volume, which is also mounted to the container with nginx that serves the static files.<\/p>\n<p><\/p>\n<p>To store the configurations for nginx and mysql, we added a Docker folder where we keep the necessary configs. When a developer does a git clone of the repository onto their machine, they get a project already prepared for local development. There is no question about which port or what settings to apply.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e7a6b308a75cacf8ce60687a9e6081dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Next, we have several components: admin, info API, push notifications.<\/p>\n<p><\/p>\n<p>Da bi sve ovo pokrenuli, kreirali smo jo\u0161 jedan repozitorij koji smo nazvali dockerized-app. Trenutno koristimo vi\u0161e repozitorija za svaki komponent. Oni se logi\u010dki razlikuju \u2014 na GitLabu to izgleda kao mapa, dok je na razvojnim ma\u0161inama mapa specifi\u010dna za projekat. Na ni\u017eem nivou nalaze se komponente koje \u0107e se kombinovati.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f4e2c45c8ec20fca0bac74b3a3892543.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ovo je primer sadr\u017eaja dockerized-app. Tako\u0111e ovde smestimo Docker direktorijum, u kojem punimo konfiguracije potrebne za interakciju svih komponenti. Postoji README.md, u kojem je kratko opisano kako pokrenuti projekat.<\/p>\n<p><\/p>\n<p>Ovde smo primenili dva docker-compose fajla. To je u\u010dinjeno da bismo imali mogu\u0107nost postupnog pokretanja. Kada programer radi sa jezgrom, nisu mu potrebna Push obave\u0161tenja, pa jednostavno pokrene docker-compose fajl i tako se \u010duvaju resursi.<\/p>\n<p><\/p>\n<p>Ako postoji potreba za integracijom sa Push obave\u0161tenjima, pokre\u0107e se docker-compose.yaml i docker-compose-push.yaml.<\/p>\n<p><\/p>\n<p>Po\u0161to se docker-compose.yaml i docker-compose-push.yaml nalaze u istoj mapi, automatski se kreira jedinstvena virtuelna mre\u017ea.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/535019c82c72c1602176fbaf4aa5640f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Opis komponenti. Ovo je detaljnija datoteka koja je odgovorna za sastavljanje komponenti. \u0160ta je ovde zanimljivo? Ovdje uvodimo komponentu balansirnika.<\/p>\n<p><\/p>\n<p>Ovo je gotov Docker imid\u017e, u kojem se pokre\u0107e nginx i aplikacija koja slu\u0161a Docker socket. Dinami\u010dki, kako se uklju\u010duju i isklju\u010duju kontejneri, regeneri\u0161e se nginx konfiguracija. Interakcija sa komponentama se raspore\u0111uje po tre\u0107em nivou domena.<\/p>\n<p><\/p>\n<p>Za razvojno okru\u017eenje koristimo domen .dev \u2014 api.informer.dev. Aplikacije sa domenom .dev dostupne su na lokalnoj ma\u0161ini programera.<\/p>\n<p><\/p>\n<p>Zatim se prenose konfiguracije do svakog projekta i svi projekti se pokre\u0107u zajedno istovremeno.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/bc1e11e6f1fd1c837d2c8087d04145c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ako grafi\u010dki prika\u017eemo, klijent je na\u0161 pretra\u017eiva\u010d ili neki alat kojim \u0161aljemo zahteve na balansirnik.<\/p>\n<p><\/p>\n<p>Balansirnik na osnovu imena domena odre\u0111uje koji kontejner treba da se pozove.<\/p>\n<p><\/p>\n<p>To mo\u017ee biti nginx koji isporu\u010duje JS za administraciju. To mo\u017ee biti nginx koji isporu\u010duje API ili stati\u010dke datoteke koje se isporu\u010duju nginx-u u obliku slika.<\/p>\n<p><\/p>\n<p>Na dijagramu se vidi da su kontejneri povezani u virtuelnu mre\u017eu i sakriveni iza proxy-ja.<\/p>\n<p><\/p>\n<p>Na razvojnem ra\u010dunalniku lahko dostopamo do vsebnika, \u010de poznamo IP, vendar tega na\u010deloma ne uporabljamo. Nepotrebnost neposrednega dostopa se prakti\u010dno ne pojavlja.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/2908c31fd9d3c79f6189bdbeeb6d028f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kateri primer naj si ogledam, da dockeriziram svojo aplikacijo? Po mojem mnenju je dober primer uradna docker slika za MySQL.<\/p>\n<p><\/p>\n<p>To je precej kompleksno. Ima veliko razli\u010dic. A njena funkcionalnost pokriva \u0161tevilne potrebe, ki se lahko pojavijo v procesu nadaljnjega razvoja. \u010ce si vzamete \u010das in ugotovite, kako vse to deluje, mislim, da ne boste imeli te\u017eav pri samostojni implementaciji.<\/p>\n<p><\/p>\n<p>Na hub.docker.com so obi\u010dajno prisotne povezave do github.com, kjer so navedeni surovi podatki, iz katerih lahko sami sestavite sliko.<\/p>\n<p><\/p>\n<p>V tem repozitoriju je prisoten skript docker-endpoint.sh, ki je odgovoren za osnovno inicializacijo in kasnej\u0161e obdelave zagona aplikacije.<\/p>\n<p><\/p>\n<p>Ta primer vklju\u010duje tudi mo\u017enost konfiguracije s pomo\u010djo okolijskih spremenljivk. Dolo\u010ditev okoljske spremenljivke pri zagonu posameznega vsebnika ali preko docker-compose lahko pove, da potrebujemo nastaviti prazno geslo za docker za root na MySQL ali pa katero koli drugo, ki jo \u017eelimo.<\/p>\n<p><\/p>\n<p>Obstaja mo\u017enost ustvarjanja naklju\u010dnega gesla. Povedali smo, da potrebujemo uporabnika, potrebno je nastaviti geslo za uporabnika in ustvariti bazo podatkov.<\/p>\n<p><\/p>\n<p>V svojih projektih smo nekoliko unificirali Dockerfile, ki je odgovoren za inicializacijo. Tam smo prilagodili za svoje potrebe, da smo preprosto raz\u0161irili pravice uporabnika, ki ga uporablja aplikacija. To je kasneje omogo\u010dilo preprosto ustvarjanje baze podatkov iz konzole aplikacije. V Ruby aplikacijah obstaja ukaz za ustvarjanje, spreminjanje in brisanje baz podatkov.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4a9b56e21819d28dd39753134d23fee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ta primer prikazuje, kako izgleda konkretna razli\u010dica MySQL na github.com. Dockerfile si lahko ogledate in preverite, kako se namestitev izvaja.<\/p>\n<p><\/p>\n<p>docker-endpoint.sh je skript, ki je odgovoren za vstopno to\u010dko. Pri osnovni inicializaciji so potrebni nekateri pripravljalni ukrepi in vsi ti koraki so izlo\u010deni v skript za inicializacijo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4153fa46526f3d802931dd1db48b08cd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Prehajamo na drugo poglavje.<\/p>\n<p><\/p>\n<p>Za shranjevanje izvornih kodov smo pre\u0161li na gitlab. To je dovolj mo\u010dan sistem, ki ima vizualni vmesnik.<\/p>\n<p><\/p>\n<p>Eden od komponentov Gitlaba je Gitlab CI. Omogo\u010da opis zaporedja ukazov, ki se bodo kasneje uporabljali za organizacijo sistema dostave kode ali za izvajanje avtomatskega testiranja.<\/p>\n<p><\/p>\n<p>Poro\u010dilo o Gitlab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 poro\u010dilo z Ruby Russia club \u2014 dovolj podrobno in morda vas bo zanimalo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5d26d20500f34eeb9768e6c3d91bbefa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sedaj bomo pregledali, kaj je potrebno, da aktiviramo Gitlab CI. Za zagon Gitlab CI nam zadostuje, da v koren projekta damo datoteko .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p>Tukaj opisujemo, kaj \u017eelimo izvajati v zaporedju stanj tipa testiranja, name\u0161\u010danja.<\/p>\n<p><\/p>\n<p>Izvajamo skripte, ki neposredno kli\u010demo za docker-compose gradnjo na\u0161e aplikacije. To je primer za backend.<\/p>\n<p><\/p>\n<p>Nato povemo, da je potrebno izvajati migracije za spremembe v bazi podatkov in narediti teste.<\/p>\n<p><\/p>\n<p>\u010ce se skripte pravilno izvajajo in ne vrnejo kode napake, nato sistem preide v drugo fazo namestitve.<\/p>\n<p><\/p>\n<p>Faza namestitve je trenutno implementirana za staging. Nismo organizirali brezprekinjenega ponovnega zagona.<\/p>\n<p><\/p>\n<p>Prisila gasi vse kontejnerje, nato pa vse kontejnerje ponovno za\u017eenemo, zgrajene v prvi fazi testiranja.<\/p>\n<p><\/p>\n<p>Izvajamo migracije baz podatkov za trenutno spremenjeno okolje, ki so jih napisali razvijalci.<\/p>\n<p><\/p>\n<p>Obstaja opomba, da se to lahko uporabi le za vejo master.<\/p>\n<p><\/p>\n<p>Pri spremembi drugih vej se ne izvaja.<\/p>\n<p><\/p>\n<p>Obstaja mo\u017enost organizirati izdajanja po vejah.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/8a5b880bd9a0d4bab0b276568e2ba413.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da to uredimo, moramo namestiti Gitlab Runner.<\/p>\n<p><\/p>\n<p>To orodje je napisano v Golangu. Gre za en sam datoteko, kot je obi\u010dajno v svetu Golanga, ki ne zahteva nobenih odvisnosti.<\/p>\n<p><\/p>\n<p>Ob zagonu registriramo Gitlab Runner.<\/p>\n<p><\/p>\n<p>V spletni vmesnik Gitlab dobimo klju\u010d.<\/p>\n<p><\/p>\n<p>Nato pokli\u010demo ukaz za inicializacijo v ukazni vrstici.<\/p>\n<p><\/p>\n<p>Nastavimo Gitlab Runner v dialogi\u010dnem na\u010dinu (Shell, Docker, VirtualBox, SSH)<\/p>\n<p><\/p>\n<p>Koda na Gitlab Runnerju se bo izvajala ob vsakem commit-u, odvisno od nastavitve .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/37c8ac7499f0cfba2eb07a84083e44e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kako to vizualno izgleda v Gitlabu v spletnem vmesniku. Po priklopu Gitlab CI se prika\u017ee zastava, ki ka\u017ee, v kak\u0161nem stanju je gradnja trenutno.<\/p>\n<p><\/p>\n<p>Vidimo, da je bil pred 4 minutami opravljen commit, ki je opravil vse teste in ni povzro\u010dil te\u017eav.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/33ac79c45f0651a5f8bde75092c4ac44.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lahko se podrobneje osredoto\u010dimo na gradnje. Tukaj vidimo, da sta se \u017ee zgodili dve stanje. Stanje testiranja in stanje namestitve na staging.<\/p>\n<p><\/p>\n<p>\u010ce kliknemo na dolo\u010deno gradnjo, bo tam izhod ukazne vrstice, ki so bile spro\u017eene v procesu v skladu s .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d26dd28708c7fc8a409af4be4d48f502.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tako izgleda zgodovina na\u0161ega izdelka. Vidimo, da so bile uspe\u0161ne poskuse. Ko testi ne uspejo, naslednji korak ne preide in koda na staging se ne posodobi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ee7bd81dc283c7af0c194779d4230780.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Katere naloge smo re\u0161evali na staging, ko smo uvedli docker? Na\u0161 sistem je sestavljen iz komponent in imeli smo potrebo po ponovnem zagonu le nekaterih komponent, ki so bile posodobljene v repozitoriju, ne celotnega sistema.<\/p>\n<p><\/p>\n<p>Zato smo morali vse razdeliti v lo\u010dene mape.<\/p>\n<p><\/p>\n<p>Potem ko smo to storili, se je pojavila te\u017eava, da Docker-compose ustvari svoje omre\u017eje za vsako mapo in ne vidi komponent soseda.<\/p>\n<p><\/p>\n<p>Da bi to ob\u0161li, smo ro\u010dno ustvarili omre\u017eje v Dockerju. V Docker-compose smo zapisali, da za ta projekt uporabimo to omre\u017eje.<\/p>\n<p><\/p>\n<p>Tako vsak komponent, ki se za\u017eene s tem omre\u017ejem, vidi komponente v drugih delih sistema.<\/p>\n<p><\/p>\n<p>Naslednja te\u017eava je lo\u010devanje staginga med ve\u010d projekti.<\/p>\n<p><\/p>\n<p>Ker da bi vse to izgledalo lepo in \u010dim bli\u017eje produkciji, je dobro uporabiti 80 ali 443 port, ki ga pogosto uporabljamo v spletu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f863cf1833271bf132455a70ad7d2706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kako smo to re\u0161ili? Dodelili smo enega Gitlab Runnerja vsem velikim projektom.<\/p>\n<p><\/p>\n<p>Gitlab omogo\u010da zagon ve\u010d razporejenih Gitlab Runnerjev, ki preprosto zaporedno v naklju\u010dnem vrstnem redu prevzemajo vse naloge in jih izvajajo.<\/p>\n<p><\/p>\n<p>Da bi prepre\u010dili zmedo, smo omejili skupino na\u0161ih projektov na enega Gitlab Runnerja, ki se pri na\u0161ih obsegih spopada brez te\u017eav.<\/p>\n<p><\/p>\n<p>Nginx-proxy smo prenesli v lo\u010den zagon skripti in v njem zapisali omre\u017eja vseh projektov. <\/p>\n<p><\/p>\n<p>Na\u0161 projekt ima eno omre\u017eje, uravnote\u017eevalnik pa ima ve\u010d omre\u017eij po imenih projektov. Lahko posreduje naprej po domenah.<\/p>\n<p><\/p>\n<p>Na\u0161i zahtevki prihajajo po domeni na 80 port in se usmerjajo v skupino kontejnerjev, ki upravljajo to domeno.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25c769f029b272a17fd06bbe60cf0ea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Katere druge te\u017eave so bile? To je to, da privzeto vsi kontejnerji delujejo pod uporabnikom root. Ta root ni enak rootu gostiteljske sistema.<\/p>\n<p><\/p>\n<p>\u010ce pa vstopite v zabojnik, bo to root in datoteka, ki jo ustvarimo v tem zabojniku, dobi pravice root.<\/p>\n<p><\/p>\n<p>\u010ce je razvijalec vstopil v zabojnik in tam izvedel dolo\u010dene ukaze, ki ustvarijo datoteke, nato pa izstopil iz zabojnika, ima v svoji delovni mapi datoteko, do katere nima dostopa.<\/p>\n<p><\/p>\n<p>Kako to re\u0161iti? Lahko dodamo uporabnike, ki bodo v zabojniku.<\/p>\n<p><\/p>\n<p>Kak\u0161ne te\u017eave so se pojavile, ko smo dodali uporabnika?<\/p>\n<p><\/p>\n<p>Pri ustvarjanju uporabnika se pogosto ne ujemata ID skupine (UID) in ID uporabnika (GID).<\/p>\n<p><\/p>\n<p>Za re\u0161itev tega problema v zabojniku uporabljamo uporabnike z ID 1000.<\/p>\n<p><\/p>\n<p>V na\u0161em primeru se je to ujemalo s tem, da prakti\u010dno vsi razvijalci uporabljajo operacijski sistem Ubuntu. Prvi uporabnik v operacijskem sistemu Ubuntu ima ID 1000.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d4911374e4953fdcd807c387efeafec3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kak\u0161ni so na\u0161i na\u010drti?<\/p>\n<p><\/p>\n<p>Ponovno prebrati dokumentacijo o Dockerju. Projekt se aktivno razvija, dokumentacija se spreminja. Podatki, ki so bili pridobljeni pred dvema do tremi meseci, se \u017ee po\u010dasi zastarajo. <\/p>\n<p><\/p>\n<p>Nekatere te\u017eave, ki smo jih re\u0161ili, so morda \u017ee re\u0161ene s standardnimi sredstvi.<\/p>\n<p><\/p>\n<p>Tako bi rad \u0161el naprej in se neposredno lotil orkestracije.<\/p>\n<p><\/p>\n<p>En od primerov je vgrajen mehanizem v Dockerju, imenovan Docker Swarm, ki je na voljo kar iz \u0161katle. Rad bi zagnal kaj v produkciji na temelju tehnologije Docker Swarm.<\/p>\n<p><\/p>\n<p>Ustvarjanje zabojnikov ote\u017euje delo s paketi. Trenutno so paketi izolirani. So razpr\u0161eni po zabojnikih. Ena od nalog je olaj\u0161ati dostop do paketov prek spletnega vmesnika.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Postopek razvoja in testiranja z Docker in Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/cff8c72dd8af7de1fa0227601bd1d69c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449742\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &#171;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&#187; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32526","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Postopek razvoja in testiranja z Dockerjem in Gitlab CI | ProHoster","description":"Predlagam, da se seznanite z razlago poro\u010dila Aleksandra Sigacheva iz Inventosa \"Postopek razvoja in testiranja z Dockerjem + Gitlab CI\". Tisti, ki \u0161ele za\u010denjajo uvajati postopek razvoja.","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.","og:url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:47:32+00:00","article:modified_time":"2019-10-31T18:47:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32526","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 11:18:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:57:22","updated":"2026-01-21 11:18:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/32526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=32526"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/32526\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media\/24326"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=32526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=32526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=32526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}