{"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\/sv\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","title":{"rendered":"Utvecklings- och testprocess med Docker och Gitlab CI","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Jag f\u00f6resl\u00e5r att ni bekantar er med transkriptionen av Alexander Sigachevs rapport fr\u00e5n Inventos \"Processen f\u00f6r utveckling och testning med Docker + Gitlab CI\"<\/strong><\/p>\n<p><\/p>\n<p>De som just har b\u00f6rjat implementera utvecklings- och testprocessen baserad p\u00e5 Docker + Gitlab CI st\u00e4ller ofta grundl\u00e4ggande fr\u00e5gor. Hur ska man b\u00f6rja? Hur ska man organisera det? Hur ska man testa?<\/p>\n<p><\/p>\n<p>Detta f\u00f6redrag \u00e4r bra eftersom det strukturerat beskriver utvecklings- och testprocessen med hj\u00e4lp av Docker och Gitlab CI. Sj\u00e4lva f\u00f6redraget \u00e4r fr\u00e5n 2017. Jag tror att man kan h\u00e4mta grundl\u00e4ggande principer, metodik, id\u00e9er och erfarenheter fr\u00e5n detta f\u00f6redrag. <\/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=\"Spela 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>Den som \u00e4r intresserad, v\u00e4nligen l\u00e4s vidare. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Jag heter Alexander Sigachev. Jag arbetar p\u00e5 f\u00f6retaget Inventos. Jag kommer att ber\u00e4tta om min erfarenhet av att anv\u00e4nda Docker och hur vi gradvis implementerar det i v\u00e5ra projekt.<\/p>\n<p><\/p>\n<p>\u00c4mnet f\u00f6r f\u00f6redraget: Utvecklingsprocessen med anv\u00e4ndning av Docker och Gitlab CI. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e30c4757e4bda1bcc3e20b16e8e2709e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Detta \u00e4r mitt andra f\u00f6redrag om Docker. Vid tidpunkten f\u00f6r det f\u00f6rsta f\u00f6redraget anv\u00e4nde vi Docker endast i utveckling p\u00e5 utvecklarnas maskiner. Antalet anst\u00e4llda som anv\u00e4nde Docker var ungef\u00e4r 2-3 personer. Successivt har vi samlat erfarenhet och gjort sm\u00e5 framsteg. L\u00e4nk till v\u00e5rt <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">f\u00f6rsta f\u00f6redrag<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Vad kommer att tas upp i detta f\u00f6redrag? Vi kommer att dela med oss av erfarenheter kring de fallgropar vi har st\u00f6tt p\u00e5, vilka problem vi har l\u00f6st. Det var inte alltid vackert, men det har till\u00e5tit oss att g\u00e5 vidare.<\/p>\n<p><\/p>\n<p>V\u00e5r slogan: dockerisera allt vi kommer \u00e5t.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25ae4f97f1c502384abfe697bac502b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vilka problem l\u00f6ser vi?<\/p>\n<p><\/p>\n<p>N\u00e4r det finns flera team i f\u00f6retaget s\u00e5 \u00e4r programmeraren en delad resurs. Det finns faser n\u00e4r en programmerare dras ut fr\u00e5n ett projekt och tillf\u00e4lligt ges till ett annat projekt.<\/p>\n<p><\/p>\n<p>F\u00f6r att en programmerare snabbt ska kunna s\u00e4tta sig in i projektet beh\u00f6ver hen ladda ner projektets k\u00e4llkod och s\u00e5 snabbt som m\u00f6jligt starta en milj\u00f6 som g\u00f6r att hen kan forts\u00e4tta och l\u00f6sa uppgifterna i det aktuella projektet.<\/p>\n<p><\/p>\n<p>Vanligtvis, om man b\u00f6rjar fr\u00e5n b\u00f6rjan, finns det lite dokumentation i projektet. Informationen om hur man konfigurerar finns endast hos veteranerna. Anst\u00e4llda st\u00e4ller oftast in sin arbetsplats p\u00e5 en eller tv\u00e5 dagar. F\u00f6r att snabba upp detta har vi anv\u00e4nt Docker.<\/p>\n<p><\/p>\n<p>Den n\u00e4sta anledningen \u00e4r standardisering av inst\u00e4llningar i Development. Utifr\u00e5n min erfarenhet visar utvecklarna alltid initiativ. I vart femte fall inf\u00f6rs en anpassad dom\u00e4n, som vasya.dev. Bredvid sitter grannen Petya, som har dom\u00e4nen petya.dev. De utvecklar en webbplats eller n\u00e5gon komponent av systemet med hj\u00e4lp av detta dom\u00e4nnamn.<\/p>\n<p><\/p>\n<p>N\u00e4r systemet v\u00e4xer och dessa dom\u00e4nnamn b\u00f6rjar dyka upp i konfigurationerna, uppst\u00e5r det en konflikt i Development-milj\u00f6er och s\u00f6kv\u00e4gen till webbplatsen skrivs om.<\/p>\n<p><\/p>\n<p>Detsamma h\u00e4nder med inst\u00e4llningarna f\u00f6r databasen. N\u00e5gon bekymrar sig inte f\u00f6r s\u00e4kerheten och arbetar med ett tomt root-l\u00f6senord. N\u00e5gon annan, vid installationen av MySQL, kr\u00e4vdes l\u00f6senord och det blev 123. Det h\u00e4nder ofta att databasens konfiguration st\u00e4ndigt \u00e4ndras beroende p\u00e5 utvecklarens commit. N\u00e5gon har fixat, n\u00e5gon har inte fixat konfigurationen. Det fanns knep f\u00f6r att vi tog ut en testkonfiguration i <code>.gitignore<\/code> och varje utvecklare var tvungen att installera databasen. Det f\u00f6rsv\u00e5rade startprocessen. F\u00f6rutom allt annat m\u00e5ste man komma ih\u00e5g databasen. Databasen beh\u00f6ver initieras, man m\u00e5ste ange l\u00f6senord, man m\u00e5ste ange anv\u00e4ndare, skapa tabeller och s\u00e5 vidare.<\/p>\n<p><\/p>\n<p>Ett annat problem \u00e4r olika versioner av bibliotek. Det \u00e4r ofta s\u00e5 att utvecklaren arbetar med olika projekt. Det finns ett Legacy-projekt som startades f\u00f6r fem \u00e5r sedan (fr\u00e5n 2017 - anm. red.). Vid starten anv\u00e4nde vi MySQL 5.5. Det finns \u00e4ven moderna projekt d\u00e4r vi str\u00e4var efter att inf\u00f6ra mer moderna versioner av MySQL, till exempel 5.7 eller senare (fr\u00e5n 2017 - anm. red.)<\/p>\n<p><\/p>\n<p>Den som arbetar med MySQL vet att dessa bibliotek tar med sig beroenden. Det \u00e4r ganska problematiskt att k\u00f6ra tv\u00e5 databaser samtidigt. \u00c5tminstone \u00e4r det problematiskt att f\u00e5 gamla kunder att ansluta till den nya databasen. Detta ger i sin tur upphov till flera problem.<\/p>\n<p><\/p>\n<p>Ett vanligt problem \u00e4r n\u00e4r utvecklaren arbetar p\u00e5 en lokal maskin och anv\u00e4nder lokala resurser, lokala filer och lokalt RAM. All interaktion under utvecklingen av l\u00f6sningar sker p\u00e5 grundval av att allt fungerar p\u00e5 en och samma maskin. Ett exempel kan vara n\u00e4r vi har tre backend-servrar i produktion, men utvecklaren sparar filer i rotkatalogen och d\u00e4rifr\u00e5n h\u00e4mtar nginx filerna f\u00f6r att svara p\u00e5 f\u00f6rfr\u00e5gningar. N\u00e4r denna kod hamnar i produktion, visar det sig att filen finns p\u00e5 en av de tre servrarna.<\/p>\n<p><\/p>\n<p>F\u00f6r n\u00e4rvarande utvecklas mikrotj\u00e4nster. N\u00e4r vi delar upp v\u00e5ra stora applikationer i mindre komponenter som interagerar med varandra. Detta g\u00f6r det m\u00f6jligt att v\u00e4lja teknologier specifikt f\u00f6r den uppgiftstablett. Det g\u00f6r det ocks\u00e5 m\u00f6jligt att dela arbete och ansvarsomr\u00e5den mellan utvecklarna.<\/p>\n<p><\/p>\n<p>En frontend-utvecklare, som utvecklar i JS, p\u00e5verkar i stort sett inte backend. Backend-utvecklaren arbetar i sin tur med Ruby on Rails i v\u00e5rt fall och st\u00f6r inte frontend. Interaktionen sker via API.<\/p>\n<p><\/p>\n<p>Som en bonus har vi kunnat optimera resurser p\u00e5 Staging med hj\u00e4lp av Docker. Varje projekt kr\u00e4vde p\u00e5 grund av sin specifika karakt\u00e4r vissa inst\u00e4llningar. Fysiskt beh\u00f6vdes det antingen att avs\u00e4tta en virtuell server och konfigurera den separat, eller att dela n\u00e5gra tillf\u00e4lliga milj\u00f6er, och projekten kunde p\u00e5verka varandra beroende p\u00e5 versionerna av biblioteken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/fa5c99f90faef84a356d4791fd915830.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Verktyg. Vad anv\u00e4nder vi? <\/p>\n<p><\/p>\n<ul>\n<li>Sj\u00e4lva Docker. I Dockerfile beskrivs beroenden f\u00f6r en applikation. <\/li>\n<li>Docker-compose \u00e4r en sammans\u00e4ttning som f\u00f6renar flera av v\u00e5ra Docker-applikationer.<\/li>\n<li>Vi anv\u00e4nder GitLab f\u00f6r lagring av k\u00e4llkoden.<\/li>\n<li>Vi anv\u00e4nder GitLab-CI f\u00f6r systemintegration.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/b6041827a6ba928e0d33add6b79c581c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Rapporten best\u00e5r av tv\u00e5 delar.<\/p>\n<p><\/p>\n<p>Den f\u00f6rsta delen handlar om hur vi k\u00f6rde Docker p\u00e5 utvecklarnas maskiner.<\/p>\n<p><\/p>\n<p>Den andra delen handlar om hur vi interagerar med GitLab, hur vi k\u00f6r tester och hur vi distribuerar till Staging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/45746d3323d35e0d18f066c8bfcb2214.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker \u00e4r en teknologi som g\u00f6r det m\u00f6jligt att (med hj\u00e4lp av ett deklarativt tillv\u00e4gag\u00e5ngss\u00e4tt) beskriva n\u00f6dv\u00e4ndiga komponenter. Detta \u00e4r ett exempel p\u00e5 en Dockerfile. H\u00e4r deklarerar vi att vi g\u00e5r fr\u00e5n den officiella Docker-bilden Ruby:2.3.0. Den inneh\u00e5ller Ruby version 2.3 installerad. Vi installerar n\u00f6dv\u00e4ndiga byggbibliotek och NodeJS. Vi beskriver att vi skapar en katalog. <code>\/app<\/code>. Vi tilldelar katalogen app som arbetskatalog. I denna katalog placerar vi den n\u00f6dv\u00e4ndiga minimala Gemfile och Gemfile.lock. D\u00e4refter utf\u00f6r vi byggen av projekt som installerar detta beroendeavbild. Vi anger att containern kommer att vara redo att lyssna p\u00e5 extern port 3000. Sista kommandot \u00e4r det som direkt startar v\u00e5r applikation. Om vi k\u00f6r kommandot f\u00f6r att starta projektet, kommer applikationen att f\u00f6rs\u00f6ka k\u00f6ra sig och k\u00f6ra det angivna kommandot.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ba503c305ae90f49b39f4ae2cbda1668.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Detta \u00e4r ett minimalt exempel p\u00e5 en docker-compose-fil. H\u00e4r visar vi hur tv\u00e5 containrar \u00e4r kopplade. Det handlar om databastj\u00e4nsten och webbtj\u00e4nsten. V\u00e5ra web-applikationer kr\u00e4ver oftast en databas som backend f\u00f6r att lagra data. Eftersom vi anv\u00e4nder MySQL, \u00e4r exemplet med MySQL \u2014 men ingenting hindrar oss fr\u00e5n att anv\u00e4nda en annan databas (PostgreSQL, Redis).<\/p>\n<p><\/p>\n<p>Vi tar officiella bilden fr\u00e5n Docker hub av MySQL 5.7.14 utan \u00e4ndringar. Bilden som ansvarar f\u00f6r v\u00e5r web-applikation bygger vi fr\u00e5n den aktuella katalogen. Den bygger bilden vid f\u00f6rsta k\u00f6rningen. Efter det k\u00f6rs kommandot vi h\u00e4r utf\u00f6r. Om vi g\u00e5r tillbaka, kommer vi att se att startkommandot definierades via Puma. Puma \u00e4r en tj\u00e4nst skriven i Ruby. I det andra fallet \u00e5sidos\u00e4tter vi. Detta kommando kan vara godtyckligt beroende p\u00e5 v\u00e5ra behov eller uppgifter.<\/p>\n<p><\/p>\n<p>Vi beskriver ocks\u00e5 att vi beh\u00f6ver vidarebefordra porten p\u00e5 v\u00e5r utvecklarv\u00e4rdmaskin fr\u00e5n 3000 till 3000-porten p\u00e5 containern. Detta g\u00f6rs automatiskt med hj\u00e4lp av iptables och sin egen mekanism, som direkt \u00e4r inb\u00e4ddad i Docker. <\/p>\n<p><\/p>\n<p>Utvecklaren kan ocks\u00e5 som tidigare rikta in sig p\u00e5 vilken tillg\u00e4nglig IP-adress som helst, till exempel 127.0.0.1 lokal eller den externa IP-adressen p\u00e5 maskinen.<\/p>\n<p><\/p>\n<p>Den sista raden s\u00e4ger att webcontainern beror p\u00e5 db-containern. N\u00e4r vi anropar f\u00f6r att starta webcontainern, kommer docker-compose f\u00f6rst att starta databasen. N\u00e4r databasen startar (i sj\u00e4lva verket \u2014 efter att containern k\u00f6rs! Databasens beredskap garanterar inte detta), kommer v\u00e5r applikation, v\u00e5r backend, att startas.<\/p>\n<p><\/p>\n<p>Detta f\u00f6rhindrar fel, n\u00e4r databasen inte har startats och sparar resurser n\u00e4r vi stoppar databaskontainern, vilket frig\u00f6r resurserna f\u00f6r andra projekt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4acbcf5de89b98db055e8abc419202de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vad ger oss anv\u00e4ndningen av databas-dockerisering i projektet? Vi fastst\u00e4ller MySQL-versionen f\u00f6r alla utvecklare. Detta hj\u00e4lper till att undvika vissa fel som kan uppst\u00e5 vid versionsavvikelser, n\u00e4r syntax, konfiguration och standardinst\u00e4llningar \u00e4ndras. Detta g\u00f6r det m\u00f6jligt att ange gemensamma v\u00e4rdnamn f\u00f6r databasen, inloggning och l\u00f6senord. Vi l\u00e4mnar det kaos av namn och konflikter i konfigurationsfiler som tidigare fanns. <\/p>\n<p><\/p>\n<p>Vi har m\u00f6jlighet att anv\u00e4nda en mer optimal konfiguration f\u00f6r utvecklingsmilj\u00f6n, som skiljer sig fr\u00e5n den standardkonfiguration som finns. MySQL \u00e4r som standard inst\u00e4llt f\u00f6r svaga maskiner och dess prestanda \u00e4r ganska l\u00e5g direkt ur kartongen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/417d77a06b18e2df9b71440c0f2a1653.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker g\u00f6r det m\u00f6jligt att anv\u00e4nda den n\u00f6dv\u00e4ndiga versionen av Python, Ruby, NodeJS, PHP. Vi slipper behovet av att anv\u00e4nda n\u00e5gon versionshanterare. Tidigare anv\u00e4nde vi ett RPM-paket f\u00f6r Ruby som gjorde att vi kunde \u00e4ndra version beroende p\u00e5 projektet. Dessutom g\u00f6r det m\u00f6jligt att smidigt migrera kod och versionera den tillsammans med beroenden tack vare Docker-containern. Vi f\u00e5r inga problem med att f\u00f6rst\u00e5 versionen av b\u00e5de tolk och kod. F\u00f6r att uppdatera versionen m\u00e5ste vi s\u00e4nka den gamla containern och starta en ny. Om n\u00e5got g\u00e5r fel kan vi s\u00e4nka den nya containern och starta den gamla.<\/p>\n<p><\/p>\n<p>Efter byggandet av bilden kommer containrarna, b\u00e5de i utvecklings- och produktionsmilj\u00f6, att vara identiska. Detta \u00e4r s\u00e4rskilt viktigt f\u00f6r stora installationer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/185a1bfe257f7e3e0eecdc6e0e0d330f.jpg\" style=\"display:block;margin: 0 auto;\" \/> P\u00e5 frontend anv\u00e4nder vi JavaScript och NodeJS.<\/p>\n<p><\/p>\n<p>Just nu \u00e4r v\u00e5rt senaste projekt baserat p\u00e5 ReactJS. Utvecklaren k\u00f6rde alla containrar och utvecklade med hj\u00e4lp av hot-reload.<\/p>\n<p><\/p>\n<p>D\u00e4refter startas en uppgift f\u00f6r att bygga JavaScript och den samlade koden levereras som statisk via nginx f\u00f6r att spara resurser.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4c2e28319d56d7fc81845b4133a1bfe6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>H\u00e4r har jag lagt fram en skiss av v\u00e5rt senaste projekt.<\/p>\n<p><\/p>\n<p>Vilka uppgifter l\u00f6ste vi? Vi fick behov av att bygga ett system som interagerar med mobila enheter. De f\u00e5r data. En av funktionerna \u00e4r att skicka push-notiser till denna enhet. <\/p>\n<p><\/p>\n<p>Vad gjorde vi f\u00f6r detta?<\/p>\n<p><\/p>\n<p>Vi delade upp applikationen i komponenter som: administrationsdelen p\u00e5 JS, backend som fungerar via REST-API under Ruby on Rails. Backend interagerar med databasen. Resultaten som genereras skickas till kunden. Administrationssystemet interagerar med backend och databasen via REST-API.<\/p>\n<p><\/p>\n<p>Vi beh\u00f6vde ocks\u00e5 skicka Push-notiser. Tidigare hade vi ett projekt d\u00e4r en mekanism implementerades f\u00f6r att leverera meddelanden till mobila plattformar. <\/p>\n<p><\/p>\n<p>Vi utvecklade ett schema: operat\u00f6ren fr\u00e5n webbl\u00e4saren interagerar med administrationspanelen, administrationspanelen interagerar med backend, och en uppgift st\u00e4lls f\u00f6r att skicka Push-notiser.<\/p>\n<p><\/p>\n<p>Push-notiser interagerar med en annan komponent som \u00e4r implementerad i NodeJS.<\/p>\n<p><\/p>\n<p>K\u00f6er byggs och sedan sker leveransen av meddelanden enligt mekanismen.<\/p>\n<p><\/p>\n<p>H\u00e4r visas tv\u00e5 databaser. F\u00f6r n\u00e4rvarande anv\u00e4nder vi med hj\u00e4lp av Docker tv\u00e5 oberoende databaser som inte \u00e4r kopplade till varandra. Den enda kopplingen \u00e4r att de har ett gemensamt virtuellt n\u00e4tverk, medan de fysiska datalagringarna finns i olika kataloger p\u00e5 utvecklarens maskin.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Samma sak men i siffror. H\u00e4r \u00e4r \u00e5teranv\u00e4ndning av koden viktig.<\/p>\n<p><\/p>\n<p>Om vi tidigare talade om \u00e5teranv\u00e4ndning av kod i form av bibliotek, s\u00e5 i det h\u00e4r exemplet \u00e5teranv\u00e4nds v\u00e5r tj\u00e4nst f\u00f6r Push-notiser som en komplett server. Den tillhandah\u00e5ller API. Och v\u00e5r nya utveckling interagerar med den.<\/p>\n<p><\/p>\n<p>Vid den tidpunkten anv\u00e4nde vi version 4 av NodeJS. Nu (\u00e5r 2017) i nya utvecklingar anv\u00e4nder vi version 7 av NodeJS. Det \u00e4r inga problem att anv\u00e4nda nya versioner av bibliotek i nya komponenter. <\/p>\n<p><\/p>\n<p>Vid behov kan vi genomf\u00f6ra en omstrukturering och uppgradera versionen av NodeJS i tj\u00e4nsten f\u00f6r Push-notiser. <\/p>\n<p><\/p>\n<p>Och om vi kan beh\u00e5lla API-kompatibilitet kan den ers\u00e4ttas i andra projekt som anv\u00e4nts tidigare.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5c58c65be078a5a1b9fc17ee2e7b4ad4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vad beh\u00f6vs f\u00f6r att l\u00e4gga till Docker? Vi l\u00e4gger till en Dockerfile i v\u00e5rt repository, som beskriver n\u00f6dv\u00e4ndiga beroenden. I det h\u00e4r exemplet \u00e4r komponenterna uppdelade efter logik. Detta \u00e4r en minimiset av vad en backend-utvecklare beh\u00f6ver.<\/p>\n<p><\/p>\n<p>N\u00e4r vi skapar ett nytt projekt skapar vi en Dockerfile, beskriver den n\u00f6dv\u00e4ndiga ekosystemet (Python, Ruby, NodeJS). I docker-compose beskriver vi n\u00f6dv\u00e4ndiga beroenden \u2013 databasen. Vi specificerar vilken version av databasen som beh\u00f6vs och var data ska lagras.<\/p>\n<p><\/p>\n<p>Vi anv\u00e4nder en separat tredje container med nginx f\u00f6r att hantera statisk inneh\u00e5ll. M\u00f6jlighet att ladda upp bilder \u00e4r f\u00f6rutsedd. Backend placerar dem i en f\u00f6rberedd volym, som ocks\u00e5 \u00e4r monterad i containern med nginx, som hanterar den statiska inneh\u00e5ll.<\/p>\n<p><\/p>\n<p>F\u00f6r att lagra konfigurationen av nginx och mysql har vi lagt till en Docker-mapp d\u00e4r vi sparar de n\u00f6dv\u00e4ndiga konfigurationerna. N\u00e4r utvecklaren g\u00f6r en git clone av repot till sin maskin f\u00e5r han ett projekt som redan \u00e4r klart f\u00f6r lokal utveckling. Det uppst\u00e5r inga fr\u00e5gor om vilken port eller vilken inst\u00e4llning som ska till\u00e4mpas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e7a6b308a75cacf8ce60687a9e6081dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sedan har vi flera komponenter: admin, inform-API, push-notifikationer.<\/p>\n<p><\/p>\n<p>F\u00f6r att starta allt detta har vi skapat ytterligare ett repo som vi kallade dockerized-app. F\u00f6r n\u00e4rvarande anv\u00e4nder vi flera repos f\u00f6r varje komponent. De skiljer sig logiskt \u2014 i GitLab ser det ut som en mapp, och p\u00e5 utvecklarens maskin finns en mapp f\u00f6r det specifika projektet. P\u00e5 en l\u00e4gre niv\u00e5 finns komponenter som kommer att samlas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f4e2c45c8ec20fca0bac74b3a3892543.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Detta \u00e4r ett exempel p\u00e5 inneh\u00e5llet i dockerized-app. Vi f\u00f6r ocks\u00e5 ut en Docker-katalog h\u00e4r, d\u00e4r vi fyller p\u00e5 med konfigurationer som kr\u00e4vs f\u00f6r interaktionerna mellan alla komponenter. Det finns en README.md som kort beskriver hur man startar projektet.<\/p>\n<p><\/p>\n<p>H\u00e4r har vi anv\u00e4nt tv\u00e5 docker-compose-filer. Det \u00e4r gjort f\u00f6r att kunna starta stegvis. N\u00e4r utvecklaren arbetar med k\u00e4rnan beh\u00f6ver han inte push-notifikationer, s\u00e5 han startar bara docker-compose-filen och d\u00e4rmed besparar resurser.<\/p>\n<p><\/p>\n<p>Om det beh\u00f6vs en integration med push-notifikationer startas docker-compose.yaml och docker-compose-push.yaml.<\/p>\n<p><\/p>\n<p>Eftersom docker-compose.yaml och docker-compose-push.yaml ligger i en mapp, skapas automatiskt ett gemensamt virtuell n\u00e4tverk.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/535019c82c72c1602176fbaf4aa5640f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Beskrivning av komponenterna. Detta \u00e4r en mer utt\u00f6mmande fil som ansvarar f\u00f6r sammanst\u00e4llningen av komponenterna. Vad \u00e4r anm\u00e4rkningsv\u00e4rt h\u00e4r? H\u00e4r introducerar vi komponentbalanseraren.<\/p>\n<p><\/p>\n<p>Detta \u00e4r en f\u00e4rdig Docker-bild d\u00e4r nginx och en applikation k\u00f6rs, som lyssnar p\u00e5 Docker-socket. Dynamiskt, n\u00e4r containrar sl\u00e5s p\u00e5 och av, regenereras nginx-konfigurationen. Vi distribuerar hanteringen av komponenterna efter tredjepartsdom\u00e4ner.<\/p>\n<p><\/p>\n<p>F\u00f6r utvecklingsmilj\u00f6n anv\u00e4nder vi dom\u00e4nen .dev \u2014 api.informer.dev. Applikationerna med dom\u00e4nen .dev \u00e4r tillg\u00e4ngliga p\u00e5 utvecklarens lokala maskin.<\/p>\n<p><\/p>\n<p>Vidare \u00f6verf\u00f6rs konfigurationerna till varje projekt och alla projekt startas tillsammans samtidigt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/bc1e11e6f1fd1c837d2c8087d04145c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Om man grafiskt visar det f\u00e5r vi klienten som v\u00e5r webbl\u00e4sare eller n\u00e5got verktyg som vi anv\u00e4nder f\u00f6r att g\u00f6ra anrop till balanceraren.<\/p>\n<p><\/p>\n<p>Balanceraren avg\u00f6r enligt dom\u00e4nnamnet vilken container den ska kontakta.<\/p>\n<p><\/p>\n<p>Det kan vara nginx som levererar JS f\u00f6r adminpanelen. Det kan vara nginx som levererar API eller statiska filer som levereras av nginx i form av bilduppladdningar.<\/p>\n<p><\/p>\n<p>I diagrammet syns att containrarna \u00e4r sammanl\u00e4nkade i ett virtuellt n\u00e4tverk och dolda bakom en proxy.<\/p>\n<p><\/p>\n<p>P\u00e5 utvecklarmaskinen kan man n\u00e5 containern om man k\u00e4nner till IP-adressen, men vi anv\u00e4nder faktiskt inte detta. Det finns s\u00e4llan behov av direkt \u00e5tkomst.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/2908c31fd9d3c79f6189bdbeeb6d028f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vilket exempel ska man titta p\u00e5 f\u00f6r att dockerisera sin applikation? Enligt min \u00e5sikt \u00e4r det officiella Docker-image f\u00f6r MySQL ett bra exempel.<\/p>\n<p><\/p>\n<p>Det \u00e4r ganska komplext. Det finns m\u00e5nga versioner. Men dess funktionalitet t\u00e4cker m\u00e5nga behov som kan uppst\u00e5 under vidare utveckling. Om du tar dig tid att f\u00f6rst\u00e5 hur allt detta interagerar, tror jag att du kommer att slippa problem med sj\u00e4lvintegration.<\/p>\n<p><\/p>\n<p>P\u00e5 hub.docker.com finns vanligtvis l\u00e4nkar till github.com, d\u00e4r r\u00e5data finns direkt, s\u00e5 att man sj\u00e4lv kan samla en image.<\/p>\n<p><\/p>\n<p>I det h\u00e4r arkivet finns ocks\u00e5 skriptet docker-endpoint.sh, som ansvarar f\u00f6r den initiala konfigurationen och f\u00f6r vidare behandling av applikationens start.<\/p>\n<p><\/p>\n<p>I det h\u00e4r exemplet finns \u00e4ven m\u00f6jlighet till konfiguration med hj\u00e4lp av milj\u00f6variabler. Genom att definiera milj\u00f6variabler vid start av en enskild container eller genom docker-compose kan man ange att vi beh\u00f6ver s\u00e4tta ett tomt l\u00f6senord f\u00f6r docker eller ett som vi vill ha f\u00f6r root p\u00e5 MySQL.<\/p>\n<p><\/p>\n<p>Det finns ett alternativ att skapa ett slumpm\u00e4ssigt l\u00f6senord. Vi s\u00e4ger att vi beh\u00f6ver en anv\u00e4ndare, vi beh\u00f6ver s\u00e4tta en anv\u00e4ndares l\u00f6senord och vi beh\u00f6ver skapa en databas.<\/p>\n<p><\/p>\n<p>I v\u00e5ra projekt har vi lite standardiserat Dockerfile som ansvarar f\u00f6r initialisering. D\u00e4r har vi gjort \u00e4ndringar f\u00f6r v\u00e5ra behov f\u00f6r att enkelt ge anv\u00e4ndaren r\u00e4ttigheter som applikationen anv\u00e4nder. Detta m\u00f6jliggjorde senare att enkelt skapa en databas fr\u00e5n applikationens konsol. I Ruby-applikationer finns det kommandon f\u00f6r att skapa, \u00e4ndra och ta bort databaser.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4a9b56e21819d28dd39753134d23fee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Detta \u00e4r ett exempel p\u00e5 hur en specifik version av MySQL ser ut p\u00e5 github.com. Dockerfile kan \u00f6ppnas och man kan se hur installationen g\u00e5r till.<\/p>\n<p><\/p>\n<p>docker-endpoint.sh \u00e4r ett skript som ansvarar f\u00f6r ing\u00e5ngspunkten. Vid f\u00f6rsta initialiseringen kr\u00e4vs vissa f\u00f6rberedande \u00e5tg\u00e4rder, och alla dessa \u00e5tg\u00e4rder har flyttats till skriptet f\u00f6r initialisering.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4153fa46526f3d802931dd1db48b08cd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi g\u00e5r vidare till del tv\u00e5.<\/p>\n<p><\/p>\n<p>F\u00f6r att lagra k\u00e4llkoden har vi \u00f6verg\u00e5tt till gitlab. Detta \u00e4r ett kraftfullt system med ett visuellt gr\u00e4nssnitt.<\/p>\n<p><\/p>\n<p>En av komponenterna i Gitlab \u00e4r Gitlab CI. Den g\u00f6r det m\u00f6jligt att beskriva sekvenser av kommandon som senare anv\u00e4nds f\u00f6r att organisera kodleverans eller k\u00f6ra automatiserade tester.<\/p>\n<p><\/p>\n<p>Rapport om Gitlab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 en presentation fr\u00e5n Ruby Russia club \u2014 ganska detaljerad och kanske intressant f\u00f6r er.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5d26d20500f34eeb9768e6c3d91bbefa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nu kommer vi att titta p\u00e5 vad som kr\u00e4vs f\u00f6r att aktivera Gitlab CI. F\u00f6r att starta Gitlab CI r\u00e4cker det med att placera filen .gitlab-ci.yml i projektets rotkatalog.<\/p>\n<p><\/p>\n<p>H\u00e4r beskriver vi vad vi vill utf\u00f6ra, en sekvens av tillst\u00e5nd av typen test, distribution.<\/p>\n<p><\/p>\n<p>Vi k\u00f6r skripten som direkt anropar docker-compose f\u00f6r att bygga v\u00e5r applikation. Detta \u00e4r ett exempel p\u00e5 backend.<\/p>\n<p><\/p>\n<p>D\u00e4refter s\u00e4ger vi att vi m\u00e5ste k\u00f6ra migrationerna f\u00f6r att \u00e4ndra databasen och utf\u00f6ra tester.<\/p>\n<p><\/p>\n<p>Om skripten k\u00f6rs korrekt och inte returnerar en felkod, g\u00e5r systemet vidare till den andra fasen av distribution.<\/p>\n<p><\/p>\n<p>Distributionens fas \u00e4r f\u00f6r n\u00e4rvarande implementerad f\u00f6r staging. Vi har inte organiserat en s\u00f6ml\u00f6s omstart.<\/p>\n<p><\/p>\n<p>Vi sl\u00e4cker alla containrar och startar sedan upp dem igen, de som byggdes under den f\u00f6rsta testfasen.<\/p>\n<p><\/p>\n<p>Vi k\u00f6r migrationerna f\u00f6r den aktuella milj\u00f6n som har skrivits av utvecklarna.<\/p>\n<p><\/p>\n<p>Det finns en notering om att detta endast ska till\u00e4mpas p\u00e5 master-branschen.<\/p>\n<p><\/p>\n<p>Vid \u00e4ndringar i andra branscher utf\u00f6rs det inte.<\/p>\n<p><\/p>\n<p>Det finns m\u00f6jlighet att organisera distributioner per bransch.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/8a5b880bd9a0d4bab0b276568e2ba413.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>F\u00f6r att g\u00e5 vidare med detta beh\u00f6ver vi installera Gitlab Runner.<\/p>\n<p><\/p>\n<p>Detta verktyg \u00e4r skrivet i Golang. Det \u00e4r en enkel fil som \u00e4r typiskt f\u00f6r Golang-v\u00e4rlden, och det kr\u00e4vs inga beroenden.<\/p>\n<p><\/p>\n<p>Vid start registrerar vi Gitlab Runner.<\/p>\n<p><\/p>\n<p>Vi f\u00e5r en nyckel i Gitlabs webbgr\u00e4nssnitt.<\/p>\n<p><\/p>\n<p>Sedan anropar vi kommandot f\u00f6r initialisering i kommandoraden.<\/p>\n<p><\/p>\n<p>Vi konfigurerar Gitlab Runner i dialogl\u00e4ge (Shell, Docker, VirtualBox, SSH)<\/p>\n<p><\/p>\n<p>Koden p\u00e5 Gitlab Runner kommer att k\u00f6ras vid varje commit beroende p\u00e5 inst\u00e4llningarna i .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/37c8ac7499f0cfba2eb07a84083e44e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hur det visuellt ser ut i Gitlab i webgr\u00e4nssnittet. Efter att vi kopplat p\u00e5 Gitlab CI f\u00e5r vi en flagga som visar i vilket tillst\u00e5nd bygget befinner sig f\u00f6r tillf\u00e4llet.<\/p>\n<p><\/p>\n<p>Vi ser att ett commit gjordes f\u00f6r 4 minuter sedan, och den klarade alla tester utan problem.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/33ac79c45f0651a5f8bde75092c4ac44.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi kan titta mer detaljerat p\u00e5 byggen. H\u00e4r ser vi att tv\u00e5 tillst\u00e5nd redan har passerats. Testtillst\u00e5ndet och distribueringsl\u00e4get p\u00e5 staging.<\/p>\n<p><\/p>\n<p>Om vi klickar p\u00e5 ett specifikt bygge kommer vi att se konsolutmatningen av de kommandon som k\u00f6rdes i processen enligt .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d26dd28708c7fc8a409af4be4d48f502.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>S\u00e5 h\u00e4r ser historiken f\u00f6r v\u00e5r produkt ut. Vi ser att det har funnits lyckade f\u00f6rs\u00f6k. N\u00e4r testerna faller avancerar det inte till n\u00e4sta steg, och koden p\u00e5 staging uppdateras inte.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ee7bd81dc283c7af0c194779d4230780.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vilka uppgifter l\u00f6ste vi p\u00e5 staging n\u00e4r vi implementerade Docker? V\u00e5rt system best\u00e5r av komponenter och vi beh\u00f6vde bara starta om de komponenter som hade uppdaterats i arkivet, snarare \u00e4n hela systemet.<\/p>\n<p><\/p>\n<p>F\u00f6r detta var vi tvungna att separera allt i olika mappar.<\/p>\n<p><\/p>\n<p>Efter att vi gjort detta st\u00f6tte vi p\u00e5 ett problem d\u00e4r Docker-compose skapar ett eget n\u00e4tverksutrymme f\u00f6r varje mapp och inte ser grannkomponenterna.<\/p>\n<p><\/p>\n<p>F\u00f6r att omg\u00e5 detta skapade vi ett n\u00e4tverk i Docker manuellt. I Docker-compose angav vi att anv\u00e4nda detta n\u00e4tverk f\u00f6r projektet.<\/p>\n<p><\/p>\n<p>P\u00e5 s\u00e5 s\u00e4tt ser varje komponent som startar med detta n\u00e4tverk komponenter i andra delar av systemet.<\/p>\n<p><\/p>\n<p>Det n\u00e4stf\u00f6ljande problemet \u00e4r att dela upp staging mellan flera projekt.<\/p>\n<p><\/p>\n<p>Eftersom allt detta ska se bra ut och vara s\u00e5 n\u00e4ra produktion som m\u00f6jligt \u00e4r det bra att anv\u00e4nda port 80 eller 443, som anv\u00e4nds allm\u00e4nt i WEB.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f863cf1833271bf132455a70ad7d2706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hur l\u00f6ste vi detta? Vi tilldelade en Gitlab Runner till alla stora projekt.<\/p>\n<p><\/p>\n<p>Gitlab till\u00e5ter att k\u00f6ra flera distribuerade Gitlab Runners som helt enkelt turas om att slumpm\u00e4ssigt ta alla uppgifter och k\u00f6ra dem.<\/p>\n<p><\/p>\n<p>F\u00f6r att vi inte skulle f\u00e5 kaos begr\u00e4nsade vi gruppen av v\u00e5ra projekt till en Gitlab Runner, som klarar av v\u00e5ra volymer utan problem.<\/p>\n<p><\/p>\n<p>Vi har flyttat nginx-proxy till ett eget startskript och angav n\u00e4tverken f\u00f6r alla projekt d\u00e4r. <\/p>\n<p><\/p>\n<p>V\u00e5rt projekt har ett n\u00e4tverk, och belastningsbalanseraren har flera n\u00e4tverk enligt projektnamn. Den kan proxy vidare baserat p\u00e5 dom\u00e4nnamn.<\/p>\n<p><\/p>\n<p>Vi f\u00e5r f\u00f6rfr\u00e5gningar som kommer in via dom\u00e4nen p\u00e5 port 80 och hanteras i en beh\u00e5llargrupp som \u00e4r kopplad till denna dom\u00e4n.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25c769f029b272a17fd06bbe60cf0ea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vilka andra problem fanns det? Det \u00e4r s\u00e5 att alla beh\u00e5llare som standard k\u00f6rs som anv\u00e4ndaren root. Detta root \u00e4r inte samma som root i systemets v\u00e4rd.<\/p>\n<p><\/p>\n<p>Men om man g\u00e5r in i beh\u00e5llaren s\u00e5 \u00e4r det root, och filen som vi skapar i denna beh\u00e5llare f\u00e5r root-beh\u00f6righet.<\/p>\n<p><\/p>\n<p>Om utvecklaren gick in i beh\u00e5llaren och utf\u00f6rde kommandon som skapade filer, och sedan l\u00e4mnade beh\u00e5llaren, s\u00e5 har han en fil i sin arbetskatalog som han inte har tillg\u00e5ng till.<\/p>\n<p><\/p>\n<p>Hur kan vi l\u00f6sa detta? Vi kan l\u00e4gga till anv\u00e4ndare som kommer att vara i beh\u00e5llaren.<\/p>\n<p><\/p>\n<p>Vilka problem uppstod n\u00e4r vi lade till en anv\u00e4ndare?<\/p>\n<p><\/p>\n<p>N\u00e4r vi skapar en anv\u00e4ndare st\u00e4mmer ofta inte grupp-ID (UID) och anv\u00e4ndar-ID (GID) \u00f6verens.<\/p>\n<p><\/p>\n<p>F\u00f6r att l\u00f6sa detta problem anv\u00e4nder vi anv\u00e4ndare med ID 1000 i beh\u00e5llaren.<\/p>\n<p><\/p>\n<p>I v\u00e5rt fall matchade det med att n\u00e4stan alla utvecklare anv\u00e4nder Ubuntu OS. I Ubuntu har den f\u00f6rsta anv\u00e4ndaren ID 1000.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d4911374e4953fdcd807c387efeafec3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vad har vi f\u00f6r planer?<\/p>\n<p><\/p>\n<p>L\u00e4sa dokumentationen f\u00f6r Docker igen. Projektet utvecklas aktivt och dokumentationen \u00e4ndras. Information som ficks f\u00f6r tv\u00e5 eller tre m\u00e5nader sedan b\u00f6rjar bli gammal. <\/p>\n<p><\/p>\n<p>En del av problemen vi har l\u00f6st \u00e4r sannolikt redan l\u00f6sta med standardverktyg.<\/p>\n<p><\/p>\n<p>Det skulle vara roligt att g\u00e5 vidare och fokusera p\u00e5 orkestrering.<\/p>\n<p><\/p>\n<p>Ett exempel p\u00e5 detta \u00e4r den inbyggda mekanismen i Docker som kallas Docker Swarm, som kommer direkt ur l\u00e5dan. Vi vill kunna k\u00f6ra n\u00e5got i produktion baserat p\u00e5 Docker Swarm-teknologin.<\/p>\n<p><\/p>\n<p>Skapandet av beh\u00e5llare g\u00f6r att det blir besv\u00e4rligt att arbeta med loggar. Just nu \u00e4r loggarna isolerade. De \u00e4r spridda \u00f6ver olika beh\u00e5llare. En av uppgifterna \u00e4r att skapa bekv\u00e4m tillg\u00e5ng till loggar genom ett webgr\u00e4nssnitt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utvecklings- och testprocess med Docker och Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/cff8c72dd8af7de1fa0227601bd1d69c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>K\u00e4lla: <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\/sv\/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=\"sv_SE\" \/>\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\/sv\/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 Utvecklings- och testprocess med Docker och Gitlab CI | ProHoster","description":"Jag f\u00f6resl\u00e5r att ni l\u00e4ser Alexander Sigachevs f\u00f6rel\u00e4sning fr\u00e5n Inventos \"Utvecklings- och testprocess med Docker + Gitlab CI\". De som just b\u00f6rjar implementera utvecklingsprocessen.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/32526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=32526"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/32526\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/24326"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=32526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=32526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=32526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}