{"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\/ro\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","title":{"rendered":"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>V\u0103 propun s\u0103 consulta\u021bi transcrierea raportului lui Aleksandr Sigacev de la Inventos \u201eProcesul de dezvoltare \u0219i testare cu Docker + Gitlab CI\u201d<\/strong><\/p>\n<p><\/p>\n<p>Cei care \u00eencep s\u0103 implementeze procesul de dezvoltare \u0219i testare bazat pe Docker + Gitlab CI adesea pun \u00eentreb\u0103ri de baz\u0103. Cu ce s\u0103 \u00eencep? Cum s\u0103 organiz\u0103m? Cum s\u0103 test\u0103m?<\/p>\n<p><\/p>\n<p>Acest raport este valoros deoarece explic\u0103 structurat procesul de dezvoltare \u0219i testare folosind Docker \u0219i Gitlab CI. Raportul este din 2017. Cred c\u0103 din acest raport se pot extrage fundamentele, metodologia, ideea, experien\u021ba utiliz\u0103rii. <\/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=\"Reda\u021bi 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>Cine este interesat, v\u0103 rog s\u0103 citi\u021bi mai departe. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Numele meu este Alexander Sigachev. Lucrez la compania Inventos. Voi \u00eemp\u0103rt\u0103\u0219i experien\u021ba mea cu Docker \u0219i modul \u00een care \u00eel implement\u0103m treptat \u00een proiectele companiei.<\/p>\n<p><\/p>\n<p>Tema raportului: Procesul de dezvoltare cu utilizarea Docker \u0219i Gitlab CI. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e30c4757e4bda1bcc3e20b16e8e2709e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acesta este al doilea meu raport despre Docker. La momentul primului raport, foloseam Docker doar \u00een dezvoltare pe ma\u0219inile dezvoltatorilor. Num\u0103rul angaja\u021bilor care foloseau Docker era de aproximativ 2-3 persoane. Treptat, am acumulat experien\u021b\u0103 \u0219i am avansat pu\u021bin mai departe. Linkul c\u0103tre raportul nostru <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">primul raport<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Ce va con\u021bine acest raport? Vom \u00eemp\u0103rt\u0103\u0219i experien\u021ba noastr\u0103 despre obstacolele \u00eent\u00e2mpinate, ce probleme am rezolvat \u0219i cum. Nu a fost \u00eentotdeauna u\u0219or, dar ne-a permis s\u0103 avans\u0103m.<\/p>\n<p><\/p>\n<p>Deviza noastr\u0103: dockerizeaz\u0103 tot ce poate ajunge \u00een m\u00e2inile noastre.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25ae4f97f1c502384abfe697bac502b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce probleme rezolv\u0103m?<\/p>\n<p><\/p>\n<p>C\u00e2nd \u00een companie sunt mai multe echipe, programatorul devine o resurs\u0103 comun\u0103. Exist\u0103 etape \u00een care programatorii sunt deturna\u021bi dintr-un proiect \u0219i aloca\u021bi pe o vreme \u00een alt proiect.<\/p>\n<p><\/p>\n<p>Pentru ca programatorul s\u0103 se integreze rapid, este necesar s\u0103 descarce codul surs\u0103 al proiectului \u0219i s\u0103 porneasc\u0103 mediul c\u00e2t mai repede, ceea ce \u00eei va permite s\u0103 continue s\u0103 rezolve sarcinile acestui proiect.<\/p>\n<p><\/p>\n<p>De obicei, dac\u0103 \u00eencepi de la zero, exist\u0103 pu\u021bin\u0103 documenta\u021bie \u00een proiect. Informa\u021biile despre cum s\u0103 configurezi, sunt doar la cei experimenta\u021bi. Angaja\u021bii \u00ee\u0219i configureaz\u0103 locul de munc\u0103 de obicei \u00een una sau dou\u0103 zile. Pentru a accelera acest proces, am aplicat Docker.<\/p>\n<p><\/p>\n<p>Urm\u0103toarea problem\u0103 este standardizarea set\u0103rilor \u00een Development. Din experien\u021ba mea, dezvoltatorii manifest\u0103 \u00eentotdeauna ini\u021biativ\u0103. \u00cen fiecare a cincea situa\u021bie, se introduce un domeniu personalizat, de exemplu vasya.dev. \u00cen apropiere se afl\u0103 vecinul Petya, care are domeniul petya.dev. Ei dezvolt\u0103 un site sau un component al sistemului folosind acest nume de domeniu.<\/p>\n<p><\/p>\n<p>C\u00e2nd sistemul cre\u0219te \u0219i aceste nume de domeniu \u00eencep s\u0103 apar\u0103 \u00een configura\u021bii, apare un conflict al mediilor de Development \u0219i se rescrie calea site-ului.<\/p>\n<p><\/p>\n<p>Acela\u0219i lucru se \u00eent\u00e2mpl\u0103 \u0219i cu set\u0103rile bazei de date. Cineva nu se \u00eengrijoreaz\u0103 de securitate \u0219i lucreaz\u0103 cu parola root goal\u0103. La cineva, \u00een timpul instal\u0103rii, MySQL a cerut o parol\u0103 \u0219i aceasta a fost 123. Se \u00eent\u00e2mpl\u0103 adesea ca configurarea bazei de date s\u0103 fie constant modificat\u0103 \u00een func\u021bie de commit-ul dezvoltatorului. Cineva a corectat, cineva nu a corectat configura\u021bia. Au fost metode ingenioase c\u00e2nd am mutat o configura\u021bie de test \u00een <code>.gitignore<\/code> \u0219i fiecare dezvoltator trebuia s\u0103 instaleze baza de date. Aceasta complica procesul de \u00eenceput. Pe l\u00e2ng\u0103 toate acestea, trebuie s\u0103 ne amintim \u0219i de baza de date. Baza de date trebuie ini\u021bializat\u0103, trebuie s\u0103 specific\u0103m parola, trebuie s\u0103 specific\u0103m utilizatorul, s\u0103 cre\u0103m tabela \u0219i a\u0219a mai departe.<\/p>\n<p><\/p>\n<p>\u00cenc\u0103 una dintre probleme este versiunile diferite ale bibliotecilor. Adesea, dezvoltatorul lucreaz\u0103 cu proiecte diferite. Exist\u0103 un proiect Legacy, care a \u00eenceput acum cinci ani (din 2017 \u2013 nota editorului). La \u00eenceput, a fost \u00eenceput cu MySQL 5.5. Exist\u0103 \u0219i proiecte moderne, unde \u00eencerc\u0103m s\u0103 implement\u0103m deja versiuni mai moderne de MySQL, de exemplu 5.7 sau mai mari (\u00een 2017 \u2013 nota editorului)<\/p>\n<p><\/p>\n<p>Cine lucreaz\u0103 cu MySQL \u0219tie c\u0103 aceste biblioteci aduc cu ele dependen\u021be. Este destul de problematic s\u0103 rula\u021bi dou\u0103 baze \u00eempreun\u0103. Cel pu\u021bin, conectarea clien\u021bilor vechi la o nou\u0103 baz\u0103 de date este problematic\u0103. Acest lucru genereaz\u0103, la r\u00e2ndul s\u0103u, mai multe probleme.<\/p>\n<p><\/p>\n<p>Urm\u0103toarea problem\u0103 este atunci c\u00e2nd dezvoltatorul lucreaz\u0103 pe o ma\u0219in\u0103 local\u0103, utiliz\u00e2nd resurse locale, fi\u0219iere locale, memorie RAM local\u0103. Toate interac\u021biunile \u00een timpul dezvolt\u0103rii solu\u021biilor sunt realizate \u00een contextul \u00een care func\u021bioneaz\u0103 pe o singur\u0103 ma\u0219in\u0103. Un exemplu ar fi atunci c\u00e2nd avem 3 servere backend \u00een produc\u021bie, iar dezvoltatorul salveaz\u0103 fi\u0219iere \u00een directorul r\u0103d\u0103cin\u0103, de unde nginx \u00ee\u0219i ia fi\u0219ierele pentru a r\u0103spunde la cereri. C\u00e2nd acest cod ajunge \u00een produc\u021bie, se constat\u0103 c\u0103 fi\u0219ierul este prezent pe unul dintre cele 3 servere.<\/p>\n<p><\/p>\n<p>Acum se dezvolt\u0103 direc\u021bia microserviciilor. C\u00e2nd \u00eemp\u0103r\u021bim aplica\u021biile noastre mari \u00een componente mici, care interac\u021bioneaz\u0103 \u00eentre ele. Aceasta permite alegerea tehnologiilor specifice pentru stiva de sarcini. De asemenea, permite \u00eemp\u0103r\u021birea muncii \u0219i a responsabilit\u0103\u021bilor \u00eentre dezvoltatori.<\/p>\n<p><\/p>\n<p>Dezvoltatorul frontend, dezvolt\u00e2nd pe JS, nu influen\u021beaz\u0103 aproape deloc backend-ul. Dezvoltatorul backend, \u00een cazul nostru, dezvolt\u0103 Ruby on Rails \u0219i nu interfereaz\u0103 cu frontend-ul. Interac\u021biunea se realizeaz\u0103 prin intermediul API-ului.<\/p>\n<p><\/p>\n<p>Ca bonus, cu ajutorul Docker am reu\u0219it s\u0103 utiliz\u0103m resursele pe Staging. Fiecare proiect, datorit\u0103 specificului s\u0103u, necesita anumite set\u0103ri. Fizic, era necesar s\u0103 aloc\u0103m fie un server virtual pentru fiecare \u0219i s\u0103 le configur\u0103m separat, fie s\u0103 \u00eemp\u0103r\u021bim un mediu variabil, iar proiectele puteau influen\u021ba unul pe altul \u00een func\u021bie de versiunile bibliotecilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/fa5c99f90faef84a356d4791fd915830.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Instrumente. Ce folosim? <\/p>\n<p><\/p>\n<ul>\n<li>Direct Docker. \u00cen Dockerfile sunt descrise dependen\u021bele unei aplica\u021bii. <\/li>\n<li>Docker-compose este leg\u0103tura care reune\u0219te c\u00e2teva dintre aplica\u021biile noastre Docker.<\/li>\n<li>Folosim GitLab pentru stocarea codului surs\u0103.<\/li>\n<li>Folosim GitLab-CI pentru integrarea sistemic\u0103.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/b6041827a6ba928e0d33add6b79c581c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Prezentarea const\u0103 \u00een dou\u0103 p\u0103r\u021bi.<\/p>\n<p><\/p>\n<p>Prima parte va vorbi despre cum am pornit Docker pe ma\u0219inile dezvoltatorilor.<\/p>\n<p><\/p>\n<p>Partea a doua va discuta despre cum interac\u021bion\u0103m cu GitLab, cum rul\u0103m testele \u0219i cum facem implementarea pe Staging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/45746d3323d35e0d18f066c8bfcb2214.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker este o tehnologie care permite (folosind o abordare declarativ\u0103) descrierea componentelor necesare. Acesta este un exemplu de Dockerfile. Aici declar\u0103m c\u0103 ne deriv\u0103m din imaginea oficial\u0103 Docker Ruby:2.3.0. Aceasta con\u021bine Ruby versiunea 2.3. Instal\u0103m bibliotecile necesare pentru compilare \u0219i NodeJS. Declar\u0103m c\u0103 cre\u0103m un director. <code>\/app<\/code>Stabilim directorul app ca director de lucru. \u00cen acest director plas\u0103m Gemfile \u0219i Gemfile.lock necesare. Apoi, execut\u0103m construc\u021bia proiectelor care instaleaz\u0103 aceast\u0103 imagine a dependen\u021belor. Indic\u0103 c\u0103 containerul va fi preg\u0103tit s\u0103 asculte pe portul extern 3000. Ultima comand\u0103 este cea care porne\u0219te efectiv aplica\u021bia noastr\u0103. Dac\u0103 execut\u0103m comanda de lansare a proiectului, aplica\u021bia va \u00eencerca s\u0103 se execute \u0219i va porni comanda specificat\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ba503c305ae90f49b39f4ae2cbda1668.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acesta este un exemplu minim al unui fi\u0219ier docker-compose. \u00cen acest caz, ar\u0103t\u0103m cum se realizeaz\u0103 conexiunea \u00eentre dou\u0103 containere. Acesta este serviciul de baz\u0103 de date \u0219i serviciul web. Aplica\u021biile noastre web necesit\u0103, \u00een cele mai multe cazuri, un backend pentru stocarea datelor, adic\u0103 o baz\u0103 de date. Deoarece utiliz\u0103m MySQL, exemplul este cu MySQL - dar nimic nu ne \u00eempiedic\u0103 s\u0103 folosim o alt\u0103 baz\u0103 de date (PostgreSQL, Redis).<\/p>\n<p><\/p>\n<p>Lu\u0103m de la sursa oficial\u0103 de pe Docker Hub imaginea MySQL 5.7.14 f\u0103r\u0103 modific\u0103ri. Imaginea care r\u0103spunde de aplica\u021bia noastr\u0103 web o construim din directorul curent. La prima execu\u021bie, construie\u0219te imaginea pentru noi. Apoi, porne\u0219te comanda pe care o execut\u0103m aici. Dac\u0103 ne \u00eentoarcem, vom vedea c\u0103 a fost definit\u0103 o comand\u0103 de lansare prin Puma. Puma este un serviciu scris \u00een Ruby. \u00cen al doilea caz, o redefinim. Aceast\u0103 comand\u0103 poate fi orice, \u00een func\u021bie de nevoile sau sarcinile noastre.<\/p>\n<p><\/p>\n<p>De asemenea, descriem c\u0103 trebuie s\u0103 redirec\u021bion\u0103m portul de pe ma\u0219ina gazd\u0103 a dezvoltatorului de la 3000 la portul 3000 al containerului. Aceasta se realizeaz\u0103 automat cu ajutorul iptables \u0219i al mecanismului s\u0103u, care este integrat direct \u00een Docker. <\/p>\n<p><\/p>\n<p>Dezvoltatorul poate, de asemenea, ca \u0219i \u00eenainte, s\u0103 se conecteze la orice adres\u0103 IP disponibil\u0103, de exemplu, 127.0.0.1 (local) sau adresa IP extern\u0103 a ma\u0219inii.<\/p>\n<p><\/p>\n<p>Ultima linie spune c\u0103 containerul web depinde de containerul db. C\u00e2nd apel\u0103m lansarea containerului web, docker-compose va porni mai \u00eent\u00e2i baza de date. La lansarea bazei de date (de fapt - dup\u0103 startul containerului! Nu garanteaz\u0103 disponibilitatea Bazei de Date), ne va porni aplica\u021bia, backend-ul nostru.<\/p>\n<p><\/p>\n<p>Acest lucru permite evitarea erorilor atunci c\u00e2nd baza de date nu este activat\u0103 \u0219i ajut\u0103 la economisirea resurselor atunci c\u00e2nd oprim containerul bazei de date, eliber\u00e2nd resursele pentru alte proiecte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4acbcf5de89b98db055e8abc419202de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce ne ofer\u0103 utilizarea containeriz\u0103rii bazei de date \u00een proiect? La to\u021bi dezvoltatorii fix\u0103m versiunea MySQL. Aceasta permite evitarea unor erori care pot ap\u0103rea din cauza discrepan\u021belor \u00eentre versiuni, c\u00e2nd se schimb\u0103 sintaxa, configura\u021bia sau set\u0103rile implicite. Permite specificarea unor hostname-uri comune pentru baza de date, login, parol\u0103. Ne \u00eendep\u0103rt\u0103m de haosul numelui \u0219i conflictele din fi\u0219ierele de configurare anterioare. <\/p>\n<p><\/p>\n<p>Avem posibilitatea de a folosi un config mai optim pentru mediu de dezvoltare, care va diferi de cel implicit. MySQL este configurat din oficiu pentru ma\u0219ini slabe, iar performan\u021ba sa din cutie este foarte sc\u0103zut\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/417d77a06b18e2df9b71440c0f2a1653.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker permite utilizarea interpretatoarelor Python, Ruby, NodeJS, PHP de versiune necesar\u0103. Ne eliber\u0103m de necesitatea unui manager de versiuni. \u00cen trecut, pentru Ruby foloseam un pachet rpm care ne permitea s\u0103 schimb\u0103m versiunea \u00een func\u021bie de proiect. De asemenea, aceasta permite, datorit\u0103 containerului Docker, s\u0103 migr\u0103m codul \u0219i s\u0103-l versiunez \u00eempreun\u0103 cu dependen\u021bele sale. Nu avem probleme \u00een a identifica versiunea at\u00e2t a interpretatorului, c\u00e2t \u0219i a codului. Pentru a actualiza versiunea, trebuie s\u0103 reducem containerul vechi \u0219i s\u0103 ridic\u0103m un nou container. Dac\u0103 ceva nu merge bine, putem reduce noul container \u0219i s\u0103 ridic\u0103m containerul vechi.<\/p>\n<p><\/p>\n<p>Dup\u0103 construirea imaginii, containerele at\u00e2t \u00een mediu de dezvoltare, c\u00e2t \u0219i \u00een produc\u021bie vor fi identice. Acest lucru este deosebit de relevant pentru instal\u0103rile mari.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/185a1bfe257f7e3e0eecdc6e0e0d330f.jpg\" style=\"display:block;margin: 0 auto;\" \/> Pe frontend folosim JavaScript \u0219i NodeJS.<\/p>\n<p><\/p>\n<p>Acum, ultimul nostru proiect este pe ReactJS. Dezvoltatorul a lansat toate containerele \u0219i a dezvoltat folosind hot-reload.<\/p>\n<p><\/p>\n<p>Apoi se lanseaz\u0103 o sarcin\u0103 de construire JavaScript, iar codul compilat \u00een statics este livrat prin nginx, economisind resurse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4c2e28319d56d7fc81845b4133a1bfe6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aici am prezentat schema ultimului nostru proiect.<\/p>\n<p><\/p>\n<p>Ce probleme am rezolvat? A existat necesitatea de a construi un sistem care interac\u021bioneaz\u0103 cu dispozitive mobile. Acestea primesc date. Una dintre posibilit\u0103\u021bile este de a trimite notific\u0103ri push c\u0103tre acest dispozitiv. <\/p>\n<p><\/p>\n<p>Ce am f\u0103cut pentru asta?<\/p>\n<p><\/p>\n<p>Am \u00eemp\u0103r\u021bit aplica\u021bia \u00een urm\u0103toarele componente: partea de admin pe JS, backend-ul care func\u021bioneaz\u0103 printr-un API REST sub Ruby on Rails. Backend-ul interac\u021bioneaz\u0103 cu baza de date. Rezultatul generat este livrat clientului. Admin panel-ul interac\u021bioneaz\u0103 cu backend-ul \u0219i baza de date prin intermediul API-ului REST.<\/p>\n<p><\/p>\n<p>De asemenea, am avut nevoie s\u0103 trimitem notific\u0103ri Push. P\u00e2n\u0103 acum, am avut un proiect \u00een care a fost implementat un mecanism care se ocup\u0103 de livrarea notific\u0103rilor pe platformele mobile. <\/p>\n<p><\/p>\n<p>Am dezvoltat un astfel de sistem: operatorul din browser interac\u021bioneaz\u0103 cu panoul de administrare, iar panoul de administrare interac\u021bioneaz\u0103 cu backend-ul, stabilind sarcina de a trimite notific\u0103rile Push.<\/p>\n<p><\/p>\n<p>Notific\u0103rile Push interac\u021bioneaz\u0103 cu un alt component, care este implementat pe NodeJS.<\/p>\n<p><\/p>\n<p>Se construiesc cozi \u0219i apoi se continu\u0103 cu mecanismul propriu de trimitere a notific\u0103rilor.<\/p>\n<p><\/p>\n<p>Aici sunt reprezentate dou\u0103 baze de date. \u00cen prezent, folosim 2 baze de date independente, care nu sunt legate \u00eentre ele, cu ajutorul Docker. Singura lor conexiune este re\u021beaua virtual\u0103 comun\u0103, iar datele fizice sunt stocate \u00een directoare diferite pe ma\u0219ina dezvoltatorului.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acela\u0219i lucru, dar \u00een cifre. Aici este important\u0103 reutilizarea codului.<\/p>\n<p><\/p>\n<p>Dac\u0103 anterior discutam despre reutilizarea codului sub form\u0103 de biblioteci, \u00een acest exemplu, serviciul nostru care se ocup\u0103 de notific\u0103rile Push este reutilizat ca un server complet. Ofer\u0103 un API, iar noua noastr\u0103 dezvoltare interac\u021bioneaz\u0103 cu acesta.<\/p>\n<p><\/p>\n<p>Pe atunci, foloseam versiunea 4 de NodeJS. Acum (\u00een 2017 \u2014 n. red.) \u00een dezvolt\u0103rile recente, folosim versiunea 7 de NodeJS. Nu avem probleme \u00een a aduce noi versiuni de biblioteci \u00een noile componente. <\/p>\n<p><\/p>\n<p>Dac\u0103 este necesar, se poate realiza un refactoring \u0219i actualizar\u0103 versiunea NodeJS a serviciului de notific\u0103ri Push. <\/p>\n<p><\/p>\n<p>Dac\u0103 putem men\u021bine compatibilitatea API-ului, atunci este posibil s\u0103 \u00eel \u00eenlocuim \u00een alte proiecte care au fost utilizate anterior.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5c58c65be078a5a1b9fc17ee2e7b4ad4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce este necesar pentru a ad\u0103uga Docker? Ad\u0103ug\u0103m \u00een depozitul nostru un Dockerfile, care descrie dependen\u021bele necesare. \u00cen acest exemplu, componentele sunt \u00eemp\u0103r\u021bite logic. Acesta este minimul necesar pentru un dezvoltator backend.<\/p>\n<p><\/p>\n<p>C\u00e2nd cre\u0103m un nou proiect, cre\u0103m un Dockerfile, descriem ecosistemul necesar (Python, Ruby, NodeJS). \u00cen docker-compose descriem dependen\u021ba necesar\u0103 \u2014 baza de date. Specific\u0103m c\u0103 este nevoie de o baz\u0103 de date de o anumit\u0103 versiune, pentru a stoca datele \u00eentr-un anumit loc.<\/p>\n<p><\/p>\n<p>Folosim un container separat cu nginx pentru livrarea fi\u0219ierelor statice. Este prev\u0103zut\u0103 posibilitatea de a \u00eenc\u0103rca imagini. Backend-ul le plaseaz\u0103 \u00eentr-un volum preg\u0103tit \u00een prealabil, care este montat \u0219i \u00een containerul cu nginx, care serve\u0219te fi\u0219ierele statice.<\/p>\n<p><\/p>\n<p>Pentru a stoca configura\u021bia nginx, mysql, am ad\u0103ugat un folder Docker \u00een care p\u0103str\u0103m configura\u021biile necesare. C\u00e2nd dezvoltatorul face git clone al repository-ului pe ma\u0219ina sa, ob\u021bine un proiect deja preg\u0103tit pentru dezvoltarea local\u0103. Nu exist\u0103 \u00eentreb\u0103ri despre ce port sau ce set\u0103ri trebuie aplicate.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e7a6b308a75cacf8ce60687a9e6081dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Apoi avem c\u00e2teva componente: admin, inform-API, notific\u0103ri push.<\/p>\n<p><\/p>\n<p>Pentru a lansa tot acest lucru, am creat un alt repository numit dockerized-app. \u00cen prezent, folosim mai multe repository-uri pentru fiecare component\u0103. Acestea sunt doar diferite logic - \u00een GitLab arat\u0103 ca un folder, iar pe ma\u0219ina dezvoltatorului, un folder pentru proiectul specific. La un nivel inferior se afl\u0103 componentele care vor fi unite.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f4e2c45c8ec20fca0bac74b3a3892543.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acesta este un exemplu exact al con\u021binutului dockerized-app. De asemenea, scoatem aici catalogul Docker, \u00een care umplem configura\u021biile necesare pentru interac\u021biunile tuturor componentelor. Exist\u0103 README.md, \u00een care este descris succint cum se lanseaz\u0103 proiectul.<\/p>\n<p><\/p>\n<p>Aici am aplicat dou\u0103 fi\u0219iere docker-compose. Acest lucru a fost realizat pentru a putea lansa aplica\u021biile \u00een etape. C\u00e2nd dezvoltatorul lucreaz\u0103 cu nucleul, nu are nevoie de notific\u0103ri push, a\u0219a c\u0103 porne\u0219te pur \u0219i simplu fi\u0219ierul docker-compose \u0219i, \u00een consecin\u021b\u0103, resursele sunt economisite.<\/p>\n<p><\/p>\n<p>Dac\u0103 este necesar\u0103 integrarea cu notific\u0103rile push, atunci se lanseaz\u0103 docker-compose.yaml \u0219i docker-compose-push.yaml.<\/p>\n<p><\/p>\n<p>Deoarece docker-compose.yaml \u0219i docker-compose-push.yaml se afl\u0103 \u00een folder, se creeaz\u0103 automat o re\u021bea virtual\u0103 unificat\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/535019c82c72c1602176fbaf4aa5640f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Descrierea componentelor. Acesta este un fi\u0219ier mai extins, care este responsabil pentru compilarea componentelor. Ce este notabil aici? Introducem componenta load balancer.<\/p>\n<p><\/p>\n<p>Acesta este un container Docker gata, \u00een care ruleaz\u0103 nginx \u0219i aplica\u021bia care ascult\u0103 socket-ul Docker. Configura\u021bia nginx este regenerat\u0103 dinamic, pe m\u0103sur\u0103 ce containerele sunt pornite \u0219i oprite. Interac\u021biunile cu componentele sunt dispersate prin numele de domeniu de nivel trei.<\/p>\n<p><\/p>\n<p>Pentru mediul de dezvoltare, folosim domeniul .dev \u2014 api.informer.dev. Aplica\u021biile cu domeniul .dev sunt disponibile pe ma\u0219ina local\u0103 a dezvoltatorului.<\/p>\n<p><\/p>\n<p>Apoi, configura\u021biile sunt transferate pentru fiecare proiect \u0219i toate proiectele sunt lansate simultan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/bc1e11e6f1fd1c837d2c8087d04145c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dac\u0103 ar fi s\u0103 reprezent\u0103m grafic, clientul ar fi browserul nostru sau un instrument cu care facem cereri c\u0103tre load balancer.<\/p>\n<p><\/p>\n<p>Load balancer-ul determin\u0103, prin numele de domeniu, la care container trebuie s\u0103 se adreseze.<\/p>\n<p><\/p>\n<p>Acesta poate fi nginx care ofer\u0103 JS pentru interfa\u021ba de administrare. Poate fi nginx care ofer\u0103 API-ul sau fi\u0219iere statice care sunt livrate de nginx sub form\u0103 de \u00eenc\u0103rcare a imaginilor.<\/p>\n<p><\/p>\n<p>\u00cen diagram\u0103 se vede c\u0103 containerele sunt unite \u00eentr-o re\u021bea virtual\u0103 \u0219i ascunse \u00een spatele unui proxy.<\/p>\n<p><\/p>\n<p>Pe ma\u0219ina dezvoltatorului, se poate accesa containerul \u0219tiind IP-ul, dar practic nu aplic\u0103m asta. Necesitatea de a accesa direct este aproape inexistent\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/2908c31fd9d3c79f6189bdbeeb6d028f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce exemplu s\u0103 consult pentru a dockeriza aplica\u021bia mea? P\u0103rerea mea este c\u0103 un exemplu bun este imaginea oficial\u0103 docker pentru MySQL.<\/p>\n<p><\/p>\n<p>Este destul de complex. Exist\u0103 multe versiuni. Dar func\u021bionalitatea sa permite acoperirea multor nevoi care pot ap\u0103rea \u00een timpul dezvolt\u0103rii ulterioare. Dac\u0103 \u00ee\u021bi vei petrece timpul \u0219i vei \u00een\u021belege cum interac\u021bioneaz\u0103 toate acestea, cred c\u0103 nu vei avea probleme \u00een implementarea independent\u0103.<\/p>\n<p><\/p>\n<p>Pe hub.docker.com exist\u0103 de obicei linkuri c\u0103tre github.com, unde sunt prezentate datele brute, din care po\u021bi crea tu \u00eensu\u021bi imaginea.<\/p>\n<p><\/p>\n<p>Mai departe, \u00een acest depozit se afl\u0103 scriptul docker-endpoint.sh, care r\u0103spunde de ini\u021bializarea ini\u021bial\u0103 \u0219i de procesarea ulterioar\u0103 a lans\u0103rii aplica\u021biei.<\/p>\n<p><\/p>\n<p>De asemenea, \u00een acest exemplu exist\u0103 posibilitatea de configurare folosind variabile de mediu. Definind variabilele de mediu la lansarea unui singur container sau prin docker-compose, putem specifica c\u0103 trebuie s\u0103 set\u0103m o parol\u0103 goal\u0103 pentru docker pentru root pe MySQL sau una pe care o dorim.<\/p>\n<p><\/p>\n<p>Exist\u0103 op\u021biunea de a crea o parol\u0103 randomizat\u0103. Spunem c\u0103 avem nevoie de un utilizator, este necesar s\u0103 set\u0103m o parol\u0103 pentru utilizator \u0219i trebuie s\u0103 cre\u0103m o baz\u0103 de date.<\/p>\n<p><\/p>\n<p>\u00cen proiectele noastre, am unificat pu\u021bin Dockerfile-ul, care r\u0103spunde de ini\u021bializare. L-am modificat pentru nevoile noastre pentru a extinde pur \u0219i simplu drepturile utilizatorului pe care \u00eel folose\u0219te aplica\u021bia. Acest lucru a permis ulterior crearea simpl\u0103 a unei baze de date din consola aplica\u021biei. \u00cen aplica\u021biile Ruby exist\u0103 comenzi pentru a crea, modifica \u0219i \u0219terge baze de date.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4a9b56e21819d28dd39753134d23fee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acesta este un exemplu despre cum arat\u0103 o versiune specific\u0103 de MySQL pe github.com. Dockerfile-ul poate fi deschis \u0219i po\u021bi vedea cum se desf\u0103\u0219oar\u0103 instalarea.<\/p>\n<p><\/p>\n<p>docker-endpoint.sh este un script care r\u0103spunde pentru punctul de intrare. La ini\u021bializarea ini\u021bial\u0103, sunt necesare anumite ac\u021biuni de preg\u0103tire, iar toate aceste ac\u021biuni sunt incluse \u00een scriptul de ini\u021bializare.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4153fa46526f3d802931dd1db48b08cd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Trecem la a doua parte.<\/p>\n<p><\/p>\n<p>Pentru stocarea codului surs\u0103, am trecut la GitLab. Este un sistem destul de puternic, care are o interfa\u021b\u0103 vizual\u0103.<\/p>\n<p><\/p>\n<p>Unul dintre componentele GitLab este GitLab CI. Acesta permite descrierea unei secven\u021be de comenzi, care vor fi folosite ulterior pentru a organiza livrarea codului sau pentru a rula teste automate.<\/p>\n<p><\/p>\n<p>Prezentare despre GitLab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 o prezentare de la Ruby Russia club \u2014 destul de detaliat\u0103 \u0219i poate c\u0103 va fi de interes pentru tine.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5d26d20500f34eeb9768e6c3d91bbefa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acum vom discuta despre ce este necesar pentru a activa GitLab CI. Pentru a porni GitLab CI, trebuie doar s\u0103 plas\u0103m fi\u0219ierul .gitlab-ci.yml \u00een r\u0103d\u0103cina proiectului.<\/p>\n<p><\/p>\n<p>Aici descriem ce dorim s\u0103 execut\u0103m ca o secven\u021b\u0103 de st\u0103ri de tip testare, livrare.<\/p>\n<p><\/p>\n<p>Execut\u0103m scripturile, care apelaz\u0103 direct compilarea aplica\u021biei noastre cu docker-compose. Acesta este un exemplu de backend.<\/p>\n<p><\/p>\n<p>Apoi, men\u021bion\u0103m c\u0103 trebuie s\u0103 rul\u0103m migra\u021biile pentru modificarea bazei de date \u0219i s\u0103 execut\u0103m testele.<\/p>\n<p><\/p>\n<p>Dac\u0103 scripturile sunt executate corect \u0219i nu returneaz\u0103 un cod de eroare, atunci sistemul trece la a doua etap\u0103 a livr\u0103rii.<\/p>\n<p><\/p>\n<p>Etapa de livrare este \u00een prezent implementat\u0103 pentru staging. Nu am organizat o repornire f\u0103r\u0103 \u00eentrerupere.<\/p>\n<p><\/p>\n<p>For\u021b\u0103m oprirea tuturor containerelor \u0219i apoi ridic\u0103m din nou toate containerele, construite \u00een prima etap\u0103 \u00een timpul test\u0103rii.<\/p>\n<p><\/p>\n<p>Rul\u0103m migra\u021biile bazei de date pentru mediu variabil actual, care au fost scrise de dezvoltatori.<\/p>\n<p><\/p>\n<p>Exist\u0103 o not\u0103 c\u0103 acest lucru ar trebui aplicat doar pentru ramura master.<\/p>\n<p><\/p>\n<p>Schimb\u0103rile \u00een alte ramuri nu sunt executate.<\/p>\n<p><\/p>\n<p>Exist\u0103 posibilitatea de a organiza livr\u0103ri pe ramuri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/8a5b880bd9a0d4bab0b276568e2ba413.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pentru a organiza mai departe acest lucru, trebuie s\u0103 instal\u0103m GitLab Runner.<\/p>\n<p><\/p>\n<p>Aceasta este o unealt\u0103 scris\u0103 \u00een Golang. Este un singur fi\u0219ier, a\u0219a cum este obi\u0219nuit \u00een lumea Golang, care nu necesit\u0103 alte dependen\u021be.<\/p>\n<p><\/p>\n<p>La pornire, \u00eenregistr\u0103m GitLab Runner.<\/p>\n<p><\/p>\n<p>Ob\u021binem \u00een interfa\u021ba web GitLab cheia.<\/p>\n<p><\/p>\n<p>Apoi apel\u0103m comanda de ini\u021bializare \u00een linia de comand\u0103.<\/p>\n<p><\/p>\n<p>Configur\u0103m GitLab Runner \u00een modul de dialog (Shell, Docker, VirtualBox, SSH).<\/p>\n<p><\/p>\n<p>Codul pe GitLab Runner va fi executat la fiecare commit \u00een func\u021bie de configurarea .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/37c8ac7499f0cfba2eb07a84083e44e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cum arat\u0103 vizual \u00een Gitlab \u00een interfa\u021ba web. Dup\u0103 ce am conectat Gitlab CI, ne apare un indicator care arat\u0103 \u00een ce stadiu se afl\u0103 buildul \u00een acest moment.<\/p>\n<p><\/p>\n<p>Vedem c\u0103 acum 4 minute a fost f\u0103cut un commit care a trecut toate testele \u0219i nu a cauzat probleme.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/33ac79c45f0651a5f8bde75092c4ac44.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Putem s\u0103 ne uit\u0103m mai detaliat la builduri. Aici vedem c\u0103 au fost deja trecute dou\u0103 st\u0103ri. Starea de testare \u0219i starea de deploy pe staging.<\/p>\n<p><\/p>\n<p>Dac\u0103 facem clic pe un build specific, acolo va fi ie\u0219irea de consol\u0103 a comenzilor care au fost rulate \u00een proces conform .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d26dd28708c7fc8a409af4be4d48f502.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A\u0219a arat\u0103 istoricul produsului nostru. Vedem \u00eencerc\u0103ri reu\u0219ite. C\u00e2nd testele e\u0219ueaz\u0103, urm\u0103torul pas nu se finalizeaz\u0103 \u0219i codul pe staging nu se actualizeaz\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ee7bd81dc283c7af0c194779d4230780.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce probleme am rezolvat pe staging c\u00e2nd am implementat docker? Sistemul nostru este compus din componente \u0219i a ap\u0103rut necesitatea de a repornit doar p\u0103r\u021bile componente care au fost actualizate \u00een repository, nu \u00eentregul sistem.<\/p>\n<p><\/p>\n<p>Pentru aceasta a trebuit s\u0103 le \u00eemp\u0103r\u021bim pe fiecare \u00een foldere separate.<\/p>\n<p><\/p>\n<p>Dup\u0103 ce am f\u0103cut asta, am avut o problem\u0103 cu faptul c\u0103 Docker-compose creeaz\u0103 pentru fiecare folder un spa\u021biu de re\u021bea propriu \u0219i nu vede componentele vecine.<\/p>\n<p><\/p>\n<p>Pentru a o ocoli, am creat manual o re\u021bea \u00een Docker. \u00cen Docker-compose am specificat s\u0103 foloseasc\u0103 aceast\u0103 re\u021bea pentru acest proiect.<\/p>\n<p><\/p>\n<p>Astfel, fiecare component\u0103 care porne\u0219te cu aceast\u0103 re\u021bea vede componentele din alte p\u0103r\u021bi ale sistemului.<\/p>\n<p><\/p>\n<p>Problema urm\u0103toare este separarea staging-ului \u00eentre mai multe proiecte.<\/p>\n<p><\/p>\n<p>Pentru ca totul s\u0103 arate bine \u0219i s\u0103 fie c\u00e2t mai asem\u0103n\u0103tor cu produc\u021bia, este bine s\u0103 folosim portul 80 sau 443, care este folosit \u00een mod obi\u0219nuit \u00een WEB.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f863cf1833271bf132455a70ad7d2706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cum am rezolvat asta? Am desemnat un Gitlab Runner pentru toate proiectele mari.<\/p>\n<p><\/p>\n<p>Gitlab permite pornirea mai multor Gitlab Runne-uri distribuite, care vor lua pur \u0219i simplu toate sarcinile \u00een ordine aleatorie.<\/p>\n<p><\/p>\n<p>Pentru a nu se crea haos, am limitat grupul proiectelor noastre la un singur Gitlab Runner, care se descurc\u0103 f\u0103r\u0103 probleme cu volumul nostru.<\/p>\n<p><\/p>\n<p>Am mutat nginx-proxy \u00eentr-un script de pornire separat \u0219i \u00een acesta am specificat re\u021belele tuturor proiectelor. <\/p>\n<p><\/p>\n<p>Proiectul nostru are o re\u021bea, iar balancer-ul are mai multe re\u021bele dup\u0103 numele proiectelor. Poate proxyia mai departe dup\u0103 numele de domeniu.<\/p>\n<p><\/p>\n<p>La noi, solicit\u0103rile vin pe domeniu pe portul 80 \u0219i sunt gestionate \u00eentr-un grup de containere care deserve\u0219te acest domeniu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25c769f029b272a17fd06bbe60cf0ea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce alte probleme au fost? Este faptul c\u0103, implicit, toate containerele ruleaz\u0103 sub utilizatorul root. Acest root nu este acela\u0219i cu root-ul sistemului.<\/p>\n<p><\/p>\n<p>Cu toate acestea, dac\u0103 intri \u00een container, acesta va fi root \u0219i fi\u0219ierul pe care \u00eel cre\u0103m \u00een acest container prime\u0219te permisiuni root.<\/p>\n<p><\/p>\n<p>Dac\u0103 dezvoltatorul a intrat \u00een container \u0219i a efectuat acolo c\u00e2teva comenzi care genereaz\u0103 fi\u0219iere, apoi a ie\u0219it din container, atunci \u00een directorul s\u0103u de lucru va avea un fi\u0219ier la care nu are acces.<\/p>\n<p><\/p>\n<p>Cum putem rezolva aceasta? Putem ad\u0103uga utilizatori care vor fi \u00een container.<\/p>\n<p><\/p>\n<p>Ce probleme au ap\u0103rut c\u00e2nd am ad\u0103ugat un utilizator?<\/p>\n<p><\/p>\n<p>Atunci c\u00e2nd cre\u0103m un utilizator, adesea nu coincid ID-ul grupului (UID) \u0219i ID-ul utilizatorului (GID).<\/p>\n<p><\/p>\n<p>Pentru a rezolva aceast\u0103 problem\u0103, \u00een container folosim utilizatori cu ID 1000.<\/p>\n<p><\/p>\n<p>\u00cen cazul nostru, aceasta a coincis cu faptul c\u0103 practic to\u021bi dezvoltatorii folosesc sistemul de operare Ubuntu. Iar \u00een Ubuntu, primul utilizator are ID 1000.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d4911374e4953fdcd807c387efeafec3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce planuri avem?<\/p>\n<p><\/p>\n<p>S\u0103 citim documenta\u021bia despre Docker. Proiectul se dezvolt\u0103 activ, documenta\u021bia se schimb\u0103. Informa\u021biile care au fost ob\u021binute acum dou\u0103-trei luni devin treptat \u00eenvechite. <\/p>\n<p><\/p>\n<p>Unele probleme pe care le-am rezolvat sunt probabil deja rezolvate prin mijloace standard.<\/p>\n<p><\/p>\n<p>Cu siguran\u021b\u0103, ne dorim s\u0103 mergem mai departe direct c\u0103tre orchestrare.<\/p>\n<p><\/p>\n<p>Un exemplu este mecanismul \u00eencorporat \u00een Docker, numit Docker Swarm, care vine din cutie. Ne dorim s\u0103 lans\u0103m ceva \u00een produc\u021bie pe baza tehnologiei Docker Swarm.<\/p>\n<p><\/p>\n<p>Generarea containerelor face ca lucrul cu jurnalele s\u0103 fie incomod. Acum, jurnalele sunt izolate. Ele sunt \u00eempr\u0103\u0219tiate printre containere. Una dintre sarcini este de a facilita accesul la jurnale printr-un interfa\u021b\u0103 web.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/cff8c72dd8af7de1fa0227601bd1d69c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Sursa: <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.2.1 - 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\/ro\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47 Procesul de dezvoltare \u0219i testare cu Docker \u0219i Gitlab CI | ProHoster","description":"V\u0103 propun s\u0103 consulta\u021bi transcrierea raportului lui Alexandr Sigacev de la Inventos despre \"Procesul de dezvoltare \u0219i testare cu Docker + Gitlab CI\". Cei care abia \u00eencepe s\u0103 implementeze procesul de dezvoltare.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/32526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=32526"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/32526\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/24326"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=32526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=32526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=32526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}