{"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\/ro\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u00cenainte ca o func\u021bionalitate s\u0103 ajung\u0103 \u00een produc\u021bie, \u00een vremea orchestratorilor complexi \u0219i a CI\/CD-ului, trebuie s\u0103 parcurg\u0103 un drum lung de la commit la teste \u0219i livrare. \u00cen trecut, puteai s\u0103 arunci fi\u0219ierele noi prin FTP (dar acum nimeni nu mai face a\u0219a, nu-i a\u0219a?), iar procesul de \u201edeploiere\u201d dura doar c\u00e2teva secunde. Acum, trebuie s\u0103 creezi o cerere de fuziune \u0219i s\u0103 a\u0219tep\u021bi un timp considerabil p\u00e2n\u0103 c\u00e2nd func\u021bionalitatea ajunge la utilizatori.<\/p>\n<p><\/p>\n<p>O parte din acest drum este construirea imaginii Docker. Uneori construirea dureaz\u0103 minute, alteori zeci de minute, ceea ce nici m\u0103car nu poate fi numit normal. \u00cen acest articol, vom lua o aplica\u021bie simpl\u0103, pe care o vom \u00eempacheta \u00eentr-o imagine, vom aplica c\u00e2teva metode pentru a accelera construc\u021bia \u0219i vom analiza detaliile acestor metode.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" 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>Avem o experien\u021b\u0103 bun\u0103 \u00een crearea \u0219i \u00eentre\u021binerea site-urilor media: <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\/\">\"Ziarul Nou\"<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>\u2026 Nu cu mult timp \u00een urm\u0103, ne-am completat portofoliul, lans\u00e2nd site-ul \u00een produc\u021bie <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>. \u0218i \u00een timp ce lucram rapid la noi func\u021bionalit\u0103\u021bi \u0219i reparam erorile vechi, deploierea lent\u0103 a devenit o mare problem\u0103.<\/p>\n<p><\/p>\n<p>Deploierea o facem pe GitLab. Construim imagini, le \u00eempingem \u00een GitLab Registry \u0219i le desf\u0103\u0219ur\u0103m \u00een produc\u021bie. \u00cen aceast\u0103 list\u0103, cea mai lung\u0103 etap\u0103 este construirea imaginilor. De exemplu: f\u0103r\u0103 optimizare, fiecare construc\u021bie a backend-ului dura 14 minute.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen cele din urm\u0103, a devenit clar c\u0103 nu mai putem continua a\u0219a, a\u0219a c\u0103 ne-am a\u0219ezat s\u0103 \u00een\u021belegem de ce imaginile se construiesc at\u00e2t de mult timp. \u00cen final, am reu\u0219it s\u0103 reducem timpul de construc\u021bie la 30 de secunde!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pentru acest articol, pentru a nu ne lega de mediul Reminder-ului, vom analiza un exemplu de creare a unei aplica\u021bii goale pe Angular. A\u0219adar, s\u0103 cre\u0103m aplica\u021bia noastr\u0103:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>Ad\u0103ug\u0103m PWA (suntem progresi\u0219ti):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>\u00cen timp ce se descarc\u0103 milioane de pachete npm, s\u0103 ne d\u0103m seama cum este construit\u0103 imaginea docker. Docker ofer\u0103 posibilitatea de a \u00eempacheta aplica\u021bii \u0219i a le rula \u00eentr-un mediu izolat, numit container. Datorit\u0103 izol\u0103rii, po\u021bi rula simultan multe containere pe un singur server. Containerele sunt mult mai u\u0219oare dec\u00e2t ma\u0219inile virtuale, deoarece ruleaz\u0103 direct pe nucleul sistemului. Pentru a rula un container cu aplica\u021bia noastr\u0103, trebuie mai \u00eent\u00e2i s\u0103 cre\u0103m o imagine \u00een care vom \u00eempacheta tot ce este necesar pentru func\u021bionarea aplica\u021biei noastre. Practic, imaginea este o copie a sistemului de fi\u0219iere. De exemplu, s\u0103 lu\u0103m un 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 este un set de instruc\u021biuni; execut\u00e2nd fiecare dintre ele, Docker va salva modific\u0103rile \u00een sistemul de fi\u0219iere \u0219i le va suprapune pe cele anterioare. Fiecare comand\u0103 creeaz\u0103 propriul s\u0103u strat. Iar imaginea final\u0103 este o combina\u021bie a acestor straturi.<\/p>\n<p><\/p>\n<p>Ce este important de \u0219tiut: fiecare strat poate fi stocat \u00een cache de Docker. Dac\u0103 nu s-a schimbat nimic de la ultima construc\u021bie, \u00een loc s\u0103 execute comanda, Docker va folosi deja stratul finalizat. Deoarece c\u00e2\u0219tigul principal \u00een viteza de construc\u021bie va veni din utilizarea cache-ului, vom acorda o aten\u021bie deosebit\u0103 m\u0103sur\u0103rii vitezei construc\u021biei atunci c\u00e2nd imaginile sunt construite cu cache. A\u0219adar, iat\u0103 pa\u0219ii:<\/p>\n<p><\/p>\n<ol>\n<li>\u0218tergem imaginile local pentru ca execu\u021biile anterioare s\u0103 nu influen\u021beze testul.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>Execut\u0103m construc\u021bia pentru prima dat\u0103.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>Schimb\u0103m fi\u0219ierul src\/index.html \u2014 imit\u0103m munca programatorului.<\/li>\n<li>Execut\u0103m construc\u021bia pentru a doua oar\u0103.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Dac\u0103 mediul pentru construc\u021bia imaginilor este configurat corect (despre care vom discuta pu\u021bin mai jos), atunci Docker va avea deja o mul\u021bime de cache-uri disponibile la \u00eenceputul construc\u021biei. Sarcina noastr\u0103 este s\u0103 \u00eenv\u0103\u021b\u0103m s\u0103 folosim cache-ul astfel \u00eenc\u00e2t construc\u021bia s\u0103 fie c\u00e2t mai rapid\u0103. Deoarece presupunem c\u0103 execu\u021bia construc\u021biei f\u0103r\u0103 cache se \u00eent\u00e2mpl\u0103 doar o singur\u0103 dat\u0103 \u2014 prima \u2014 putem ignora c\u00e2t de lent\u0103 a fost acea prim\u0103 dat\u0103. \u00cen teste, conteaz\u0103 mai mult a doua execu\u021bie a construc\u021biei, c\u00e2nd cache-urile sunt deja pre\u00eenc\u0103lzite \u0219i suntem gata s\u0103 ne coacem pl\u0103cinta. Cu toate acestea, unele sfaturi vor influen\u021ba \u0219i prima construc\u021bie.<\/p>\n<p><\/p>\n<p>S\u0103 plas\u0103m Dockerfile-ul, descris mai sus, \u00een folderul proiectului \u0219i s\u0103 ini\u021biem construc\u021bia. Toate list\u0103rile prezentate sunt reduse pentru a facilita citirea.<\/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>Modific\u0103m con\u021binutul src\/index.html \u0219i ini\u021biem din nou construc\u021bia.<\/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>Pentru a verifica dac\u0103 am ob\u021binut imaginea, vom executa comanda <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   Aproape acum un minut   1.74GB<\/code><\/pre>\n<p><\/p>\n<p>\u00cenainte de a construi, Docker ia toate fi\u0219ierele din contextul actual \u0219i le trimite demonului s\u0103u. <code>Trimiterea contextului de construc\u021bie c\u0103tre demonul Docker 409MB<\/code>. Contextul pentru construc\u021bie este specificat ca ultimul argument al comenzii build. \u00cen cazul nostru, acesta este directorul curent \u2014 \u201e.\u201d \u2014 \u0219i Docker aduce tot ce avem \u00een aceast\u0103 dosar. 409 MB este mult: s\u0103 ne g\u00e2ndim cum putem corecta asta.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">Reducerea contextului<\/h2>\n<p><\/p>\n<p>Pentru a reduce contextul, exist\u0103 dou\u0103 op\u021biuni. Fie s\u0103 punem toate fi\u0219ierele necesare pentru construc\u021bie \u00eentr-un dosar separat \u0219i s\u0103 indic\u0103m Docker-ului exact acest dosar ca context. Aceasta poate fi uneori incomod, a\u0219a c\u0103 exist\u0103 op\u021biunea de a specifica excep\u021bii: ce nu trebuie s\u0103 fie inclus \u00een context. Pentru aceasta, vom ad\u0103uga un fi\u0219ier .dockerignore \u00een proiect \u0219i vom specifica ce nu este necesar pentru construc\u021bie:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>\u0219i vom rula construc\u021bia din nou:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nTrimiterea contextului de construc\u021bie c\u0103tre demonul Docker 607.2kB\nPasul 1\/5 : DIN node:12.16.2\nPasul 2\/5 : WORKDIR \/app\n ---&gt; Folosind cache\nPasul 3\/5 : COPIE . .\nPasul 4\/5 : RULARE npm ci\nad\u0103ugat 1357 pachete \u00een 22.47s\nPasul 5\/5 : RULARE npm run build --prod\nData: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Timp: 37313ms\nConstruit cu succes 4942f010792a\nEtichetat cu succes app:latest\n\nreal 1m47.763s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607.2 K\u0431\u0430\u0439\u0442 \u2014 mult mai bine dec\u00e2t 409 MB. \u0218i am redus dimensiunea imaginii de la 1.74 la 1.38 GB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOZITAR   ETICHET\u0102   ID IMAGINE       CREAT         DIMENSIUNE\napp          latest   4942f010792a   acum 3 minute   1.38GB<\/code><\/pre>\n<p><\/p>\n<p>Hai s\u0103 \u00eencerc\u0103m s\u0103 reducem \u0219i mai mult dimensiunea imaginii.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Folosim Alpine<\/h2>\n<p><\/p>\n<p>\u00cenca o metod\u0103 de a economisi pe dimensiunea imaginii \u2014 utilizarea unei imagini parentale mai mici. Imaginea parental\u0103 este imaginea pe care se bazeaz\u0103 imaginea noastr\u0103. Stratul de baz\u0103 este specificat cu comanda <code>FROM<\/code> \u00een Dockerfile. \u00cen cazul nostru, folosim o imagine bazat\u0103 pe Ubuntu, care are deja nodejs instalat. \u0218i c\u00e2nt\u0103re\u0219te \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c acum 17 minute 916MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 aproape un gigabyte. Se poate reduce semnificativ volumul, folosind o imagine bazat\u0103 pe Alpine Linux. Alpine este un Linux foarte mic. Imaginea Docker pentru nodejs bazat\u0103 pe alpine c\u00e2nt\u0103re\u0219te doar 88.5 MB. A\u0219adar, hai s\u0103 \u00eenlocuim imaginea noastr\u0103 prea grea:<\/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++\nWORKDIR \/app\nCOPY . .\nRUN npm ci\nRUN npm run build --prod<\/code><\/pre>\n<p><\/p>\n<p>A trebuit s\u0103 instal\u0103m c\u00e2teva lucruri necesare pentru construirea aplica\u021biei. Da, Angular nu se compileaz\u0103 f\u0103r\u0103 Python \u00af(\u00b0_o)\\\/\u00af<\/p>\n<p><\/p>\n<p>Dar dimensiunea imaginii a sc\u0103zut cu 150 MB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOZITAR   ETICHET\u0102   ID IMAGINE       CREAT          DIMENSIUNE\napp          latest   aa031edc315a   acum 22 minute   761MB<\/code><\/pre>\n<p><\/p>\n<p>S\u0103 mergem mai departe.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">Construire multi-stage<\/h2>\n<p><\/p>\n<p>Nu tot ce exist\u0103 \u00een imagine ne este necesar \u00een produc\u021bie.<\/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>Folosind <code>docker run app ls -lah<\/code> Am lansat un container bazat pe imaginea noastr\u0103 <code>app<\/code> \u0219i am executat comanda \u00een el <code>ls -lah<\/code>, dup\u0103 care containerul \u0219i-a terminat activitatea.<\/p>\n<p><\/p>\n<p>Pe produc\u021bie, avem nevoie doar de folderul <code>dist<\/code>. Totu\u0219i, trebuie s\u0103 expunem fi\u0219ierele. Putem rula un server HTTP folosind nodejs. Dar vom face mai simplu. Ghici\u021bi cuv\u00e2ntul rom\u00e2nesc care are patru litere \u201e\u00ee\u201d. Corect! \u00cendj\u00eenii. Vom lua o imagine cu nginx, vom plasa \u00een ea folderul <code>dist<\/code> \u0219i un mic fi\u0219ier de configurare:<\/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>Acest lucru ne va ajuta s\u0103 utiliz\u0103m un multi-stage build. Vom modifica Dockerfile-ul nostru:<\/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>Acum avem dou\u0103 instruc\u021biuni <code>FROM<\/code> \u00een Dockerfile, fiecare dintre ele ruleaz\u0103 propria etap\u0103 de construc\u021bie. Prima a fost numit\u0103 <code>builder<\/code>, iar de la ultimul FROM se va preg\u0103ti imaginea noastr\u0103 final\u0103. Pasul final este s\u0103 copiem artefactul construc\u021biei noastre din etapa anterioar\u0103 \u00een imaginea final\u0103 cu nginx. Dimensiunea imaginii a fost semnificativ redus\u0103:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   2c6c5da07802   acum 29 de minute   36MB<\/code><\/pre>\n<p><\/p>\n<p>Hai s\u0103 lans\u0103m un container cu imaginea noastr\u0103 \u0219i s\u0103 ne asigur\u0103m c\u0103 totul func\u021bioneaz\u0103:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>Cu op\u021biunea -p8080:80 am redirec\u021bionat portul 8080 de pe ma\u0219ina noastr\u0103 gazd\u0103 c\u0103tre portul 80 din interiorul containerului, unde ruleaz\u0103 nginx. Deschidem \u00een browser <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> \u0219i vedem aplica\u021bia noastr\u0103. Totul func\u021bioneaz\u0103!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Reducerea dimensiunii imaginii de la 1.74 GB la 36 MB scurteaz\u0103 semnificativ timpul necesar pentru livrarea aplica\u021biei tale \u00een produc\u021bie. Dar s\u0103 ne \u00eentoarcem la timpul de construc\u021bie.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nTrimite contextul construc\u021biei daemon-ului Docker 608.8kB\nPasul 1\/11 : FROM node:12.16.2-alpine3.11 as builder\nPasul 2\/11 : RUN apk --no-cache --update --virtual build-dependencies add python make g++\n ---&gt; Using cache\nPasul 3\/11 : WORKDIR \/app\n ---&gt; Using cache\nPasul 4\/11 : COPY . .\nPasul 5\/11 : RUN npm ci\nau fost ad\u0103ugate 1357 pachete \u00een 47.338s\nPasul 6\/11 : RUN npm run build --prod\nData: 2020-04-16T21:16:03.899Z - Hash: fffa0fddaa3425c55dd3 - Timp: 39948ms\n ---&gt; 27f1479221e4\nPasul 7\/11 : FROM nginx:stable-alpine\nPasul 8\/11 : WORKDIR \/app\n ---&gt; Using cache\nPasul 9\/11 : RUN rm \/etc\/nginx\/conf.d\/default.conf\n ---&gt; Using cache\nPasul 10\/11 : COPY nginx\/static.conf \/etc\/nginx\/conf.d\n ---&gt; Using cache\nPasul 11\/11 : COPY --from=builder \/app\/dist\/app .\nConstruc\u021bie reu\u0219it\u0103 d201471c91ad\nEtichet\u0103 reu\u0219it\u0103 app:latest\n\nreal 2m17.700s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<h2 id=\"menyaem-poryadok-sloyov\">Schimb\u0103m ordinea straturilor<\/h2>\n<p><\/p>\n<p>Primele trei pa\u0219i au fost cache-uite (sugestie <code>Using cache<\/code>). La pasul al patrulea se copiaz\u0103 toate fi\u0219ierele proiectului, iar la pasul al cincilea se instaleaz\u0103 dependen\u021bele <code>RUN npm ci<\/code> \u2014 \u00eentregi 47,338s. De ce s\u0103 instal\u0103m dependen\u021bele de fiecare dat\u0103, dac\u0103 ele se schimb\u0103 foarte rar? Hai s\u0103 vedem de ce nu au fost stocate \u00een cache. Problema este c\u0103 Docker verific\u0103 strat cu strat, dac\u0103 comanda \u0219i fi\u0219ierele asociate cu aceasta s-au schimbat. \u00cen pasul patru copiem toate fi\u0219ierele proiectului nostru, iar printre ele, desigur, exist\u0103 modific\u0103ri, a\u0219a c\u0103 Docker nu numai c\u0103 nu ia din cache acest strat, dar \u0219i toate cele ulterioare! S\u0103 facem c\u00e2teva modific\u0103ri \u00een 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>Mai \u00eent\u00e2i sunt copiate package.json \u0219i package-lock.json, apoi se instaleaz\u0103 dependen\u021bele, \u0219i abia dup\u0103 aceea se copiaz\u0103 \u00eentreg proiectul. Ca rezultat:<\/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 secunde \u00een loc de 3 minute \u2014 mult mai bine! Este important s\u0103 avem ordinea corect\u0103 a straturilor: mai \u00eent\u00e2i copiem ceea ce nu se schimb\u0103, apoi ceea ce se schimb\u0103 rar, iar la final \u2014 ceea ce se schimb\u0103 frecvent.<\/p>\n<p><\/p>\n<p>Apoi, c\u00e2teva cuvinte despre construirea imaginilor \u00een sistemele CI\\\/CD.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Utilizarea imaginilor anterioare pentru cache<\/h2>\n<p><\/p>\n<p>Dac\u0103 folosim o solu\u021bie SaaS pentru construirea aplica\u021biei, cache-ul local Docker poate fi gol \u0219i proasp\u0103t. Pentru ca Docker s\u0103 aib\u0103 de unde s\u0103 ia straturile coapte, ofer\u0103-i imaginea construit\u0103 anterior.<\/p>\n<p><\/p>\n<p>S\u0103 lu\u0103m ca exemplu construirea aplica\u021biei noastre \u00een GitHub Actions. Folosim aceast\u0103 configura\u021bie<\/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>Imaginea este construit\u0103 \u0219i \u00eempins\u0103 \u00een GitHub Packages \u00een dou\u0103 minute \u0219i 20 de secunde:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Acum vom modifica construc\u021bia pentru a folosi cache-ul bazat pe imaginile construite anterior:<\/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>\u00cen primul r\u00e2nd, trebuie s\u0103 explic\u0103m de ce sunt rulate dou\u0103 comenzi. <code>build<\/code>Ceea ce se \u00eent\u00e2mpl\u0103 este c\u0103, \u00een construc\u021bia multi-stagiu, rezultatul va fi un set de straturi din ultimul stagiu. Straturile din straturile anterioare nu vor fi incluse \u00een imagine. Prin urmare, c\u00e2nd se folose\u0219te imaginea final\u0103 din construc\u021bia anterioar\u0103, Docker nu va putea g\u0103si straturile necesare pentru a construi imaginea cu nodejs (stagiu builder). Pentru a rezolva aceast\u0103 problem\u0103, se creeaz\u0103 o imagine intermediar\u0103. <code>$IMAGE_NAME-builder-stage<\/code> \u0219i este trimis\u0103 \u00een GitHub Packages, astfel \u00eenc\u00e2t s\u0103 poat\u0103 fi folosit\u0103 \u00een construc\u021biile ulterioare ca surs\u0103 de cache.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Timpul total de construc\u021bie a fost redus la o minut\u0103 \u0219i jum\u0103tate. O jum\u0103tate de minut este consumat\u0103 pentru a atrage imaginile anterioare.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">Crearea preliminar\u0103 a imaginilor<\/h2>\n<p><\/p>\n<p>O alt\u0103 modalitate de a rezolva problema memoriei cache \u00een Docker este s\u0103 extindem o parte din straturi \u00eentr-un alt Dockerfile, s\u0103-l compil\u0103m separat, s\u0103-l \u00eenc\u0103rc\u0103m \u00een Container Registry \u0219i s\u0103-l folosim ca p\u0103rinte.<\/p>\n<p><\/p>\n<p>Cre\u0103m imaginea noastr\u0103 nodejs pentru compilarea aplica\u021biei Angular. Cre\u0103m un Dockerfile.node \u00een proiect.<\/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>Construim \u0219i \u00eenc\u0103rc\u0103m imaginea public\u0103 \u00een 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>Acum, \u00een Dockerfile-ul nostru principal, folosim imaginea gata f\u0103cut\u0103:<\/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>\u00cen exemplul nostru, timpul de construire nu s-a redus, dar imaginile pre-construite pot fi utile dac\u0103 ave\u021bi multe proiecte \u0219i \u00een fiecare dintre ele trebuie s\u0103 instala\u021bi acelea\u0219i dependen\u021be.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"C\u00e2teva sfaturi despre cum s\u0103 acceler\u0103m construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Am analizat c\u00e2teva metode de accelerare a construirii imaginilor Docker. Dac\u0103 dori\u021bi ca desf\u0103\u0219urarea s\u0103 fie rapid\u0103, \u00eencerca\u021bi s\u0103 aplica\u021bi \u00een proiectul dumneavoastr\u0103:<\/p>\n<p><\/p>\n<ul>\n<li>reducerea contextului;<\/li>\n<li>utilizarea unor imagini p\u0103rinte mici;<\/li>\n<li>construc\u021bia cu multiple stadii;<\/li>\n<li>schimbarea ordinii instruc\u021biunilor \u00een Dockerfile pentru a utiliza eficient memoria cache;<\/li>\n<li>configurarea cache-ului \u00een sistemele CI\/CD;<\/li>\n<li>crearea prealabil\u0103 a imaginilor.<\/li>\n<\/ul>\n<p><\/p>\n<p>Sper c\u0103 exemplul va face mai clar cum func\u021bioneaz\u0103 Docker \u0219i c\u0103 ve\u021bi putea s\u0103 v\u0103 optimiza\u021bi desf\u0103\u0219urarea. Pentru a experimenta cu exemplele din articol, s-a creat un depozit <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>Sursa: <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.2.1 - 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\/ro\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\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\/ro\/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\udd47C\u00e2teva sfaturi despre cum s\u0103 accelera\u021bi construirea imaginilor Docker. De exemplu, p\u00e2n\u0103 la 30 de secunde | ProHoster","description":"\u00cenainte ca func\u021bia s\u0103 ajung\u0103 \u00een produc\u021bie, \u00een vremurile noastre de orchestratori \u0219i CI\/CD complexi, va trebui s\u0103 parcurg\u0103 un drum lung de la commit p\u00e2n\u0103 la teste \u0219i livrare.","canonical_url":"https:\/\/prohoster.info\/ro\/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":"ro_RO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/81600","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}