{"id":69351,"date":"2020-02-18T14:44:06","date_gmt":"2020-02-18T11:44:06","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker"},"modified":"2020-03-03T16:15:00","modified_gmt":"2020-03-03T13:15:00","slug":"sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","title":{"rendered":"Skapande av CI\/CD-kedja och automatisering av arbete med Docker","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Jag skrev mina f\u00f6rsta webbplatser i slutet av 90-talet. D\u00e5 var det mycket enkelt att f\u00e5 dem att fungera. Det fanns en Apache-server p\u00e5 n\u00e5gon typ av delad hosting, och du kunde logga in p\u00e5 den servern via FTP, genom att skriva n\u00e5got i webbl\u00e4sarens adressf\u00e4lt som <code>ftp:\/\/ftp.example.com<\/code>. Sedan beh\u00f6vde man ange namn och l\u00f6senord och ladda upp filer till servern. Det var andra tider, allt var enklare d\u00e5 \u00e4n nu.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/488668\/\"><img decoding=\"async\" alt=\"Skapande av CI\/CD-kedja och automatisering av arbete med Docker\" src=\"\/wp-content\/uploads\/2020\/02\/0861cdd82770ef4695ffac7a09777c52.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>Under de senaste tv\u00e5 decennierna har mycket f\u00f6r\u00e4ndrats. Webbplatser har blivit mer komplexa och innan de sl\u00e4pps i produktion m\u00e5ste de byggas. En enda server har blivit m\u00e5nga servrar som arbetar bakom lastbalanserare, och anv\u00e4ndningen av versionshanteringssystem har blivit vanligt.<\/p>\n<p>F\u00f6r mitt personliga projekt hade jag en speciell konfiguration. Och jag visste att jag beh\u00f6vde m\u00f6jlighet att distribuera webbplatsen i produktion med endast en \u00e5tg\u00e4rd: att skriva koden till grenen <code>master<\/code> p\u00e5 GitHub. Dessutom visste jag att jag inte ville hantera en stor Kubernetes-kluster, eller anv\u00e4nda Docker Swarm, eller underh\u00e5lla en park av servrar med poddar, agenter och andra komplexiteter f\u00f6r att f\u00e5 mitt lilla webbtill\u00e4mpning att fungera. F\u00f6r att uppn\u00e5 m\u00e5let att f\u00f6renkla arbetet mest m\u00f6jligt beh\u00f6vde jag bekanta mig med CI\/CD.<\/p>\n<p>Om du har ett litet projekt (i v\u00e5rt fall handlar det om ett Node.js-projekt) och vill veta hur man automatiserar distributionen av detta projekt, s\u00e5 att det som lagras i f\u00f6rvaret exakt motsvarar det som fungerar i produktion, s\u00e5 kan denna artikel intressera dig.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>F\u00f6rkrav<\/h2>\n<p>\nDet f\u00f6rv\u00e4ntas att l\u00e4saren av denna artikel har grundl\u00e4ggande kunskaper om att arbeta med kommandoraden och skriva Bash-skript. Dessutom kommer du att beh\u00f6va konton <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">Travis CI<\/a><\/noindex> och <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a><\/noindex>.<\/p>\n<h2>M\u00e5ls\u00e4ttningar<\/h2>\n<p>\nJag kan inte s\u00e4ga att denna artikel utan tvekan kan kallas en \"handledning\". Detta \u00e4r snarare ett dokument d\u00e4r jag ber\u00e4ttar vad jag har l\u00e4rt mig och beskriver den process f\u00f6r testning och distribution av kod i produktion som jag \u00e4r n\u00f6jd med, genomf\u00f6rd i ett automatiserat steg.<\/p>\n<p>S\u00e5 h\u00e4r blev min arbetsprocess till slut.<\/p>\n<p>F\u00f6r koden som skickas till n\u00e5gon gren av f\u00f6rvaret, f\u00f6rutom <code>master<\/code>, utf\u00f6rs f\u00f6ljande \u00e5tg\u00e4rder:<\/p>\n<ul>\n<li>Projektbyggnaden startas p\u00e5 Travis CI.<\/li>\n<li>Alla enhetstest, integrationstester och end-to-end-tester k\u00f6rs.<\/li>\n<\/ul>\n<p>\nEndast f\u00f6r koden som tr\u00e4ffar <code>master<\/code>, utf\u00f6rs f\u00f6ljande:<\/p>\n<ul>\n<li>Allt det som n\u00e4mns ovan, plus\u2026<\/li>\n<li>Byggande av en Docker-image baserat p\u00e5 den aktuella koden, inst\u00e4llningarna och milj\u00f6n.<\/li>\n<li>Publicering av imagen p\u00e5 Docker Hub.<\/li>\n<li>Anslutning till produktionsservern.<\/li>\n<li>Nedladdning av imagen fr\u00e5n Docker Hub till servern.<\/li>\n<li>Stoppa den aktuella containern och starta en ny baserat p\u00e5 den nya imagen.<\/li>\n<\/ul>\n<p>\nOm du inte vet n\u00e5gonting om Docker, images och containrar, oroa dig inte. Jag kommer att ber\u00e4tta allt om det.<\/p>\n<h2>Vad \u00e4r CI\/CD?<\/h2>\n<p>\nF\u00f6rkortningen CI\/CD st\u00e5r f\u00f6r \"continuous integration\/continuous deployment\" \u2014 \"kontinuerlig integration\/kontinuerlig distribution\".<\/p>\n<h3>\u258dKontinuerlig integration<\/h3>\n<p>\nKontinuerlig integration \u00e4r en process d\u00e4r utvecklare g\u00f6r commits till det huvudsakliga k\u00e4llkodsf\u00f6rr\u00e5det f\u00f6r projektet (vanligtvis till grenen <code>master<\/code>). Kvaliteten p\u00e5 koden s\u00e4kerst\u00e4lls genom att automatiserade tester utf\u00f6rs.<\/p>\n<h3>\u258dKontinuerlig distribution<\/h3>\n<p>\nKontinuerlig distribution \u00e4r en frekvent automatiserad distribution av kod till produktion. Den andra delen av f\u00f6rkortningen CI\/CD ibland f\u00f6rklaras som \"continuous delivery\" (\"kontinuerlig leverans\"). Detta \u00e4r i allm\u00e4nhet detsamma som \"kontinuerlig distribution\", men \"kontinuerlig leverans\" inneb\u00e4r behovet av manuell bekr\u00e4ftelse av f\u00f6r\u00e4ndringar innan distributionsprocessen f\u00f6r projektet inleds.<\/p>\n<h2>Komma ig\u00e5ng<\/h2>\n<p>\nApplikationen som jag har l\u00e4rt mig detta p\u00e5 heter <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/taniarascia\/takenote\">TakeNote<\/a><\/noindex>. Detta \u00e4r ett webbprojekt som jag jobbar med, avsett f\u00f6r att ta anteckningar. F\u00f6rst f\u00f6rs\u00f6kte jag g\u00f6ra ett <noindex><a rel=\"nofollow\" href=\"https:\/\/jamstack.org\/\">JAMStack<\/a><\/noindex>-projekt, eller bara en frontend-applikation utan server, f\u00f6r att utnyttja standardfunktionerna f\u00f6r hosting och distribution av projekt som erbjuds av <noindex><a rel=\"nofollow\" href=\"https:\/\/www.netlify.com\/\">Netlify<\/a><\/noindex>. I takt med att komplexiteten i applikationen v\u00e4xte, beh\u00f6vde jag skapa dess serverdel, vilket betydde att jag skulle beh\u00f6va formulera min egen strategi f\u00f6r automatiserad integration och automatiserad distribution av projektet.<\/p>\n<p>I mitt fall representerar applikationen en Express-server som k\u00f6rs i Node.js-milj\u00f6, som betj\u00e4nar en en-sides React-applikation och st\u00f6djer ett skyddat server-API. Denna arkitektur f\u00f6ljer en strategi som man kan hitta i <noindex><a rel=\"nofollow\" href=\"https:\/\/www.taniarascia.com\/full-stack-cookies-localstorage-react-express\/\">denna<\/a><\/noindex> guide f\u00f6r fullstack-autentisering.<\/p>\n<p>Jag r\u00e5dfr\u00e5gade med <noindex><a rel=\"nofollow\" href=\"http:\/\/qualitytesting.tech\/\">annan<\/a><\/noindex>, som \u00e4r expert p\u00e5 automation, och jag fr\u00e5gade honom vad jag beh\u00f6vde g\u00f6ra f\u00f6r att allt skulle fungera som jag ville. Han gav mig en id\u00e9 om hur den automatiserade arbetsprocessen skulle se ut, beskriven i avsnittet \"M\u00e5l\" i den h\u00e4r artikeln. Att jag hade satt s\u00e5dana m\u00e5l betydde att jag beh\u00f6vde f\u00f6rst\u00e5 hur man anv\u00e4nder Docker.<\/p>\n<h2>Docker<\/h2>\n<p>\nDocker \u00e4r ett verktyg som, tack vare containerteknologi, g\u00f6r det enkelt att distribuera applikationer, samt att utf\u00f6ra deras distribution och k\u00f6rning i samma milj\u00f6 \u00e4ven om sj\u00e4lva Docker-plattformen fungerar i olika milj\u00f6er. F\u00f6r att b\u00f6rja beh\u00f6vde jag f\u00e5 tillg\u00e5ng till Docker Command Line Interface (CLI) verktyg. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/install\/\">Instruktionen<\/a><\/noindex> f\u00f6r att installera Docker kan inte kallas s\u00e4rskilt tydlig och l\u00e4ttf\u00f6rst\u00e5elig, men den ger information om att f\u00f6r att g\u00f6ra det f\u00f6rsta steget i installationen m\u00e5ste man ladda ner Docker Desktop (f\u00f6r Mac eller Windows).<\/p>\n<p>Docker Hub \u00e4r ungef\u00e4r detsamma som <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/\">GitHub<\/a><\/noindex> f\u00f6r git-repositorier, eller ett register <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/\">npm<\/a><\/noindex> f\u00f6r JavaScript-paket. Det \u00e4r ett online-repositorium f\u00f6r Docker-bilder. Det \u00e4r just till detta som Docker Desktop ansluter.<\/p>\n<p>S\u00e5, f\u00f6r att b\u00f6rja arbeta med Docker, m\u00e5ste du g\u00f6ra tv\u00e5 saker:<\/p>\n<ul>\n<li>Installera <noindex><a rel=\"nofollow\" href=\"https:\/\/www.docker.com\/get-started\">anv\u00e4ndning av<\/a><\/noindex>.<\/li>\n<li>Registrera dig p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\nEfter det kan du kontrollera att Docker CLI fungerar genom att k\u00f6ra f\u00f6ljande kommando f\u00f6r att kontrollera Docker-versionen:<\/p>\n<pre><code class=\"plaintext\">docker -v<\/code><\/pre>\n<p>\nD\u00e4refter, logga in p\u00e5 Docker Hub genom att ange ditt anv\u00e4ndarnamn och l\u00f6senord n\u00e4r du blir tillfr\u00e5gad:<\/p>\n<pre><code class=\"plaintext\">docker login<\/code><\/pre>\n<p>\nF\u00f6r att anv\u00e4nda Docker m\u00e5ste du f\u00f6rst\u00e5 koncepten av bilder och containrar.<\/p>\n<h3>\u258dBilder<\/h3>\n<p>\nEn bild \u00e4r som en plan som inneh\u00e5ller instruktioner f\u00f6r att bygga en container. Det \u00e4r en of\u00f6r\u00e4ndrad avbildning av filsystemet och applikationsinst\u00e4llningarna. Utvecklare kan enkelt dela bilder.<\/p>\n<pre><code class=\"plaintext\"># \u0412\u044b\u0432\u043e\u0434 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u043e\u0431\u0440\u0430\u0437\u0430\u0445\ndocker images<\/code><\/pre>\n<p>\nDetta kommando kommer att visa en tabell med f\u00f6ljande rubrik:<\/p>\n<pre><code class=\"plaintext\">REPOSITORY     TAG     IMAGE ID     CREATED     SIZE\n---<\/code><\/pre>\n<p>\nD\u00e4refter kommer vi att g\u00e5 igenom n\u00e5gra exempel p\u00e5 kommandon i samma format \u2014 f\u00f6rst kommer kommandot med en kommentar, och sedan ett exempel p\u00e5 vad det kan ge som utdata.<\/p>\n<h3>\u258dContainrar<\/h3>\n<p>\nEn container \u00e4r ett exekverbart paket som inneh\u00e5ller allt som beh\u00f6vs f\u00f6r att k\u00f6ra en applikation. Med denna metod kommer applikationen alltid att fungera p\u00e5 samma s\u00e4tt oavsett infrastruktur: i en isolerad milj\u00f6 och i samma typ av milj\u00f6. Detta handlar om att instanser av samma bild startas i olika milj\u00f6er.<\/p>\n<pre><code class=\"plaintext\"># \u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432\ndocker ps -a\nCONTAINER ID \u00a0 \u00a0 IMAGE     COMMAND \u00a0 \u00a0 CREATED     STATUS     PORTS \u00a0 \u00a0 NAMES\n---<\/code><\/pre>\n<p><\/p>\n<h3>\u258dTaggar<\/h3>\n<p>\nEn tagg \u00e4r en indikation p\u00e5 en specifik version av en bild.<\/p>\n<h3>\u258dKort guide f\u00f6r Docker-kommandon<\/h3>\n<p>\nH\u00e4r \u00e4r en \u00f6versikt \u00f6ver n\u00e5gra av de oftast anv\u00e4nda Docker-kommandona.<\/p>\n<p>Team<\/p>\n<p>Kontext<\/p>\n<p>f\u00f6r konsolen nu:<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/build\/\">docker build<\/a><\/noindex><\/p>\n<p>Typ<\/p>\n<p>Bygga en bild fr\u00e5n Dockerfile<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/tag\/\">docker tag<\/a><\/noindex><\/p>\n<p>Typ<\/p>\n<p>Tagga en bild<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/images\/\">docker images<\/a><\/noindex><\/p>\n<p>Typ<\/p>\n<p>Visa listan \u00f6ver bilder<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/run\/\">docker run<\/a><\/noindex><\/p>\n<p>Container<\/p>\n<p>K\u00f6ra en container baserad p\u00e5 en bild<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/push\/\">docker push<\/a><\/noindex><\/p>\n<p>Typ<\/p>\n<p>Skicka en bild till registret<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/about:blank\">docker pull<\/a><\/noindex><\/p>\n<p>Typ<\/p>\n<p>Ladda ner en bild fr\u00e5n registret<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/ps\/\">docker ps<\/a><\/noindex><\/p>\n<p>Container<\/p>\n<p>Visa listan \u00f6ver containrar<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/system_prune\/\">docker system prune<\/a><\/noindex><\/p>\n<p>Bild\/Container<\/p>\n<p>Ta bort oanv\u00e4nda containrar och bilder<\/p>\n<h3>\u258dDockerfile<\/h3>\n<p>\nJag vet hur man lokalt startar en applikation f\u00f6r produktion. Jag har en Webpack-konfiguration som \u00e4r avsedd f\u00f6r att bygga en f\u00e4rdig React-applikation. Dessutom har jag ett kommando som k\u00f6r en server baserad p\u00e5 Node.js p\u00e5 porten <code>5000<\/code>. S\u00e5 h\u00e4r ser det ut:<\/p>\n<pre><code class=\"plaintext\">npm i          # installera beroenden\nnpm run build  # bygga React-applikationen\nnpm run start  # starta Node-servern<\/code><\/pre>\n<p>\nDet \u00e4r v\u00e4rt att notera att jag inte har n\u00e5got exempelapplikation f\u00f6r detta material. Men h\u00e4r, f\u00f6r experiment, passar vilken enkel Node-applikation som helst.<\/p>\n<p>F\u00f6r att anv\u00e4nda containern beh\u00f6ver du ge instruktioner till Docker. Detta g\u00f6rs genom en fil som kallas <code>Dockerfile<\/code>, som finns i projektets rotmapp. Denna fil verkar i b\u00f6rjan ganska sv\u00e5r att f\u00f6rst\u00e5.<\/p>\n<p>Men inneh\u00e5llet i den beskriver i sj\u00e4lva verket, med speciella kommandon, n\u00e5got som liknar inst\u00e4llning av arbetsmilj\u00f6n. H\u00e4r \u00e4r n\u00e5gra av dessa kommandon:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#from\">FR\u00c5N<\/a><\/noindex> \u2014 Detta kommando startar filen. Det anger den grundbild som containern bygger p\u00e5.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#copy\">COPY<\/a><\/noindex> \u2014 Kopiera filer fr\u00e5n en lokal k\u00e4lla till containern.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#workdir\">WORKDIR<\/a><\/noindex> \u2014 Ange arbetskatalogen f\u00f6r f\u00f6ljande kommandon.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#run\">RUN<\/a><\/noindex> \u2014 K\u00f6ra kommandon.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#expose\">EXPOSE<\/a><\/noindex> \u2014 St\u00e4lla in porten.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#entrypoint\">ENTRYPOINT<\/a><\/noindex> \u2014 Ange kommandot som ska k\u00f6ras.<\/li>\n<\/ul>\n<p>\n<code>Dockerfile<\/code> kan se ut ungef\u00e4r s\u00e5 h\u00e4r:<\/p>\n<pre><code class=\"plaintext\"># \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437\nFROM node:12-alpine\n\n# \u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e app\/\nCOPY . app\/\n\n# \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c app\/ \u0432 \u0440\u043e\u043b\u0438 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438\nWORKDIR app\/\n\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (\u043a\u043e\u043c\u0430\u043d\u0434\u0430 npm ci \u043f\u043e\u0445\u043e\u0436\u0430 npm i, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a)\nRUN npm ci --only-production\n\n# \u0421\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430\nRUN npm run build\n\n# \u041f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u0442\nEXPOSE 5000\n\n# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Node-\u0441\u0435\u0440\u0432\u0435\u0440\nENTRYPOINT npm run start<\/code><\/pre>\n<p>\nBeroende p\u00e5 vilken grundbild du v\u00e4ljer kan det h\u00e4nda att du beh\u00f6ver installera extra beroenden. Vissa grundbilder (till exempel Node Alpine Linux) har skapats f\u00f6r att vara s\u00e5 kompakta som m\u00f6jligt. D\u00e4rf\u00f6r kan det h\u00e4nda att vissa program som du f\u00f6rlitar dig p\u00e5 saknas.<\/p>\n<h3>\u258dByggande, taggning och k\u00f6rning av container<\/h3>\n<p>\nLokal byggnation och k\u00f6rning av container \u00e4r efter att vi har <code>Dockerfile<\/code>, ganska enkla uppgifter. Innan du skickar bilden till Docker Hub m\u00e5ste den testas lokalt.<\/p>\n<h3>\u258dByggnation<\/h3>\n<p>\nF\u00f6rst m\u00e5ste vi bygga <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/build\/\">bild<\/a><\/noindex>, ange ett namn och eventuellt en tagg (om ingen tagg specificeras, kommer systemet automatiskt att tilldela bilden en tagg <code>latest<\/code>).<\/p>\n<pre><code class=\"plaintext\"># \u0421\u0431\u043e\u0440\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u0430\ndocker build -t &lt;image&gt;:&lt;tag&gt; .<\/code><\/pre>\n<p>\nN\u00e4r detta kommando har k\u00f6rts kan du se hur Docker bygger bilden.<\/p>\n<pre><code class=\"plaintext\">Sending build context to Docker daemon \u00a0 2.88MB\nStep 1\/9 : FROM node:12-alpine\n\u00a0---&gt; ...utf\u00f6r byggstegen...\nSuccessfully built 123456789123\nSuccessfully tagged &lt;image&gt;:&lt;tag&gt;<\/code><\/pre>\n<p>\nByggprocessen kan ta ett par minuter \u2013 beroende p\u00e5 hur m\u00e5nga beroenden du har. Efter att byggandet \u00e4r klart kan du k\u00f6ra kommandot <code>docker images<\/code> och titta p\u00e5 beskrivningen av din nya bild.<\/p>\n<pre><code class=\"plaintext\">REPOSITORY\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TAG               IMAGE ID\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CREATED              SIZE\n&lt;image&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 latest            123456789123\u00a0 \u00a0 \u00a0 \u00a0 F\u00f6r ungef\u00e4r en minut sedan   x.xxGB<\/code><\/pre>\n<p><\/p>\n<h3>\u258dK\u00f6rning<\/h3>\n<p>\nBild skapad. Det betyder att vi kan starta en container baserad p\u00e5 den. Eftersom jag vill ha m\u00f6jlighet att n\u00e5 applikationen som k\u00f6rs i containern via adressen <code>localhost:5000<\/code>, har jag i den v\u00e4nstra delen av paret <code>5000:5000<\/code> i n\u00e4sta kommando angivit <code>5000<\/code>. I den h\u00f6gra delen finns porten f\u00f6r containern.<\/p>\n<pre><code class=\"plaintext\"># \u0417\u0430\u043f\u0443\u0441\u043a \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430 5000 \u0438 \u043f\u043e\u0440\u0442\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 5000\ndocker run -p 5000:5000 &lt;image&gt;:&lt;tag&gt;<\/code><\/pre>\n<p>\nNu n\u00e4r containern har skapats och k\u00f6rs kan du anv\u00e4nda kommandot <code>docker ps<\/code> f\u00f6r att f\u00e5 information om denna container (eller s\u00e5 kan du anv\u00e4nda kommandot <code>docker ps -a<\/code>, som visar information om alla containrar, inte bara de som k\u00f6rs).<\/p>\n<pre><code class=\"plaintext\">CONTAINER ID\u00a0 \u00a0 \u00a0 \u00a0 IMAGE               COMMAND\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CREATED              STATUS                  \u00a0 \u00a0 PORTS                    NAMES\n987654321234\u00a0 \u00a0 \u00a0 \u00a0 &lt;image&gt;             &quot;\/bin\/sh -c 'npm run\u2026&quot; \u00a0 6 seconds ago        Up 6 seconds            \u00a0 \u00a0 0.0.0.0:5000-&gt;5000\/tcp   stoic_darwin<\/code><\/pre>\n<p>\nOm du nu g\u00e5r till adressen <code>localhost:5000<\/code> \u2013 kan du se sidan f\u00f6r den k\u00f6rande applikationen, som ser exakt ut som sidan f\u00f6r applikationen som k\u00f6rs i produktionsmilj\u00f6.<\/p>\n<h3>\u258dTilldelning av tagg och publicering<\/h3>\n<p>\nF\u00f6r att anv\u00e4nda ett av de skapade bilderna p\u00e5 produktionsservern beh\u00f6ver vi kunna ladda ner denna bild fr\u00e5n Docker Hub. Det inneb\u00e4r att vi f\u00f6rst m\u00e5ste skapa ett lager p\u00e5 Docker Hub f\u00f6r projektet. D\u00e4refter f\u00e5r vi en plats d\u00e4r vi kan skicka bilden. Bilden m\u00e5ste d\u00f6pas s\u00e5 att dess namn b\u00f6rjar med v\u00e5rt anv\u00e4ndarnamn p\u00e5 Docker Hub. Efter det ska namn p\u00e5 lagret f\u00f6lja. I slutet av namnet kan en valfri tagg placeras. Nedan visas ett exempel p\u00e5 namngivning av bilder enligt detta schema.<\/p>\n<p>Nu kan vi bygga bilden och ge den ett nytt namn och k\u00f6ra kommandot <code>docker push<\/code> f\u00f6r att skicka den till Docker Hub-lagret.<\/p>\n<pre><code class=\"plaintext\">docker build -t \/: .\ndocker tag \/: \/:latest\ndocker push \/:\n\n# I praktiken kan det se ut s\u00e5 h\u00e4r:\ndocker build -t user\/app:v1.0.0 .\ndocker tag user\/app:v1.0.0 user\/app:latest\ndocker push user\/app:v1.0.0<\/code><\/pre>\n<p>\nOm allt g\u00e5r som det ska, kommer bilden att vara tillg\u00e4nglig p\u00e5 Docker Hub och l\u00e4tt kunna laddas ner till servern eller \u00f6verf\u00f6ras till andra utvecklare.<\/p>\n<h2>F\u00f6ljande steg<\/h2>\n<p>\nVid detta stadium har vi verifierat att applikationen, som en Docker-container, fungerar lokalt. Vi har laddat containern p\u00e5 Docker Hub. Allt detta inneb\u00e4r att vi redan har kommit l\u00e5ngt mot v\u00e5rt m\u00e5l. Nu beh\u00f6ver vi l\u00f6sa ytterligare tv\u00e5 fr\u00e5gor:<\/p>\n<ul>\n<li>Inst\u00e4llning av CI-verktyg f\u00f6r testning och distribution av kod.<\/li>\n<li>Inst\u00e4llning av produktionsservern s\u00e5 att den kan ladda ner och k\u00f6ra v\u00e5r kod.<\/li>\n<\/ul>\n<p>\nI v\u00e5rt fall anv\u00e4nds som CI\/CD-l\u00f6sning <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">Travis CI<\/a><\/noindex>. Som server \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex>.<\/p>\n<p>Det \u00e4r v\u00e4rt att notera att det h\u00e4r kan anv\u00e4ndas en annan kombination av tj\u00e4nster. Till exempel kan CircleCI eller Github Actions anv\u00e4ndas ist\u00e4llet f\u00f6r Travis CI. Och ist\u00e4llet f\u00f6r DigitalOcean \u2014 AWS eller Linode.<\/p>\n<p>Vi har beslutat att arbeta med Travis CI, och jag har redan n\u00e5got konfigurerat i den h\u00e4r tj\u00e4nsten. D\u00e4rf\u00f6r kommer jag nu kort att ber\u00e4tta hur man f\u00f6rbereder det f\u00f6r arbete.<\/p>\n<h2>Travis CI<\/h2>\n<p>\nTravis CI \u00e4r ett verktyg f\u00f6r testning och distribution av kod. Jag skulle inte vilja g\u00e5 in p\u00e5 detaljer om hur man konfigurerar Travis CI, eftersom varje projekt \u00e4r unikt och det inte skulle vara s\u00e4rskilt anv\u00e4ndbart. Men jag kommer att ber\u00e4tta om grunderna som g\u00f6r det m\u00f6jligt f\u00f6r dig att b\u00f6rja arbeta om du v\u00e4ljer att anv\u00e4nda Travis CI. Oavsett vad du v\u00e4ljer \u2014 Travis CI, CircleCI, Jenkins eller n\u00e5got annat \u2014 kommer liknande metoder att till\u00e4mpas.<\/p>\n<p>F\u00f6r att b\u00f6rja arbeta med Travis CI, g\u00e5 till <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">projektets webbplats<\/a><\/noindex> och skapa ett konto. Integrera sedan Travis CI med ditt GitHub-konto. Under systeminst\u00e4llningarna kommer du att beh\u00f6va ange det f\u00f6rr\u00e5d som du vill automatisera, och ge \u00e5tkomst till det. (Jag anv\u00e4nder GitHub, men jag \u00e4r s\u00e4ker p\u00e5 att Travis CI kan integreras med BitBucket, GitLab och andra liknande tj\u00e4nster).<\/p>\n<p>Varje g\u00e5ng Travis CI startar ett arbete, startas en server som k\u00f6r de kommandon som anges i konfigurationsfilen, inklusive distribution av aktuella grenar av f\u00f6rr\u00e5det.<\/p>\n<h3>\u258dUppgifts livscykel<\/h3>\n<p>\nKonfigurationsfilen f\u00f6r Travis CI, som kallas <code>.travis.yml<\/code> och som lagras i projektets rotkatalog, st\u00f6der konceptet av h\u00e4ndelser <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.travis-ci.com\/user\/job-lifecycle\/\">f\u00f6r RHEL 6 och 7-distributioner, och f\u00f6r RHEL 8 kommer det att publiceras paketuppdateringar i Application Stream fram till juni 2024.<\/a><\/noindex> f\u00f6r uppgiften. H\u00e4r \u00e4r dessa h\u00e4ndelser, i den ordning de intr\u00e4ffar:<\/p>\n<ul>\n<li><code>apt addons<\/code><\/li>\n<li><code>cache components<\/code><\/li>\n<li><code>before_install<\/code><\/li>\n<li><code>install<\/code><\/li>\n<li><code>before_script<\/code><\/li>\n<li><code>script<\/code><\/li>\n<li><code>before_cache<\/code><\/li>\n<li><code>after_success eller after_failure<\/code><\/li>\n<li><code>before_deploy<\/code><\/li>\n<li><code>deploy<\/code><\/li>\n<li><code>after_deploy<\/code><\/li>\n<li><code>after_script<\/code><\/li>\n<\/ul>\n<p><\/p>\n<h3>\u258dTestning<\/h3>\n<p>\nI konfigurationsfilen kommer jag att st\u00e4lla in en lokal server f\u00f6r Travis CI. Som spr\u00e5k har jag valt Node version 12 och instruerat systemet att installera de beroenden som beh\u00f6vs f\u00f6r att anv\u00e4nda Docker.<\/p>\n<p>Allt som anges i <code>.travis.yml<\/code>, kommer att k\u00f6ras vid alla pull-f\u00f6rfr\u00e5gningar till alla grenar av f\u00f6rr\u00e5det, s\u00e5vida inte annat anges. Detta \u00e4r en anv\u00e4ndbar funktion, eftersom det inneb\u00e4r att vi kan testa all kod som kommer in i f\u00f6rr\u00e5det. Det g\u00f6r att vi kan veta om koden \u00e4r redo att skrivas till grenen <code>master<\/code>, och om den inte kommer att st\u00f6ra byggprocessen av projektet. I denna globala konfiguration installerar jag allt lokalt, k\u00f6r Webpack utvecklarserver i bakgrunden (detta \u00e4r en funktion av min arbetsprocess) och k\u00f6r tester.<\/p>\n<p>Om du vill att det i ditt f\u00f6rr\u00e5d ska visas m\u00e4rken med information om testt\u00e4ckning av koden, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.taniarascia.com\/display-build-status-and-test-coverage\/\">). Ett typiskt exempel p\u00e5 anv\u00e4ndning:<\/a><\/noindex> kan du hitta en kort v\u00e4gledning om anv\u00e4ndning av Jest, Travis CI och Coveralls f\u00f6r att samla in och visa dessa uppgifter.<\/p>\n<p>S\u00e5 h\u00e4r ser inneh\u00e5llet i filen ut <code>.travis.yml<\/code>:<\/p>\n<pre><code class=\"plaintext\"># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u044f\u0437\u044b\u043a\nlanguage: node_js\n\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e Node.js\nnode_js:\n\u00a0\u00a0- '12'\n\nservices:\n\u00a0\u00a0# \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 Docker\n\u00a0\u00a0- docker\n\ninstall:\n\u00a0\u00a0# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\n\u00a0\u00a0- npm ci\n\nbefore_script:\n\u00a0\u00a0# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\n\u00a0\u00a0- npm run dev &amp;\n\nscript:\n\u00a0\u00a0# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b\n\u00a0\u00a0- npm run test<\/code><\/pre>\n<p>\nH\u00e4r slutar de \u00e5tg\u00e4rder som utf\u00f6rs f\u00f6r alla grenar av f\u00f6rr\u00e5det och f\u00f6r pull-f\u00f6rfr\u00e5gningar.<\/p>\n<h3>\u258dDistribution<\/h3>\n<p>\nMed tanke p\u00e5 att alla automatiserade tester har avslutats framg\u00e5ngsrikt, kan vi, vilket inte \u00e4r obligatoriskt, distribuera koden till produktionsservern. Eftersom vi bara vill g\u00f6ra detta f\u00f6r koden fr\u00e5n grenen <code>master<\/code>, vi ger systemet l\u00e4mpliga instruktioner i distributionsinst\u00e4llningarna. Innan du f\u00f6rs\u00f6ker anv\u00e4nda koden som vi kommer att g\u00e5 igenom senare i ditt projekt, vill jag varna dig f\u00f6r att du m\u00e5ste ha ett verkligt skript som anropas f\u00f6r distribution.<\/p>\n<pre><code class=\"plaintext\">deploy:\n  # Bygg Docker-kontainern och skicka den till Docker Hub\n  provider: script\n  script: bash deploy.sh\n  on:\n    branch: master<\/code><\/pre>\n<p>\nDistributionsskriptet l\u00f6ser tv\u00e5 uppgifter:<\/p>\n<ul>\n<li>Bygga, tagga och skicka bilden till Docker Hub med CI-verktyget (i v\u00e5rt fall \u00e4r det Travis CI).<\/li>\n<li>Ladda upp bilden p\u00e5 servern, stoppa den gamla kontainern och starta den nya (i v\u00e5rt fall k\u00f6r servern p\u00e5 plattformen DigitalOcean).<\/li>\n<\/ul>\n<p>\nF\u00f6rst m\u00e5ste du st\u00e4lla in den automatiska byggprocessen, taggning och uppladdning av bilden till Docker Hub. Allt detta liknar det vi redan har gjort manuellt, f\u00f6rutom att vi beh\u00f6ver en strategi f\u00f6r att tilldela bilder unika taggar och automatisera inloggningen. Jag hade problem med vissa detaljer i distributionsskriptet, s\u00e5som taggningsstrategin, inloggningen, SSH-nyckelkodningen och etableringen av SSH-anslutningen. Men lyckligtvis \u00e4r min pojkv\u00e4n mycket bra p\u00e5 bash, precis som p\u00e5 m\u00e5nga andra saker. Han hj\u00e4lpte mig att skriva detta skript.<\/p>\n<p>S\u00e5, den f\u00f6rsta delen av skriptet \u00e4r att skicka bilden till Docker Hub. Det \u00e4r ganska enkelt. Den taggstruktur jag anv\u00e4nde inneb\u00e4r en kombination av git-hash och git-tag, om den existerar. Detta s\u00e4kerst\u00e4ller att en unik tagg skapas och underl\u00e4ttar identifieringen av bygget som den baserades p\u00e5. <code>DOCKER_USERNAME<\/code> och <code>DOCKER_PASSWORD<\/code> \u2014 \u00e4r anv\u00e4ndarspecifika milj\u00f6variabler som kan st\u00e4llas in med hj\u00e4lp av gr\u00e4nssnittet f\u00f6r Travis CI. Travis CI kommer automatiskt att hantera k\u00e4nsliga uppgifter s\u00e5 att de inte hamnar i fel h\u00e4nder.<\/p>\n<p>H\u00e4r \u00e4r den f\u00f6rsta delen av skriptet <code>deploy.sh<\/code>.<\/p>\n<pre><code class=\"plaintext\">#!\/bin\/sh\nset -e # \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a\n\nIMAGE=&quot;&lt;username&gt;\/&lt;repository&gt;&quot; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # \u041e\u0431\u0440\u0430\u0437 Docker\nGIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-\u0445\u044d\u0448 \u0438 \u0442\u0435\u0433\u0438\n\n# \u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u0430\ndocker build -t ${IMAGE}:${GIT_VERSION} .\ndocker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest\n\n# \u0412\u0445\u043e\u0434 \u0432 Docker Hub \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u0430\necho &quot;${DOCKER_PASSWORD}&quot; | docker login -u &quot;${DOCKER_USERNAME}&quot; --password-stdin\ndocker push ${IMAGE}:${GIT_VERSION}<\/code><\/pre>\n<p>\nHur den andra delen av skriptet kommer att se ut beror helt p\u00e5 vilken v\u00e4rd du anv\u00e4nder och hur anslutningen \u00e4r organiserad. I mitt fall, eftersom jag anv\u00e4nder Digital Ocean, anv\u00e4nds kommandon f\u00f6r att ansluta till servern <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/digitalocean\/doctl\">doctl<\/a><\/noindex>. Vid arbete med AWS kommer verktyget <code>aws<\/code>, och s\u00e5 vidare.<\/p>\n<p>Att konfigurera serverns drift var inte s\u00e4rskilt sv\u00e5rt. S\u00e5, jag konfigurerade en droplet baserad p\u00e5 en grundbild. Det \u00e4r v\u00e4rt att n\u00e4mna att det system jag valde kr\u00e4ver en eng\u00e5ngshandinstallation av Docker och en eng\u00e5ngshandstart av Docker. F\u00f6r att installera Docker anv\u00e4nde jag Ubuntu 18.04, s\u00e5 om ni ocks\u00e5 anv\u00e4nder Ubuntu f\u00f6r att g\u00f6ra detsamma kan ni bara f\u00f6lja <noindex><a rel=\"nofollow\" href=\"https:\/\/phoenixnap.com\/kb\/how-to-install-docker-on-ubuntu-18-04\">detta<\/a><\/noindex> den enkla guiden.<\/p>\n<p>Jag pratar inte h\u00e4r om specifika kommandon f\u00f6r tj\u00e4nsten, eftersom detta kan variera kraftigt i olika fall. Jag kommer bara att ge en allm\u00e4n handlingsplan som genomf\u00f6rs efter att man kopplat upp sig via SSH till servern d\u00e4r projektet ska distribueras:<\/p>\n<ul>\n<li>Du beh\u00f6ver hitta den container som f\u00f6r n\u00e4rvarande k\u00f6rs och stoppa den.<\/li>\n<li>Sedan m\u00e5ste du i bakgrunden starta en ny container.<\/li>\n<li>Du kommer att beh\u00f6va st\u00e4lla in den lokala serverporten till v\u00e4rdet <code>80<\/code> \u2014 detta kommer att g\u00f6ra att du kan komma \u00e5t webbplatsen p\u00e5 en adress av typen <code>example.com<\/code>, utan att ange port, ist\u00e4llet f\u00f6r att anv\u00e4nda en adress som liknar <code>example.com:5000<\/code>.<\/li>\n<li>Och slutligen m\u00e5ste du ta bort alla gamla containrar och bilder.<\/li>\n<\/ul>\n<p>\nH\u00e4r \u00e4r forts\u00e4ttningen p\u00e5 skriptet.<\/p>\n<pre><code class=\"plaintext\"># \u041d\u0430\u0439\u0442\u0438 ID \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\nCONTAINER_ID=$(docker ps | grep takenote | cut -d&quot; &quot; -f1)\n\n# \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439, \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443\ndocker stop ${CONTAINER_ID}\ndocker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}\ndocker system prune -a -f<\/code><\/pre>\n<p><\/p>\n<h2>N\u00e5gra saker att vara medveten om<\/h2>\n<p>\nKanske, n\u00e4r du kopplar upp dig p\u00e5 servern via SSH fr\u00e5n Travis CI, kommer du att se en varning som hindrar installationen fr\u00e5n att forts\u00e4tta, eftersom systemet kommer att v\u00e4nta p\u00e5 anv\u00e4ndarens respons.<\/p>\n<pre><code class=\"plaintext\">Autenticiteten av v\u00e4rden '&lt;hostname&gt; (&lt;IP address&gt;)' kan inte fastst\u00e4llas.\nRSA nyckelfingeravtryck \u00e4r &lt;key fingerprint&gt;.\n\u00c4r du s\u00e4ker p\u00e5 att du vill forts\u00e4tta ansluta (ja\/nej)?<\/code><\/pre>\n<p>\nJag fick veta att str\u00e4ngnyckeln kan kodas i base64 f\u00f6r att bevara den i ett format som \u00e4r enklare och s\u00e4krare att arbeta med. Vid installationsstadiet kan den offentliga nyckeln dekodas och skrivas till filen <code>known_hosts<\/code> f\u00f6r att bli av med det tidigare beskrivna felet.<\/p>\n<pre><code class=\"plaintext\">echo &lt;public key&gt; | base64 # utdata &lt;offentlig nyckel, kodad i base64&gt;<\/code><\/pre>\n<p>\nI praktiken kan detta kommando se ut s\u00e5 h\u00e4r:<\/p>\n<pre><code class=\"plaintext\">echo &quot;123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom\/BWDSU\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\nPbv7kOdJ\/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK\/7XA\nt3FaoJoAsncM1Q9x5+3V0Ww68\/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw\/Pb0rwert\/En\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z\/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\nNrRFi9wrf+M7Q== you@example.com&quot; | base64<\/code><\/pre>\n<p>\nOch h\u00e4r \u00e4r hur den ser ut \u2014 en str\u00e4ng i base64-kodning:<\/p>\n<pre><code class=\"plaintext\">MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==<\/code><\/pre>\n<p>\nH\u00e4r \u00e4r kommandot som n\u00e4mndes ovan<\/p>\n<pre><code class=\"plaintext\">install:\n  - echo  | base64 -d &gt;&gt; $HOME\/.ssh\/known_hosts<\/code><\/pre>\n<p>\nSamma metod kan anv\u00e4ndas med den privata nyckeln vid anslutning, eftersom du kanske beh\u00f6ver den privata nyckeln f\u00f6r att f\u00e5 \u00e5tkomst till servern. N\u00e4r du arbetar med nyckeln beh\u00f6ver du bara se till att den lagras s\u00e4kert i en milj\u00f6variabel f\u00f6r Travis CI, och att den inte skrivs ut n\u00e5gonstans.<\/p>\n<p>En annan sak att t\u00e4nka p\u00e5 \u00e4r att du kan beh\u00f6va k\u00f6ra hela distributionsskriptet som en enda rad, till exempel \u2014 med hj\u00e4lp av <code>doctl<\/code>. Detta kan kr\u00e4va en del extra anstr\u00e4ngningar.<\/p>\n<pre><code class=\"plaintext\">doctl compute ssh &lt;droplet&gt; --ssh-command &quot;\u0432\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u0437\u0434\u0435\u0441\u044c &amp;&amp; \u0437\u0434\u0435\u0441\u044c&quot;<\/code><\/pre>\n<p><\/p>\n<h2>TLS\/SSL och lastbalansering<\/h2>\n<p>\nEfter att jag gjort allt som n\u00e4mndes ovan, blev den sista fr\u00e5gan jag st\u00e4llde mig att servern inte hade SSL. Eftersom jag anv\u00e4nder en Node.js-server, f\u00f6r att f\u00e5 detta att fungera <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-secure-a-containerized-node-js-application-with-nginx-let-s-encrypt-and-docker-compose\">fungera<\/a><\/noindex> beh\u00f6vs en Nginx backproxy och Let\u2019s Encrypt, vilket kr\u00e4ver en del arbete.<\/p>\n<p>Jag ville verkligen inte g\u00f6ra all denna SSL-konfiguration manuellt, s\u00e5 jag skapade helt enkelt en lastbalanserare och registrerade dess information i DNS. I fallet med DigitalOcean, till exempel, \u00e4r det en enkel, gratis och snabb procedur att skapa ett sj\u00e4lvsignerat certifikat som uppdateras automatiskt p\u00e5 lastbalanseraren. Denna metod har ocks\u00e5 den extra f\u00f6rdelen att det enkelt till\u00e5ter att st\u00e4lla in SSL p\u00e5 flera servrar som arbetar bakom lastbalanseraren. Det inneb\u00e4r att servrarna sj\u00e4lva inte beh\u00f6ver \"t\u00e4nka\" p\u00e5 SSL, men kan anv\u00e4nda porten som vanligt. <code>80<\/code>S\u00e5 att konfigurera SSL p\u00e5 lastbalanseraren \u00e4r mycket enklare och bekv\u00e4mare \u00e4n alternativa metoder f\u00f6r att st\u00e4lla in SSL.<\/p>\n<p>Nu kan vi st\u00e4nga alla portar p\u00e5 servern som accepterar inkommande anslutningar \u2014 f\u00f6rutom porten <code>80<\/code>, som anv\u00e4nds f\u00f6r kommunikation med lastbalanseraren, och porten <code>22<\/code> f\u00f6r SSH. Som ett resultat kommer ett direktf\u00f6rs\u00f6k att kontakta servern via andra portar \u00e4n dessa tv\u00e5 att misslyckas.<\/p>\n<h2>Sammanfattning<\/h2>\n<p>\nEfter att jag gjorde allt som jag n\u00e4mner i detta material var jag inte l\u00e4ngre r\u00e4dd f\u00f6r plattformen Docker eller koncepten kring automatiserade CI\/CD-processer. Jag lyckades st\u00e4lla in en kontinuerlig integrationskedja d\u00e4r kodtestning sker innan den n\u00e5r produktion och kod automatiskt distribueras p\u00e5 servern. Allt detta \u00e4r fortfarande ganska nytt f\u00f6r mig, och jag \u00e4r s\u00e4ker p\u00e5 att det finns s\u00e4tt att f\u00f6rb\u00e4ttra min automatiserade arbetsprocess och g\u00f6ra den effektivare. S\u00e5 om du har n\u00e5gra id\u00e9er i det avseendet \u2014 l\u00e5t mig veta. <noindex><a rel=\"nofollow\" href=\"mailto:hello@taniarascia.com\">jag<\/a><\/noindex> Jag hoppas att denna artikel har hj\u00e4lpt dig i dina sysslor. Jag vill tro att genom att l\u00e4sa den har du l\u00e4rt dig lika mycket som jag gjorde medan jag utforskade allt som jag talade om h\u00e4r.<\/p>\n<p><b>P.S.<\/b> I v\u00e5r <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/marketplace#order\">marknadsplats<\/a><\/noindex> finns en bild <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/marketplace\/docker#advantages\">Docker<\/a><\/noindex>, som installeras med ett klick. Du kan kontrollera hur containrarna fungerar p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/\">VPS<\/a><\/noindex>. Alla nya kunder f\u00e5r 3 dagar gratis f\u00f6r testning.<\/p>\n<p><b>K\u00e4ra l\u00e4sare!<\/b> Anv\u00e4nder du CI\/CD-teknologier i dina projekt?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" alt=\"Skapande av CI\/CD-kedja och automatisering av arbete med Docker\" src=\"\/wp-content\/uploads\/2020\/02\/3fbfa90ea56a3d9b6b89ba945eb94570.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>K\u00e4lla: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/488668\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u0411\u044b\u043b Apache-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u0431\u0449\u0435\u043c \u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0435, \u043d\u0430 \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0439\u0442\u0438 \u043f\u043e FTP, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u043d\u0435\u0447\u0442\u043e \u0432\u0440\u043e\u0434\u0435 ftp:\/\/ftp.example.com. \u041f\u043e\u0442\u043e\u043c \u043d\u0430\u0434\u043e \u0431\u044b\u043b\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0438\u043c\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u0414\u0440\u0443\u0433\u0438\u0435 \u0431\u044b\u043b\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0430, \u0432\u0441\u0451 \u0442\u043e\u0433\u0434\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":69352,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-69351","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=\"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.\" \/>\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\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker\" \/>\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\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CI\/CD-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Docker | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker\" \/>\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=\"2020-02-18T11:44:06+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:15:00+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\udd47Skapande av CI\/CD-kedja och automatisering av arbete med Docker | ProHoster","description":"Jag skrev mina f\u00f6rsta hemsidor i slutet av 90-talet. D\u00e5 var det v\u00e4ldigt enkelt att f\u00e5 dem att fungera.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","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\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CI\/CD-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Docker | ProHoster","og:description":"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","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":"2020-02-18T11:44:06+00:00","article:modified_time":"2020-03-03T13:15:00+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"69351","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:24:45","updated":"2026-08-11 12:50: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\/69351","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=69351"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/69351\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/69352"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=69351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=69351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=69351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}