{"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\/et\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Enne funktsioon j\u00f5uab tootmisse, peab see meie keerukate orkestratorite ja CI\/CD ajastul l\u00e4bima pika tee commitist testide ja tarnimiseni. Varem sai faile FTP kaudu kiiresti \u00fcles laadida (aga keegi ei tee seda enam, eks?), ja \u201edeploion\u201c kestis sekundeid. N\u00fc\u00fcd tuleb luua merge request ja oodata, kuni funktsioon j\u00f5uab kasutajateni.<\/p>\n<p><\/p>\n<p>Osa sellest teest on Docker-pildi koostamine. M\u00f5nikord kestab koostamine minuteid, m\u00f5nikord \u2014 k\u00fcmneid minuteid, mida on raske normaalseks pidada. Selles artiklis v\u00f5tame lihtsa rakenduse, pakime selle pildiks, rakendame mitmeid meetodeid koostamise kiirendamiseks ja vaatame nende meetodite n\u00fcansse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" 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>Meil on hea kogemus meedia veebisaitide loomisel ja haldamisel: <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\/\">&quot;\u041d\u043e\u0432\u0430\u044f \u0433\u0430\u0437\u0435\u0442\u0430&quot;<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>\u2026 Eelmisel ajal t\u00e4iendame oma portfelli, k\u00e4ivitades tootmisse veebisaidi <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>. Ja samal ajal kui me kiiresti t\u00e4iendame uusi funktsioone ja parandame vanu vigu, on aeglane deploion muutunud suureks probleemiks.<\/p>\n<p><\/p>\n<p>Deploime GitLabis. Koostame pilte, pushime need GitLabi registrisse ja levitame tootmises. Sellest nimekirjast on aeglasem osa piltide koostamine. N\u00e4iteks: ilma optimeerimiseta kestis iga backendi koostamine 14 minutit.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>L\u00f5puks selgus, et nii ei saa enam elada, ja istusime maha, et aru saada, miks pildid nii kaua koostavad. L\u00f5puks \u00f5nnestus koostamisaega k\u00e4rpida 30 sekundini!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0414\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044e Reminder&#8217;\u0430, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Angular. \u0418\u0442\u0430\u043a, \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>Lisame sellele PWA (me oleme ju progressiivsed):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>Kuni miljoni npm-paketi allalaadimise jooksul vaatame, kuidas docker-pilt t\u00f6\u00f6tab. Docker v\u00f5imaldab rakendusi pakendada ja k\u00e4itada neid isoleeritud keskkonnas, mida nimetatakse konteineriks. Isolatsiooni t\u00f5ttu saab samaaegselt \u00fchel serveril k\u00e4itada palju konteineri. Konteinerid on oluliselt kergemad virtuaalsetest masinatest, kuna need t\u00f6\u00f6tavad otse s\u00fcsteemi tuumast. Meie rakenduse konteineri k\u00e4ivitamiseks peame esmalt looma pildi, kuhu pakime k\u00f5ik vajalikud komponendid meie rakenduse talitamiseks. Sisuliselt on pilt failis\u00fcsteemi koopia. N\u00e4iteks v\u00f5tame Dockerfile'i:<\/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 on komplekt juhiseid; t\u00e4itmisel salvestab Docker iga\u00fche muudatused failis\u00fcsteemis ja lisab need eelnevate peale. Iga k\u00e4sk loob oma kihi. Valmis image on kokku pandud kihtide kombinatsioon.<\/p>\n<p><\/p>\n<p>Oluline teada: iga kiht suudab Dockeris vahem\u00e4lu salvestada. Kui midagi pole muutunud eelmise ehituse ajal, siis pigem kui k\u00e4sku t\u00e4ita, v\u00f5tab docker juba olemasoleva kihi. Kuna peamine kiiruset\u00f5us ehituses toimub vahem\u00e4lu kasutamise kaudu, p\u00f6\u00f6rame ehituse kiirusm\u00f5\u00f5tmistesse t\u00e4helepanu just valmiskihile. Nii et, sammud on j\u00e4rgmised:<\/p>\n<p><\/p>\n<ol>\n<li>Kustutame kohalikult pildid, et varasemad k\u00e4ivitused ei m\u00f5jutaks testi.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>K\u00e4ivitame ehituse esmakordselt.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>Muudame faili src\/index.html \u2014 j\u00e4ljendame programmeerija t\u00f6\u00f6d.<\/li>\n<li>K\u00e4ivitame ehituse teist korda.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Kui pildiehituse keskkond on \u00f5igesti seadistatud (mille kohta r\u00e4\u00e4gime natuke allpool), on dockeri k\u00e4ivitamisel juba hulk vahem\u00e4lusid valmis. Meie \u00fclesanne on \u00f5ppida vahem\u00e4lu kasutama nii, et ehitus kulgeks v\u00f5imalikult kiiresti. Kuna eeldame, et ilma vahem\u00e4luta ehitus k\u00e4ivitub ainult \u00fcks kord \u2014 k\u00f5ige esimene \u2014 v\u00f5ime ignoreerida, kui aeglane oli see esimene kord. Testides on meie jaoks oluline teine ehitus, kui vahem\u00e4lud on juba soojendatud ja oleme valmis meie pirukat k\u00fcpsetama. Siiski m\u00f5nede n\u00f5uannete m\u00f5ju avaldub ka esimesel ehitusel.<\/p>\n<p><\/p>\n<p>Paigutame eespool kirjeldatud Dockerfile projekti kausta ja k\u00e4ivitame ehituse. K\u00f5ik esitatud loetelud on l\u00fchendatud lugemise mugavuse huvides.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSaadetakse ehituskontekst Docker daemonile 409MB\nSamm 1\/5 : FROM node:12.16.2\nOleku: Uus pilt node:12.16.2\nSamm 2\/5 : WORKDIR \/app\nSamm 3\/5 : COPY . .\nSamm 4\/5 : RUN npm ci\nlisatud 1357 paketid 22.47s\nSamm 5\/5 : RUN npm run build --prod\nKuup\u00e4ev: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Aeg: 37581ms\nEdukas ehitus c8c279335f46\nEdukas m\u00e4rgistatud app:latest\n\nreaalne 5m4.541s\nkasutaja 0m0.000s\ns\u00fcsteem 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>Muudame sisu src\/index.html ja k\u00e4ivitame teist korda.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSaadetakse ehituskontekst Docker daemonile 409MB\nSamm 1\/5 : FROM node:12.16.2\nSamm 2\/5 : WORKDIR \/app\n ---&gt; Kasutatakse vahem\u00e4lu\nSamm 3\/5 : COPY . .\nSamm 4\/5 : RUN npm ci\nlisatud 1357 paketid 22.47s\nSamm 5\/5 : RUN npm run build --prod\nKuup\u00e4ev: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - Aeg: 37902ms\nEdukas ehitus 79f335df92d3\nEdukas m\u00e4rgistatud app:latest\n\nreaalne 3m33.262s\nkasutaja 0m0.000s\ns\u00fcsteem 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>Kuna tahame n\u00e4ha, kas oleme pildi saanud, k\u00e4ivitame k\u00e4su <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   Umbes minut tagasi   1.74GB<\/code><\/pre>\n<p><\/p>\n<p>Enne dokkeri kogumist v\u00f5tab dokker k\u00f5ik failid praeguses kontekstis ja saadab need oma daemoni <code>Saadan ehituse konteksti Docker daemonile 409MB<\/code>. Ehituse konteksti m\u00e4\u00e4ratakse build k\u00e4su viimase argumendina. Meie puhul on see praegune kataloog \u2014 \".\", \u2014 ja dokker toob k\u00f5ik, mis meil selles kaustas on. 409 MB on palju: m\u00f5elgem, kuidas seda parandada.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">V\u00e4hendame konteksti<\/h2>\n<p><\/p>\n<p>Konteksti v\u00e4hendamiseks on kaks v\u00f5imalust. Kas panna k\u00f5ik ehitamiseks vajalikud failid eraldi kausta ja osutada dokkerile just sellele kaustale. See ei pruugi alati mugav olla, seega on v\u00f5imalus m\u00e4\u00e4rata erandeid: mida ei pea konteksti tooma. Selleks paneme projekti faili .dockerignore ja m\u00e4\u00e4rame, mida ei ole vajalik ehitamiseks:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>ja k\u00e4ivitame ehituse uuesti:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSaadan ehituse konteksti Docker daemonile 607.2kB\nStep 1\/5 : FROM node:12.16.2\nStep 2\/5 : WORKDIR \/app\n ---&gt; Kasutatakse vahem\u00e4lu\nStep 3\/5 : COPY . .\nStep 4\/5 : RUN npm ci\nLisatud 1357 paketti 22.47s jooksul\nStep 5\/5 : RUN npm run build --prod\nKuup\u00e4ev: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Aeg: 37313ms\nEduka ehituse l\u00f5petamine 4942f010792a\nEduka sildistamise l\u00f5petamine app:latest\n\nreaalne 1m47.763s\nkasutaja 0m0.000s\ns\u00fcsteem 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607.2 Kb \u2014 palju parem kui 409 MB. Lisaks v\u00e4hendasime pildi suurust 1.74 GB-lt 1.38 GB-le:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED         SIZE\napp          latest   4942f010792a   3 minutit tagasi   1.38GB<\/code><\/pre>\n<p><\/p>\n<p>Proovime veelgi pildi suurust v\u00e4hendada.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Kasutame Alpine'i<\/h2>\n<p><\/p>\n<p>Veel \u00fcks viis pildi suuruse k\u00e4rpimiseks on kasutada v\u00e4ikest vanemat pilti. Vanem pilt on see pilt, mille p\u00f5hjal meie pilt luuakse. Alumine kiht m\u00e4\u00e4ratakse k\u00e4suga <code>KUST<\/code> Dockerfile'is. Meie puhul kasutame Ubuntu p\u00f5hjal tehtud pilti, kus on juba installitud nodejs. Ja selle suurus on \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c 17 minutit tagasi 916MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 peaaegu gigabait. Oluliselt mahtu v\u00e4hendada saame, kasutades Alpine Linux p\u00f5hjal tehtud pilti. Alpine on v\u00e4ga v\u00e4ike linux. Docker pilt nodejs jaoks Alpine'i p\u00f5hjal kaalub vaid 88.5 MB. Seega asendame meie suure pildi:<\/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>Me pidime installima m\u00f5ned asjad, mis on vajalikud rakenduse ehitamiseks. Jah, Angular ei ehitu ilma pythonita \u00af(\u00b0_o)\\\/\u00af<\/p>\n<p><\/p>\n<p>Aga pildi suurus langes 150 MB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   aa031edc315a   22 minutit tagasi   761MB<\/code><\/pre>\n<p><\/p>\n<p>Liigume veelgi kaugemale.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">Mitme etapi ehitus<\/h2>\n<p><\/p>\n<p>Ei ole k\u00f5ike, mis pildis on, meie jaoks tootmises vajalik.<\/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>EL-i abil <code>docker run app ls -lah<\/code> meie k\u00e4ivitasime konteineri meie pildist <code>app<\/code> ja t\u00e4itsime selles k\u00e4su <code>ls -lah<\/code>, p\u00e4rast mida konteiner l\u00f5petas oma t\u00f6\u00f6.<\/p>\n<p><\/p>\n<p>Prod-keskkonnas vajame ainult kausta <code>dist<\/code>. Sellegipoolest peame failid kuidagi v\u00e4ljastama. Saame k\u00e4ivitada m\u00f5ne HTTP-serveri nodejs-is. Kuid teeme lihtsamalt. Arva vene s\u00f5na, milles on neli t\u00e4hte \u00ab\u044b\u00bb. \u00d5ige! \u042b\u043d\u0436\u044b\u043d\u044b\u043a\u0441\u044b. V\u00f5tame nginx-i pildi, paneme sinna kausta <code>dist<\/code> ja v\u00e4ikese konfi:<\/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>Seda k\u00f5ike saab teha multi-stage build abil. Muudame meie Dockerfile'i:<\/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>N\u00fc\u00fcd on meil kaks k\u00e4sku <code>KUST<\/code> Dockerfile'is, millest iga\u00fchel on oma ehitusetapp. Esimese nimega <code>Raspberry Pi 3 jaoks un-def, lts, mp kernelitega, kui pulseaudio on kasutusel, tuleb \u00fche helikaardi (k\u00f5rvaklapid v\u00f5i HDMI) v\u00e4lja l\u00fclitada, vastasel juhul v\u00f5ib arvuti v\u00e4lja l\u00fclitamine kesta kaua ja heli v\u00f5ib kaduda pulseaudio t\u00f5ttu.<\/code>, kuid alates viimast FROM-ist valmistatakse meie l\u00f5plikku pilti. Viimasena kopeerime meie ehitusartefakti eelmisest etapist nginx-i l\u00f5plikku pilti. Pildi suurus on oluliselt v\u00e4henenud:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   2c6c5da07802   29 minutes ago   36MB<\/code><\/pre>\n<p><\/p>\n<p>K\u00e4ivitame konteineri meie pildiga ja veendume, et k\u00f5ik t\u00f6\u00f6tab:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>Valiku -p8080:80 kaudu suunamine viib meie hostmasinalt portaali 8080 konteineri 80-le, kus nginx t\u00f6\u00f6tab. Avame brauseris <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> ja n\u00e4eme meie rakendust. K\u00f5ik t\u00f6\u00f6tab!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pildi suuruse v\u00e4hendamine 1,74 GB-lt 36 MB-le l\u00fchendab oluliselt teie rakenduse toimetamise aega. Kuid naaseme ehitusaega.<\/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\">Muudame kihtide j\u00e4rjekorda<\/h2>\n<p><\/p>\n<p>Esimesed kolm sammu on meil vahem\u00e4lul (vihje <code>Using cache<\/code>). Neljandas etapis kopeeritakse k\u00f5ik projektifailid ja viiendas etapis installitakse s\u00f5ltuvused <code>RUN npm ci<\/code> \u2014 kokku 47.338s. Miks installida s\u00f5ltuvusi iga kord uuesti, kui need harva muutuvad? Vaatame, miks need ei ole vahem\u00e4lusse salvestunud. Asi on selles, et Docker kontrollib kihtide kaupa, kas k\u00e4sk ja sellega seotud failid on muutunud. Neljandas sammus kopeerime k\u00f5ik meie projekti failid, ja nende seas on loomulikult muudatusi, seega Docker ei kasuta mitte ainult seda kihti vahem\u00e4lust, vaid ka k\u00f5iki j\u00e4rgnevaid! Teeme Dockerfile'is v\u00e4ikeseid muudatusi.<\/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>Esiteks kopeeritakse package.json ja package-lock.json, seej\u00e4rel installitakse s\u00f5ltuvused ja alles siis kopeeritakse terve projekt. Tulemuseks:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSaatmine ehituse konteksti Docker daemonile 608.8kB\n1\/12 etapp: FROM node:12.16.2-alpine3.11 as builder\n2\/12 etapp: RUN apk --no-cache --update --virtual build-dependencies add python make g++\n ---&gt; Kasutatakse vahem\u00e4lu\n3\/12 etapp: WORKDIR \/app\n ---&gt; Kasutatakse vahem\u00e4lu\n4\/12 etapp: COPY package*.json .\/\n ---&gt; Kasutatakse vahem\u00e4lu\n5\/12 etapp: RUN npm ci\n ---&gt; Kasutatakse vahem\u00e4lu\n6\/12 etapp: COPY . .\n7\/12 etapp: RUN npm run build --prod\nKuup\u00e4ev: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Aeg: 38287ms\n ---&gt; 1b9448c73558\n8\/12 etapp: FROM nginx:stable-alpine\n9\/12 etapp: WORKDIR \/app\n ---&gt; Kasutatakse vahem\u00e4lu\n10\/12 etapp: RUN rm \/etc\/nginx\/conf.d\/default.conf\n ---&gt; Kasutatakse vahem\u00e4lu\n11\/12 etapp: COPY nginx\/static.conf \/etc\/nginx\/conf.d\n ---&gt; Kasutatakse vahem\u00e4lu\n12\/12 etapp: COPY --from=builder \/app\/dist\/app .\nEhitamine \u00f5nnestus a44dd7c217c3\nEhitamine m\u00e4rgitud: app:latest\n\nreaalne 0m46.497s\nkasutaja 0m0.000s\ns\u00fcsteem 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>46 sekundit, mitte 3 minutit \u2014 oluliselt parem! Oluline on kihtide \u00f5ige j\u00e4rjekord: esmalt kopeerime selle, mis ei muutu, seej\u00e4rel selle, mis harva muutub, ja l\u00f5puks \u2014 selle, mis tihti.<\/p>\n<p><\/p>\n<p>J\u00e4rgmine paar s\u00f5na piltide ehitamisest CI\/CD s\u00fcsteemides.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Eelnevate piltide kasutamine vahem\u00e4luna<\/h2>\n<p><\/p>\n<p>Kui kasutame m\u00f5nda SaaS-lahendust kogumise jaoks, v\u00f5ib kohalik Docker vahem\u00e4lu olla t\u00fchi ja v\u00e4rske. Et Dockeril oleks kustki v\u00f5tta k\u00fcpsetatud kihte, andke talle eelnevalt koostatud pilt.<\/p>\n<p><\/p>\n<p>Vaadakem n\u00e4iteks meie rakenduse ehitamist GitHub Actions'is. Kasutame sellist konfi<\/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>Pildi loomine ja saatmine GitHub Packages'i kestab kaks minutit ja 20 sekundit:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>N\u00fc\u00fcd muudame ehituse nii, et kasutatakse eelmisel korral loodud piltide p\u00f5hjal cache'i:<\/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>Esiteks tuleb r\u00e4\u00e4kida, miks k\u00e4ivitatakse kaks k\u00e4sku <code>build<\/code>. Asi on selles, et mitmestastilise ehituse tulemusena on l\u00f5pp-produkt viimasest etapist koosnev kihistikum. Samal ajal ei p\u00e4\u00e4se eelmistest kihtidest loodud kihid pildisse. Seet\u00f5ttu, kui kasutada viimase ehituse l\u00f5pp-pilti, ei suuda Docker leida valmis kihte Node.js pildi (ehituse etapp) jaoks. Selle probleemi lahendamiseks luuakse vahepealne pilt <code>$IMAGE_NAME-builder-stage<\/code> ja saadetakse GitHub Packages'isse, et saaks seda j\u00e4rgmises ehituses kasutada cache'i allikana.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kokkuv\u00f5ttes on ehitamise aeg l\u00fchenenud \u00fchele ja poolele minutile. Pool minutit kulub eelnevate piltide allalaadimisele.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">Eelneva pildi loomine<\/h2>\n<p><\/p>\n<p>Veel, kuidas lahendada puhta docker-kihi probleemi, on osa kihtidest viia teise Dockerfile'i, koguda see eraldi, pushida see Container Registry'sse ja kasutada seda vanemana.<\/p>\n<p><\/p>\n<p>Loome oma nodejs pildi Angular-rakenduse ehitamiseks. Loome projektis Dockerfile.node.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11\nRUN apk --no-cache --update --virtual ehitus-s\u00f5ltuvused lisada \n    python \n    make \n    g++<\/code><\/pre>\n<p><\/p>\n<p>Kogume ja pushime avaliku pildi Docker Hub'i:<\/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>N\u00fc\u00fcd kasutame meie p\u00f5hikanalis valmis pilti:<\/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>Meie n\u00e4ites ei v\u00e4henenud ehitusaeg, kuid eelnevalt loodud pildid v\u00f5ivad olla kasulikud, kui teil on palju projekte ja igas neist tuleb paigaldada sama s\u00f5ltuvus.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide koostamise kiirendamiseks. N\u00e4iteks kuni 30 sekundit.\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oleme vaadanud mitmeid meetodeid docker-piltide ehituse kiirusel. Kui soovite, et juurutamine oleks kiire, proovige oma projektis rakendada:<\/p>\n<p><\/p>\n<ul>\n<li>konteksti v\u00e4hendamine;<\/li>\n<li>v\u00e4ikeste vanemate piltide kasutamine;<\/li>\n<li>mitmeastmelist ehitamist;<\/li>\n<li>Dockerfile'i k\u00e4skude j\u00e4rjekorra muutmine, et t\u00f5husalt kasutada vahem\u00e4lu;<\/li>\n<li>vahem\u00e4lu seadistamine CI\/CD s\u00fcsteemides;<\/li>\n<li>eelnevalt loodud piltide tegemine.<\/li>\n<\/ul>\n<p><\/p>\n<p>Loodetavasti selgub n\u00e4itest, kuidas Docker t\u00f6\u00f6tab, ja suudate oma juurutuse optimaalselt seadistada. Artikli n\u00e4idistega m\u00e4ngimiseks on loodud hoidla. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>Allikas: <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.1.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\/et\/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.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\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\/et\/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\udd47M\u00f5ned n\u00e4pun\u00e4ited Docker-piltide ehituse kiirusel. N\u00e4iteks kuni 30 sekundit | ProHoster","description":"Enne kui funktsioon j\u00f5uab tootmisse, peab t\u00e4nap\u00e4eval keeruliste orkestraatorite ja CI\/CD kaudu l\u00e4bima pika tee commit'ist testideni ja kohaletoimetamiseni.","canonical_url":"https:\/\/prohoster.info\/et\/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":"et_EE","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\/et\/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\/et\/wp-json\/wp\/v2\/posts\/81600","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}