{"id":81600,"date":"2020-05-15T01:42:41","date_gmt":"2020-05-14T23:42:41","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund"},"modified":"2020-05-15T01:42:41","modified_gmt":"2020-05-14T23:42:41","slug":"neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Innan en funktion g\u00e5r live, m\u00e5ste den i v\u00e5r tid av komplexa orkestratorer och CI\/CD genomg\u00e5 en l\u00e5ng v\u00e4g fr\u00e5n commit till tester och leverans. Tidigare kunde man bara ladda upp nya filer via FTP (det \u00e4r inte s\u00e5 n\u00e5gon g\u00f6r l\u00e4ngre, eller hur?), och processen f\u00f6r \"deployment\" tog sekunder. Nu m\u00e5ste man skapa en merge request och v\u00e4nta en betydande tid p\u00e5 att funktionen ska n\u00e5 anv\u00e4ndarna.<\/p>\n<p><\/p>\n<p>En del av denna v\u00e4g \u00e4r att bygga Docker-bilder. Ibland tar byggandet minuter, ibland \u2013 tiotals minuter, vilket \u00e4r sv\u00e5rt att kalla normalt. I den h\u00e4r artikeln kommer vi att ta ett enkelt program, packa det i en bild, till\u00e4mpa n\u00e5gra metoder f\u00f6r att snabba upp byggnaden och g\u00e5 igenom detaljerna f\u00f6r dessa metoder.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/7d4775ca1ac64735dfcaba205416da50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Vi har en ganska bra erfarenhet av att skapa och underh\u00e5lla nyhetssajter: <noindex><a rel=\"nofollow\" href=\"https:\/\/tass.ru\/\">TASS<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/thebell.io\/\">The Bell<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/novayagazeta.ru\/\">\"Nya tidningen\"<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>\u2026 F\u00f6r inte s\u00e5 l\u00e4nge sedan ut\u00f6kade vi v\u00e5r portf\u00f6lj genom att lansera sajten <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>. Och medan vi snabbt finjusterade nya funktioner och fixade gamla buggar blev den l\u00e5ngsamma deploymenten ett stort problem.<\/p>\n<p><\/p>\n<p>Vi g\u00f6r deployment p\u00e5 GitLab. Vi bygger bilder, pushar till GitLab Registry och distribuerar till produktion. Det som tar l\u00e4ngst tid i den h\u00e4r listan \u00e4r byggandet av bilder. Som exempel: utan optimering tog varje backend-bygge 14 minuter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Till slut blev det uppenbart att vi inte kunde forts\u00e4tta s\u00e5 h\u00e4r, och vi satte oss ned f\u00f6r att f\u00f6rst\u00e5 varf\u00f6r bilderna tog s\u00e5 l\u00e5ng tid att bygga. Vi lyckades i slut\u00e4ndan minska byggtiden till 30 sekunder!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>F\u00f6r denna artikel, f\u00f6r att inte binda oss till Reminder&#8217;a, l\u00e5t oss titta p\u00e5 ett exempel p\u00e5 hur man bygger en tom applikation i Angular. S\u00e5, l\u00e5t oss skapa v\u00e5r applikation:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>Vi l\u00e4gger till PWA (vi \u00e4r ju progressiva):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>Medan en miljon npm-paket laddas ner, l\u00e5t oss ta en titt p\u00e5 hur en docker-bild \u00e4r uppbyggd. Docker ger m\u00f6jlighet att paketera applikationer och k\u00f6ra dem i en isolerad milj\u00f6 som kallas container. Tack vare isoleringen kan m\u00e5nga containrar k\u00f6ras samtidigt p\u00e5 en och samma server. Containrar \u00e4r betydligt l\u00e4ttare \u00e4n virtuella maskiner eftersom de k\u00f6rs direkt p\u00e5 systemets k\u00e4rna. F\u00f6r att k\u00f6ra en container med v\u00e5r applikation beh\u00f6ver vi f\u00f6rst skapa en bild d\u00e4r vi packar allt som beh\u00f6vs f\u00f6r att v\u00e5r applikation ska fungera. I princip \u00e4r en bild en avbildning av filsystemet. L\u00e5t oss ta ett exempel p\u00e5 Dockerfile:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2\nWORKDIR \/app\nCOPY . .\nRUN npm ci\nRUN npm run build --prod<\/code><\/pre>\n<p><\/p>\n<p>Dockerfile \u00e4r en upps\u00e4ttning instruktioner; n\u00e4r varje instruktion utf\u00f6rs kommer Docker att spara \u00e4ndringarna i filsystemet och applicera dem p\u00e5 f\u00f6reg\u00e5ende lager. Varje kommando skapar sitt eget lager. Den f\u00e4rdiga bilden \u00e4r en sammanst\u00e4llning av dessa lager.<\/p>\n<p><\/p>\n<p>Det \u00e4r viktigt att veta: varje lager kan cachas av Docker. Om ingenting har \u00e4ndrats sedan den senaste byggprocessen, kommer Docker att ta det redan existerande lagret ist\u00e4llet f\u00f6r att utf\u00f6ra kommandot. Eftersom den st\u00f6rsta hastighetsvinsten i byggprocessen kommer att ske genom anv\u00e4ndning av cache, kommer vi att fokusera p\u00e5 byggtiden f\u00f6r att m\u00e4ta detta med caching. S\u00e5, steg f\u00f6r steg:<\/p>\n<p><\/p>\n<ol>\n<li>Vi tar bort bilder lokalt s\u00e5 att tidigare k\u00f6rningar inte p\u00e5verkar testet.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>Vi k\u00f6r bygget f\u00f6rsta g\u00e5ngen.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>Vi \u00e4ndrar filen src\/index.html \u2014 simulerar programmerarens arbete.<\/li>\n<li>Vi k\u00f6r bygget en andra g\u00e5ng.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Om milj\u00f6n f\u00f6r byggandet av bilder \u00e4r korrekt inst\u00e4lld (vilket beskrivs lite l\u00e4ngre ner), kommer Docker vid byggstart att ha en m\u00e4ngd cachelagrade objekt. V\u00e5rt m\u00e5l \u00e4r att l\u00e4ra oss att anv\u00e4nda cachen s\u00e5 att byggprocessen g\u00e5r s\u00e5 snabbt som m\u00f6jligt. Eftersom vi antar att byggprocessen utan cache bara k\u00f6rs en g\u00e5ng \u2014 den allra f\u00f6rsta \u2014 kan vi bortse fr\u00e5n hur l\u00e5ngsam den f\u00f6rsta k\u00f6rningen var. I testerna \u00e4r den andra k\u00f6rningen den mest relevanta, n\u00e4r cacherna redan \u00e4r uppv\u00e4rmda och vi \u00e4r redo att baka v\u00e5r kaka. Trots detta kommer vissa tips ocks\u00e5 p\u00e5verka den f\u00f6rsta byggprocessen.<\/p>\n<p><\/p>\n<p>Vi l\u00e4gger Dockerfile som beskrivs ovan i projektmappen och k\u00f6r bygget. Alla angivna listingar \u00e4r f\u00f6rkortade f\u00f6r att underl\u00e4tta l\u00e4sningen.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 409MB\nStep 1\/5 : FROM node:12.16.2\nStatus: Downloaded newer image for node:12.16.2\nStep 2\/5 : WORKDIR \/app\nStep 3\/5 : COPY . .\nStep 4\/5 : RUN npm ci\nadded 1357 packages in 22.47s\nStep 5\/5 : RUN npm run build --prod\nDate: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Time: 37581ms\nSuccessfully built c8c279335f46\nSuccessfully tagged app:latest\n\nreal 5m4.541s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>Vi \u00e4ndrar inneh\u00e5llet i src\/index.html och k\u00f6r det en andra g\u00e5ng.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 409MB\nStep 1\/5 : FROM node:12.16.2\nStep 2\/5 : WORKDIR \/app\n ---&gt; Using cache\nStep 3\/5 : COPY . .\nStep 4\/5 : RUN npm ci\nadded 1357 packages in 22.47s\nStep 5\/5 : RUN npm run build --prod\nDate: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - Time: 37902ms\nSuccessfully built 79f335df92d3\nSuccessfully tagged app:latest\n\nreal 3m33.262s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>F\u00f6r att se om vi har f\u00e5tt en bild, k\u00f6r vi f\u00f6ljande kommando <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   F\u00f6r ungef\u00e4r en minut sedan   1.74GB<\/code><\/pre>\n<p><\/p>\n<p>Innan bygget tar Docker alla filer i den aktuella kontexten och skickar dem till sin daemon. <code>Skickar byggets kontext till Docker-demonen 409MB.<\/code>. Kontexten f\u00f6r bygget anges som det sista argumentet i build-kommandot. I v\u00e5rt fall \u00e4r det den aktuella katalogen \u2013 \u00ab.\u00bb, \u2013 och Docker tar med allt vi har i den h\u00e4r mappen. 409 megabyte \u00e4r mycket: l\u00e5t oss t\u00e4nka p\u00e5 hur vi kan \u00e5tg\u00e4rda detta.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">Minska kontexten.<\/h2>\n<p><\/p>\n<p>F\u00f6r att minska kontexten finns det tv\u00e5 alternativ. Antingen l\u00e4gger vi alla filer som beh\u00f6vs f\u00f6r bygget i en separat mapp och anger f\u00f6r Docker att kontexten \u00e4r just den mappen. Detta kanske inte alltid \u00e4r bekv\u00e4mt, s\u00e5 det finns m\u00f6jlighet att ange undantag: vad som inte ska tas med i kontexten. F\u00f6r detta l\u00e4gger vi till en .dockerignore-fil i projektet och anger vad som inte beh\u00f6vs f\u00f6r bygget:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>och k\u00f6r bygget igen:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSkickar byggets kontext till Docker-demonen 607.2kB\nSteg 1\/5 : FR\u00c5N node:12.16.2\nSteg 2\/5 : WORKDIR \/app\n ---&gt; Anv\u00e4nder cache\nSteg 3\/5 : COPY . .\nSteg 4\/5 : RUN npm ci\nlade till 1357 paket p\u00e5 22.47s\nSteg 5\/5 : RUN npm run build --prod\nDatum: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Tid: 37313ms\nByggd framg\u00e5ngsrikt 4942f010792a\nM\u00e4rkt app:latest\n\nreell 1m47.763s\nanv\u00e4ndare 0m0.000s\nsystem 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607.2 kB \u2013 mycket b\u00e4ttre \u00e4n 409 MB. Och dessutom har vi minskat bildens storlek fr\u00e5n 1.74 till 1.38 GB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED         SIZE\napp          latest   4942f010792a   3 minuter sedan   1.38GB<\/code><\/pre>\n<p><\/p>\n<p>L\u00e5t oss f\u00f6rs\u00f6ka minska bildens storlek \u00e4nnu mer.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Anv\u00e4nd Alpine.<\/h2>\n<p><\/p>\n<p>\u00c4nnu ett s\u00e4tt att spara p\u00e5 bildens storlek \u00e4r att anv\u00e4nda en liten f\u00f6r\u00e4ldrabild. F\u00f6r\u00e4ldrabilden \u00e4r bilden som v\u00e5r bild byggs p\u00e5. Det undre lagret anges med kommandot <code>FR\u00c5N<\/code> i Dockerfile. I v\u00e5rt fall anv\u00e4nder vi en bild baserad p\u00e5 Ubuntu, som redan har nodejs installerat. Och den v\u00e4ger \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c 17 minuter sedan 916MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 n\u00e4stan en gigabyte. Vi kan kraftigt minska storleken genom att anv\u00e4nda en bild baserad p\u00e5 Alpine Linux. Alpine \u00e4r en mycket liten Linux. Docker-bilden f\u00f6r nodejs baserat p\u00e5 Alpine v\u00e4ger endast 88.5 MB. S\u00e5 l\u00e5t oss ers\u00e4tta v\u00e5r feta f\u00f6r\u00e4ldrabild:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FR\u00c5N node:12.16.2-alpine3.11\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++\nWORKDIR \/app\nCOPY . .\nRUN npm ci\nRUN npm run build --prod<\/code><\/pre>\n<p><\/p>\n<p>Vi var tvungna att installera n\u00e5gra verktyg som beh\u00f6vs f\u00f6r att bygga applikationen. Ja, Angular byggs inte utan Python \u00af(\u00b0_o)\/\u00af<\/p>\n<p><\/p>\n<p>Men storleken p\u00e5 bilden minskade med 150 MB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   aa031edc315a   22 minuter sedan   761MB<\/code><\/pre>\n<p><\/p>\n<p>L\u00e5t oss g\u00e5 \u00e4nnu l\u00e4ngre.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">Multi-stage build.<\/h2>\n<p><\/p>\n<p>Inte allt som finns i bilden beh\u00f6ver vi i produktionen.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker run app ls -lah\ntotal 576K\ndrwxr-xr-x 1 root root 4.0K Apr 16 19:54 .\ndrwxr-xr-x 1 root root 4.0K Apr 16 20:00 ..\n-rwxr-xr-x 1 root root 19 Apr 17 2020 .dockerignore\n-rwxr-xr-x 1 root root 246 Apr 17 2020 .editorconfig\n-rwxr-xr-x 1 root root 631 Apr 17 2020 .gitignore\n-rwxr-xr-x 1 root root 181 Apr 17 2020 Dockerfile\n-rwxr-xr-x 1 root root 1020 Apr 17 2020 README.md\n-rwxr-xr-x 1 root root 3.6K Apr 17 2020 angular.json\n-rwxr-xr-x 1 root root 429 Apr 17 2020 browserslist\ndrwxr-xr-x 3 root root 4.0K Apr 16 19:54 dist\ndrwxr-xr-x 3 root root 4.0K Apr 17 2020 e2e\n-rwxr-xr-x 1 root root 1015 Apr 17 2020 karma.conf.js\n-rwxr-xr-x 1 root root 620 Apr 17 2020 ngsw-config.json\ndrwxr-xr-x 1 root root 4.0K Apr 16 19:54 node_modules\n-rwxr-xr-x 1 root root 494.9K Apr 17 2020 package-lock.json\n-rwxr-xr-x 1 root root 1.3K Apr 17 2020 package.json\ndrwxr-xr-x 5 root root 4.0K Apr 17 2020 src\n-rwxr-xr-x 1 root root 210 Apr 17 2020 tsconfig.app.json\n-rwxr-xr-x 1 root root 489 Apr 17 2020 tsconfig.json\n-rwxr-xr-x 1 root root 270 Apr 17 2020 tsconfig.spec.json\n-rwxr-xr-x 1 root root 1.9K Apr 17 2020 tslint.json<\/code><\/pre>\n<p><\/p>\n<p>Med hj\u00e4lp av <code>docker run app ls -lah<\/code> Vi har startat en container baserad p\u00e5 v\u00e5r bild <code>app<\/code> och k\u00f6rde ett kommando i den <code>ls -lah<\/code>, efter vilket containern avslutade sin drift.<\/p>\n<p><\/p>\n<p>I produktion beh\u00f6ver vi bara mappen <code>dist<\/code>. Samtidigt m\u00e5ste vi p\u00e5 n\u00e5got s\u00e4tt ge ut filerna. Vi kan starta en HTTP-server med nodejs. Men vi g\u00f6r det enklare. Gissa ett ryskt ord som inneh\u00e5ller fyra bokst\u00e4ver \u201e\u044b\u201c. R\u00e4tt! \u042b\u043d\u0436\u044b\u043d\u044b\u043a\u0441\u044b. Vi tar en bild med nginx, l\u00e4gger in mappen <code>dist<\/code> och en liten konfiguration:<\/p>\n<p><\/p>\n<pre><code class=\"nginx\">server {\n    listen 80 default_server;\n    server_name localhost;\n    charset utf-8;\n    root \/app\/dist;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.html;\n    }\n}<\/code><\/pre>\n<p><\/p>\n<p>Detta kommer att hj\u00e4lpa oss att genomf\u00f6ra en multi-stage build. Vi \u00e4ndrar v\u00e5r Dockerfile:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11 as builder\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++\nWORKDIR \/app\nCOPY . .\nRUN npm ci\nRUN npm run build --prod\n\nFROM nginx:1.17.10-alpine\nRUN rm \/etc\/nginx\/conf.d\/default.conf\nCOPY nginx\/static.conf \/etc\/nginx\/conf.d\nCOPY --from=builder \/app\/dist\/app .<\/code><\/pre>\n<p><\/p>\n<p>Nu har vi tv\u00e5 instruktioner <code>FR\u00c5N<\/code> i Dockerfile, var och en av dem k\u00f6r sin egen byggfas. Den f\u00f6rsta har vi kallat <code>F\u00f6r Raspberry Pi 3 med un-def-k\u00e4rnor, lts, mp, m\u00e5ste en av ljudkortarna (h\u00f6rlurar eller HDMI) st\u00e4ngas av n\u00e4r pulseaudio anv\u00e4nds, annars upplevs l\u00e5ngsam avst\u00e4ngning av datorn och ljud kan f\u00f6rsvinna p\u00e5 grund av fryst pulseaudio.<\/code>, men fr\u00e5n den sista FROM kommer v\u00e5rt slutgiltiga bild att f\u00f6rberedas. Som sista steg kopierar vi artefakten fr\u00e5n v\u00e5r tidigare byggfas till den slutgiltiga bilden med nginx. Storleken p\u00e5 bilden har minskat betydligt:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   2c6c5da07802   29 minuter sedan   36MB<\/code><\/pre>\n<p><\/p>\n<p>L\u00e5t oss k\u00f6ra en container med v\u00e5r bild och se till att allt fungerar:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>Med alternativet -p8080:80 har vi vidarebefordrat port 8080 p\u00e5 v\u00e5r v\u00e4rdmaskin till port 80 inuti containern, d\u00e4r nginx k\u00f6rs. \u00d6ppna i webbl\u00e4saren <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> och se v\u00e5r applikation. Allt fungerar!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Att minska bildens storlek fr\u00e5n 1,74 GB till 36 MB minskar avsev\u00e4rt tiden f\u00f6r att leverera din applikation till produktion. Men l\u00e5t oss \u00e5terv\u00e4nda till byggtiden.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 608.8kB\nStep 1\/11 : FROM node:12.16.2-alpine3.11 as builder\nStep 2\/11 : RUN apk --no-cache --update --virtual build-dependencies add python make g++\n---&gt; Using cache\nStep 3\/11 : WORKDIR \/app\n---&gt; Using cache\nStep 4\/11 : COPY . .\nStep 5\/11 : RUN npm ci\nadded 1357 packages in 47.338s\nStep 6\/11 : RUN npm run build --prod\nDate: 2020-04-16T21:16:03.899Z - Hash: fffa0fddaa3425c55dd3 - Time: 39948ms\n---&gt; 27f1479221e4\nStep 7\/11 : FROM nginx:stable-alpine\nStep 8\/11 : WORKDIR \/app\n---&gt; Using cache\nStep 9\/11 : RUN rm \/etc\/nginx\/conf.d\/default.conf\n---&gt; Using cache\nStep 10\/11 : COPY nginx\/static.conf \/etc\/nginx\/conf.d\n---&gt; Using cache\nStep 11\/11 : COPY --from=builder \/app\/dist\/app .\nSuccessfully built d201471c91ad\nSuccessfully tagged app:latest\n\nreal 2m17.700s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<h2 id=\"menyaem-poryadok-sloyov\">Vi \u00e4ndrar ordningen p\u00e5 lagren<\/h2>\n<p><\/p>\n<p>De f\u00f6rsta tre stegen har cache-lagts (tips <code>Using cache<\/code>). I det fj\u00e4rde steget kopieras alla projektfiler och i det femte steget installeras beroenden <code>RUN npm ci<\/code> \u2014 hela 47.338s. Varf\u00f6r installera beroenden varje g\u00e5ng, om de \u00e4ndras s\u00e5 s\u00e4llan? L\u00e5t oss g\u00e5 igenom varf\u00f6r de inte cachades. Saken \u00e4r den att Docker kontrollerar lager f\u00f6r lager, om kommandot och filer kopplade till det har \u00e4ndrats. I det fj\u00e4rde steget kopierar vi alla filer fr\u00e5n v\u00e5rt projekt, och bland dem finns det givetvis \u00e4ndringar, d\u00e4rf\u00f6r att Docker inte bara inte tar det h\u00e4r lagret fr\u00e5n cachen, utan \u00e4ven alla efterf\u00f6ljande! L\u00e5t oss g\u00f6ra n\u00e5gra sm\u00e5 \u00e4ndringar i Dockerfile.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11 as builder\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++\nWORKDIR \/app\nCOPY package*.json .\/\nRUN npm ci\nCOPY . .\nRUN npm run build --prod\n\nFROM nginx:1.17.10-alpine\nRUN rm \/etc\/nginx\/conf.d\/default.conf\nCOPY nginx\/static.conf \/etc\/nginx\/conf.d\nCOPY --from=builder \/app\/dist\/app .<\/code><\/pre>\n<p><\/p>\n<p>F\u00f6rst kopieras package.json och package-lock.json, sedan installeras beroenden, och f\u00f6rst efter det kopieras hela projektet. Resultatet:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 608.8kB\nStep 1\/12 : FROM node:12.16.2-alpine3.11 as builder\nStep 2\/12 : RUN apk --no-cache --update --virtual build-dependencies add python make g++\n ---&gt; Using cache\nStep 3\/12 : WORKDIR \/app\n ---&gt; Using cache\nStep 4\/12 : COPY package*.json .\/\n ---&gt; Using cache\nStep 5\/12 : RUN npm ci\n ---&gt; Using cache\nStep 6\/12 : COPY . .\nStep 7\/12 : RUN npm run build --prod\nDate: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Time: 38287ms\n ---&gt; 1b9448c73558\nStep 8\/12 : FROM nginx:stable-alpine\nStep 9\/12 : WORKDIR \/app\n ---&gt; Using cache\nStep 10\/12 : RUN rm \/etc\/nginx\/conf.d\/default.conf\n ---&gt; Using cache\nStep 11\/12 : COPY nginx\/static.conf \/etc\/nginx\/conf.d\n ---&gt; Using cache\nStep 12\/12 : COPY --from=builder \/app\/dist\/app .\nSuccessfully built a44dd7c217c3\nSuccessfully tagged app:latest\n\nreal 0m46.497s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>46 sekunder ist\u00e4llet f\u00f6r 3 minuter \u2014 mycket b\u00e4ttre! Viktigt \u00e4r den korrekta ordningen p\u00e5 lagren: f\u00f6rst kopierar vi det som inte \u00e4ndras, sedan det som s\u00e4llan \u00e4ndras, och till sist \u2014 det som ofta \u00e4ndras.<\/p>\n<p><\/p>\n<p>Sedan n\u00e5gra ord om att bygga bilder i CI\/CD-system.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Anv\u00e4ndning av tidigare bilder f\u00f6r caching<\/h2>\n<p><\/p>\n<p>Om vi anv\u00e4nder en SaaS-l\u00f6sning f\u00f6r att bygga, kan den lokala cach\u00e9n av Docker vara ren och fr\u00e4sch. F\u00f6r att Docker ska ha n\u00e5gonstans att h\u00e4mta bakade lager fr\u00e5n, ge den den tidigare byggda bilden.<\/p>\n<p><\/p>\n<p>L\u00e5t oss ta exemplet med att bygga v\u00e5r applikation i GitHub Actions. Vi anv\u00e4nder en s\u00e5dan konfiguration<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">on:\n  push:\n    branches:\n      - master\n\nname: Test docker build\n\njobs:\n  deploy:\n    name: Build\n    runs-on: ubuntu-latest\n    env:\n      IMAGE_NAME: docker.pkg.github.com\/${{ github.repository }}\/app\n      IMAGE_TAG: ${{ github.sha }}\n\n    steps:\n    - name: Checkout\n      uses: actions\/checkout@v2\n\n    - name: Login to GitHub Packages\n      env:\n        TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN\n\n    - name: Build\n      run: |\n        docker build \n          -t $IMAGE_NAME:$IMAGE_TAG \n          -t $IMAGE_NAME:latest \n          .\n\n    - name: Push image to GitHub Packages\n      run: |\n        docker push $IMAGE_NAME:latest\n        docker push $IMAGE_NAME:$IMAGE_TAG\n\n    - name: Logout\n      run: |\n        docker logout docker.pkg.github.com<\/code><\/pre>\n<p><\/p>\n<p>Avbilden samlas och pushas till GitHub Packages p\u00e5 tv\u00e5 minuter och 20 sekunder:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nu f\u00f6r\u00e4ndrar vi bygget s\u00e5 att vi anv\u00e4nder cache baserat p\u00e5 tidigare byggda bilder:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">on:\n  push:\n    branches:\n      - master\n\nname: Test docker build\n\njobs:\n  deploy:\n    name: Build\n    runs-on: ubuntu-latest\n    env:\n      IMAGE_NAME: docker.pkg.github.com\/${{ github.repository }}\/app\n      IMAGE_TAG: ${{ github.sha }}\n\n    steps:\n    - name: Checkout\n      uses: actions\/checkout@v2\n\n    - name: Login to GitHub Packages\n      env:\n        TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN\n\n    - name: Pull latest images\n      run: |\n        docker pull $IMAGE_NAME:latest || true\n        docker pull $IMAGE_NAME-builder-stage:latest || true\n\n    - name: Images list\n      run: |\n        docker images\n\n    - name: Build\n      run: |\n        docker build \n          --target builder \n          --cache-from $IMAGE_NAME-builder-stage:latest \n          -t $IMAGE_NAME-builder-stage \n          .\n        docker build \n          --cache-from $IMAGE_NAME-builder-stage:latest \n          --cache-from $IMAGE_NAME:latest \n          -t $IMAGE_NAME:$IMAGE_TAG \n          -t $IMAGE_NAME:latest \n          .\n\n    - name: Push image to GitHub Packages\n      run: |\n        docker push $IMAGE_NAME-builder-stage:latest\n        docker push $IMAGE_NAME:latest\n        docker push $IMAGE_NAME:$IMAGE_TAG\n\n    - name: Logout\n      run: |\n        docker logout docker.pkg.github.com<\/code><\/pre>\n<p><\/p>\n<p>F\u00f6rst m\u00e5ste vi f\u00f6rklara varf\u00f6r tv\u00e5 kommandon k\u00f6rs <code>build<\/code>. Det handlar om att i en multi-stage-build kommer den resulterande bilden att vara en upps\u00e4ttning lager fr\u00e5n det senaste steget. Lager fr\u00e5n tidigare steg kommer inte att ing\u00e5 i bilden. D\u00e4rf\u00f6r, n\u00e4r man anv\u00e4nder den slutgiltiga bilden fr\u00e5n tidigare byggning, kommer Docker inte att kunna hitta de f\u00e4rdiga lagren f\u00f6r att bygga bilden med nodejs (builder-steget). F\u00f6r att l\u00f6sa detta problem skapas en mellanliggande bild <code>$IMAGE_NAME-builder-stage<\/code> och skickas till GitHub Packages s\u00e5 att den kan anv\u00e4ndas i den efterf\u00f6ljande byggningen som en cachek\u00e4lla.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den totala byggetiden har minskat till en och en halv minut. En halv minut g\u00e5r \u00e5t till att h\u00e4mta tidigare bilder.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">F\u00f6rhandsbygge av bilder<\/h2>\n<p><\/p>\n<p>Ett annat s\u00e4tt att l\u00f6sa problemet med ren Docker-cache \u00e4r att extrahera delar av lagren till en annan Dockerfile, bygga den separat, pusha den till Container Registry och anv\u00e4nda den som f\u00f6r\u00e4lder.<\/p>\n<p><\/p>\n<p>Vi skapar v\u00e5r egen Node.js-bild f\u00f6r att bygga Angular-applikationen. Skapa Dockerfile.node i projektet.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++<\/code><\/pre>\n<p><\/p>\n<p>Bygg och pusha den offentliga bilden till Docker Hub:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker build -t exsmund\/node-for-angular -f Dockerfile.node .\ndocker push exsmund\/node-for-angular:latest<\/code><\/pre>\n<p><\/p>\n<p>Nu anv\u00e4nder vi den f\u00e4rdiga bilden i v\u00e5r huvud-Dockerfile:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM exsmund\/node-for-angular:latest as builder\n...<\/code><\/pre>\n<p><\/p>\n<p>I v\u00e5rt exempel har byggtiden inte minskat, men f\u00f6rhandsbyggda bilder kan vara anv\u00e4ndbara om du har m\u00e5nga projekt som kr\u00e4ver samma beroenden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u00e5gra tips om hur man kan snabba upp byggandet av Docker-bilder. Till exempel, upp till 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi har g\u00e5tt igenom flera metoder f\u00f6r att p\u00e5skynda byggandet av Docker-bilder. Om du vill att distributionen ska g\u00e5 snabbt, prova att implementera f\u00f6ljande i ditt projekt:<\/p>\n<p><\/p>\n<ul>\n<li>reducera kontexten;<\/li>\n<li>anv\u00e4nda sm\u00e5 f\u00f6r\u00e4lderbilder;<\/li>\n<li>multistage-build;<\/li>\n<li>\u00e4ndra ordningen p\u00e5 instruktionerna i Dockerfile f\u00f6r att effektivt anv\u00e4nda cache;<\/li>\n<li>konfigurera cache i CI\/CD-system;<\/li>\n<li>f\u00f6rhandsbygga bilder.<\/li>\n<\/ul>\n<p><\/p>\n<p>Jag hoppas att exemplet g\u00f6r det tydligare hur Docker fungerar, och att du kan optimera din distribution. F\u00f6r att experimentera med exemplen i artikeln har ett repo skapats. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>K\u00e4lla: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/501680\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u0438\u0447\u0430 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0434, \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 CI\/CD \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0443\u0442\u044c \u043e\u0442 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0434\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438. \u0420\u0430\u043d\u044c\u0448\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043a\u0438\u043d\u0443\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043f\u043e FTP (\u0442\u0430\u043a \u0431\u043e\u043b\u044c\u0448\u0435 \u0442\u0430\u043a \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u0432\u0435\u0440\u043d\u043e?), \u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u00ab\u0434\u0435\u043f\u043b\u043e\u044f\u00bb \u0437\u0430\u043d\u0438\u043c\u0430\u043b \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0436\u0435 \u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c merge request \u0438 \u0436\u0434\u0430\u0442\u044c \u043d\u0435\u043c\u0430\u043b\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u043a\u0430 \u0444\u0438\u0447\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":81601,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-81600","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\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u0438\u0447\u0430 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0434, \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 CI\/CD \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0443\u0442\u044c \u043e\u0442 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0434\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\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\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund\" \/>\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\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0432\u0435\u0442\u043e\u0432 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e 30 \u0441\u0435\u043a\u0443\u043d\u0434 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u0438\u0447\u0430 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0434, \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 CI\/CD \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0443\u0442\u044c \u043e\u0442 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0434\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund\" \/>\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-05-14T23:42:41+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-14T23:42:41+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 N\u00e5gra tips f\u00f6r att p\u00e5skynda byggandet av Docker-bilder. Till exempel, upp till 30 sekunder | ProHoster","description":"Innan en funktion n\u00e5r produktion m\u00e5ste den, i v\u00e5r tids \u00e5ngestfyllda orkestratorer och CI\/CD, genomg\u00e5 en l\u00e5ng v\u00e4g fr\u00e5n commit till tester och leverans.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","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\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0432\u0435\u0442\u043e\u0432 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e 30 \u0441\u0435\u043a\u0443\u043d\u0434 | ProHoster","og:description":"\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u0438\u0447\u0430 \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0434, \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 CI\/CD \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0443\u0442\u044c \u043e\u0442 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0434\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438.","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","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-05-14T23:42:41+00:00","article:modified_time":"2020-05-14T23:42:41+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"81600","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:55:42","updated":"2022-09-29 02:10:06","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\/81600","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=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}