{"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\/cs\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>P\u0159ed t\u00edm, ne\u017e se funkce dostane na produkci, je t\u0159eba proj\u00edt dlouhou cestou od commitu p\u0159es testy a\u017e k nasazen\u00ed v dne\u0161n\u00ed dob\u011b slo\u017eit\u00fdch orchestr\u00e1tor\u016f a CI\/CD. D\u0159\u00edve sta\u010dilo nahr\u00e1t nov\u00e9 soubory pomoc\u00ed FTP (to u\u017e dnes nikdo ned\u011bl\u00e1, \u017ee?), a proces \u201edeploy\u201c trval sekundy. Dnes je nutn\u00e9 vytvo\u0159it merge request a \u010dekat, ne\u017e se funkce dostane k u\u017eivatel\u016fm.<\/p>\n<p><\/p>\n<p>\u010c\u00e1st z t\u00e9to cesty je build Docker obrazu. N\u011bkdy build trv\u00e1 minuty, jindy des\u00edtky minut, co\u017e se t\u011b\u017eko d\u00e1 pova\u017eovat za norm\u00e1ln\u00ed. V tomto \u010dl\u00e1nku vezmeme jednoduchou aplikaci, zabal\u00edme ji do obrazu, pou\u017eijeme n\u011bkolik metod pro zrychlen\u00ed buildu a prozkoum\u00e1me nuance t\u011bchto metod.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" 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>M\u00e1me slu\u0161n\u00e9 zku\u0161enosti s vytv\u00e1\u0159en\u00edm a \u00fadr\u017ebou web\u016f pro m\u00e9dia: <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\/\">\"Nov\u00e1 gazeta\"<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>\u2026 Ned\u00e1vno jsme roz\u0161\u00ed\u0159ili na\u0161e portfolio t\u00edm, \u017ee jsme spustili web <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>. A zat\u00edmco jsme rychle dod\u011bl\u00e1vali nov\u00e9 funkce a opravovali star\u00e9 chyby, pomal\u00fd deploy se stal velk\u00fdm probl\u00e9mem.<\/p>\n<p><\/p>\n<p>Deploy prov\u00e1d\u00edme na GitLab. Vytv\u00e1\u0159\u00edme obrazy, pushujeme do GitLab Registry a nasazujeme na produkci. Nejdel\u0161\u00ed \u010d\u00e1st\u00ed tohoto procesu je pr\u00e1v\u011b build obraz\u016f. Nap\u0159\u00edklad: bez optimalizace ka\u017ed\u00fd build backendu trval 14 minut.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nakonec se uk\u00e1zalo, \u017ee takto \u017e\u00edt nelze, a usadili jsme se, abychom zjistili, pro\u010d trv\u00e1 build obraz\u016f tak dlouho. Nakonec se n\u00e1m poda\u0159ilo zkr\u00e1tit dobu buildu na 30 sekund!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pro tento \u010dl\u00e1nek, abychom se nev\u00e1zali na prost\u0159ed\u00ed Reminderu, si vezmeme p\u0159\u00edklad vytvo\u0159en\u00ed pr\u00e1zdn\u00e9 aplikace na Angular. Tak\u017ee vytvo\u0159\u00edme na\u0161i aplikaci:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>P\u0159id\u00e1me do n\u00ed PWA (jsme p\u0159ece progresivn\u00ed):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>Zat\u00edmco se stahuje milion npm bal\u00ed\u010dk\u016f, pod\u00edvejme se, jak funguje docker obraz. Docker umo\u017e\u0148uje balit aplikace a spou\u0161t\u011bt je v izolovan\u00e9m prost\u0159ed\u00ed, kter\u00e9 se naz\u00fdv\u00e1 kontejner. D\u00edky izolaci m\u016f\u017eeme spou\u0161t\u011bt v\u00edce kontejner\u016f na jednom serveru. Kontajnery jsou mnohem leh\u010d\u00ed ne\u017e virtu\u00e1ln\u00ed stroje, proto\u017ee b\u011b\u017e\u00ed p\u0159\u00edmo na j\u00e1dru syst\u00e9mu. Abychom spustili kontejner s na\u0161\u00ed aplikac\u00ed, mus\u00edme nejd\u0159\u00edve vytvo\u0159it obraz, do kter\u00e9ho zabal\u00edme v\u0161e, co je pot\u0159eba pro b\u011bh na\u0161\u00ed aplikace. V podstat\u011b je obraz otiskem souborov\u00e9ho syst\u00e9mu. Nap\u0159\u00edklad, vezmeme 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 je sada pokyn\u016f; p\u0159i vykon\u00e1v\u00e1n\u00ed ka\u017ed\u00e9ho z nich Docker ulo\u017e\u00ed zm\u011bny do souborov\u00e9ho syst\u00e9mu a aplikuje je na p\u0159edchoz\u00ed. Ka\u017ed\u00fd p\u0159\u00edkaz vytv\u00e1\u0159\u00ed svou vlastn\u00ed vrstvu. Hotov\u00fd obraz je pak spojen\u00edm t\u011bchto vrstev.<\/p>\n<p><\/p>\n<p>Co je d\u016fle\u017eit\u00e9 v\u011bd\u011bt: ka\u017ed\u00e1 vrstva m\u016f\u017ee b\u00fdt cachov\u00e1na. Pokud se nic nezm\u011bnilo od posledn\u00ed kompilace, Docker m\u00edsto vykon\u00e1v\u00e1n\u00ed p\u0159\u00edkazu vezme ji\u017e hotovou vrstvu. Hlavn\u00ed p\u0159\u00ednos v rychlosti kompilace bude d\u00edky vyu\u017e\u00edv\u00e1n\u00ed cach\u00ed, a proto se p\u0159i m\u011b\u0159en\u00ed rychlosti kompilace budeme soust\u0159edit pr\u00e1v\u011b na kompilaci obrazu s ji\u017e p\u0159ipravenou cache. Tak\u017ee postupn\u011b:<\/p>\n<p><\/p>\n<ol>\n<li>Odstra\u0148ujeme obrazy lok\u00e1ln\u011b, aby p\u0159edchoz\u00ed spu\u0161t\u011bn\u00ed neovlivnila test.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>Spou\u0161t\u00edme build poprv\u00e9.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>M\u011bn\u00edme soubor src\/index.html \u2013 imitujeme pr\u00e1ci program\u00e1tora.<\/li>\n<li>Spou\u0161t\u00edme build podruh\u00e9.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Pokud je prost\u0159ed\u00ed pro budov\u00e1n\u00ed obraz\u016f spr\u00e1vn\u011b nakonfigurov\u00e1no (o \u010dem\u017e bude \u0159e\u010d n\u00ed\u017ee), Docker p\u0159i spu\u0161t\u011bn\u00ed build bude m\u00edt k dispozici spoustu cach\u00ed. Na\u0161\u00edm \u00fakolem je nau\u010dit se vyu\u017e\u00edvat cache tak, aby kompilace prob\u00edhala co nejrychleji. P\u0159edpokl\u00e1d\u00e1me, \u017ee spu\u0161t\u011bn\u00ed build bez cache prob\u00edh\u00e1 jen jednou \u2013 poprv\u00e9 \u2013 tedy m\u016f\u017eeme ignorovat, jak pomal\u00e9 bylo toto prvn\u00ed spu\u0161t\u011bn\u00ed. V testech je pro n\u00e1s d\u016fle\u017eit\u00fd druh\u00fd b\u011bh kompilace, kdy jsou cache ji\u017e aktivov\u00e1ny a jsme p\u0159ipraveni p\u00e9ct n\u00e1\u0161 kol\u00e1\u010d. Nicm\u00e9n\u011b n\u011bkter\u00e9 rady se projev\u00ed u\u017e p\u0159i prvn\u00edm buildov\u00e1n\u00ed.<\/p>\n<p><\/p>\n<p>Ulo\u017e\u00edme v\u00fd\u0161e popsan\u00fd Dockerfile do slo\u017eky s projektem a spust\u00edme build. V\u0161echny uveden\u00e9 \u00faryvky byly zkr\u00e1ceny pro snaz\u0161\u00ed \u010dten\u00ed.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nOdes\u00edl\u00e1n\u00ed kontextu build do Docker d\u00e9mona 409MB\nKrok 1\/5 : FROM node:12.16.2\nStav: St\u00e1hnuta nov\u011bj\u0161\u00ed verze obrazu pro node:12.16.2\nKrok 2\/5 : WORKDIR \/app\nKrok 3\/5 : COPY . .\nKrok 4\/5 : RUN npm ci\np\u0159id\u00e1no 1357 bal\u00ed\u010dk\u016f za 22.47s\nKrok 5\/5 : RUN npm run build --prod\nDatum: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - \u010cas: 37581ms\n\u00dasp\u011b\u0161n\u011b vytvo\u0159eno c8c279335f46\n\u00dasp\u011b\u0161n\u011b ozna\u010deno app:latest\n\nskute\u010dn\u00fd 5m4.541s\nu\u017eivatelsk\u00fd 0m0.000s\nsyst\u00e9mov\u00fd 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>M\u011bn\u00edme obsah src\/index.html a spou\u0161t\u00edme podruh\u00e9.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nOdes\u00edl\u00e1n\u00ed kontextu build do Docker d\u00e9mona 409MB\nKrok 1\/5 : FROM node:12.16.2\nKrok 2\/5 : WORKDIR \/app\n ---&gt; Pou\u017e\u00edv\u00e1 cache\nKrok 3\/5 : COPY . .\nKrok 4\/5 : RUN npm ci\np\u0159id\u00e1no 1357 bal\u00ed\u010dk\u016f za 22.47s\nKrok 5\/5 : RUN npm run build --prod\nDatum: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - \u010cas: 37902ms\n\u00dasp\u011b\u0161n\u011b vytvo\u0159eno 79f335df92d3\n\u00dasp\u011b\u0161n\u011b ozna\u010deno app:latest\n\nskute\u010dn\u00fd 3m33.262s\nu\u017eivatelsk\u00fd 0m0.000s\nsyst\u00e9mov\u00fd 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>Abychom zjistili, jestli jsme \u00fasp\u011b\u0161n\u011b vytvo\u0159ili obraz, provedeme p\u0159\u00edkaz <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   P\u0159ed asi minutou   1.74GB<\/code><\/pre>\n<p><\/p>\n<p>P\u0159ed sestaven\u00edm Docker shrom\u00e1\u017ed\u00ed v\u0161echny soubory v aktu\u00e1ln\u00edm kontextu a ode\u0161le je sv\u00e9mu d\u00e9monu. <code>Odes\u00edl\u00e1n\u00ed kontextu sestaven\u00ed do d\u00e9monu Docker 409MB<\/code>. Kontext pro sestaven\u00ed se uv\u00e1d\u00ed jako posledn\u00ed argument p\u0159\u00edkazu build. V na\u0161em p\u0159\u00edpad\u011b je to aktu\u00e1ln\u00ed adres\u00e1\u0159 \u2013 \u201e.\u201c, \u2013 a Docker p\u0159en\u00e1\u0161\u00ed v\u0161echno, co m\u00e1me v t\u00e9to slo\u017ece. 409 MB je hodn\u011b: p\u0159em\u00fd\u0161lejme, jak to napravit.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">Sni\u017eujeme kontext<\/h2>\n<p><\/p>\n<p>Abychom sn\u00ed\u017eili kontext, existuj\u00ed dv\u011b mo\u017enosti. Bu\u010f p\u0159esunout v\u0161echny soubory pot\u0159ebn\u00e9 pro sestaven\u00ed do samostatn\u00e9 slo\u017eky a poskytnout kontext Dockeru pr\u00e1v\u011b na tuto slo\u017eku. To nemus\u00ed b\u00fdt v\u017edy pohodln\u00e9, a proto m\u00e1me mo\u017enost uv\u00e9st v\u00fdjimky: co nemus\u00edme p\u0159en\u00e1\u0161et do kontextu. K tomu p\u0159id\u00e1me do projektu soubor .dockerignore a uvedeme, co nen\u00ed pot\u0159eba pro sestaven\u00ed:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>a spust\u00edme sestaven\u00ed znovu:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nOdes\u00edl\u00e1n\u00ed kontextu sestaven\u00ed do d\u00e9monu Docker 607.2kB\nKrok 1\/5 : Z FROM node:12.16.2\nKrok 2\/5 : WORKDIR \/app\n ---&gt; Pou\u017eit\u00ed vyrovn\u00e1vac\u00ed pam\u011bti\nKrok 3\/5 : COPY . .\nKrok 4\/5 : RUN npm ci\np\u0159id\u00e1no 1357 bal\u00ed\u010dk\u016f za 22.47s\nKrok 5\/5 : RUN npm run build --prod\nDatum: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - \u010cas: 37313ms\n\u00dasp\u011b\u0161n\u011b sestaveno 4942f010792a\n\u00dasp\u011b\u0161n\u011b ozna\u010deno app:latest\n\nre\u00e1ln\u00e9 1m47.763s\nu\u017eivatel 0m0.000s\nsyst\u00e9m 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607.2 Kb \u2014 mnohem lep\u0161\u00ed ne\u017e 409 MB. A je\u0161t\u011b jsme zmen\u0161ili velikost obrazu z 1.74 na 1.38GB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSIT\u00c1\u0158   TAG      ID OBRAZU       VYTVO\u0158ENO         VELIKOST\napp          latest   4942f010792a   p\u0159ed 3 minutami   1.38GB<\/code><\/pre>\n<p><\/p>\n<p>Zkusme obraz zmen\u0161it je\u0161t\u011b v\u00edce.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Pou\u017e\u00edv\u00e1me Alpine<\/h2>\n<p><\/p>\n<p>Dal\u0161\u00edm zp\u016fsobem, jak u\u0161et\u0159it na velikosti obrazu, je pou\u017e\u00edt mal\u00fd z\u00e1kladn\u00ed obraz. Z\u00e1kladn\u00ed obraz je obraz, na jeho\u017e z\u00e1klad\u011b je n\u00e1\u0161 obraz p\u0159ipravov\u00e1n. Spodn\u00ed vrstvu uv\u00e1d\u00edme p\u0159\u00edkazem <code>FROM<\/code> v Dockerfile. V na\u0161em p\u0159\u00edpad\u011b pou\u017e\u00edv\u00e1me obraz zalo\u017een\u00fd na Ubuntu, kter\u00fd ji\u017e m\u00e1 nainstalovan\u00fd nodejs. A jeho v\u00e1ha je \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c p\u0159ed 17 minutami 916MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 t\u00e9m\u011b\u0159 gigabyte. V\u00fdrazn\u011b sn\u00ed\u017eit objem lze pou\u017eit\u00edm obrazu zalo\u017een\u00e9ho na Alpine Linux. Alpine je velmi mal\u00fd linux. Docker obraz pro nodejs na z\u00e1klad\u011b Alpine v\u00e1\u017e\u00ed pouze 88.5 MB. Tak\u017ee poj\u010fme nahradit n\u00e1\u0161 tlust\u00fd z\u00e1kladn\u00ed obraz:<\/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>Museli jsme nainstalovat n\u011bkter\u00e9 v\u011bci, kter\u00e9 jsou pot\u0159ebn\u00e9 pro sestaven\u00ed aplikace. Ano, Angular se nesestav\u00ed bez Pythona \u00af(\u00b0_o)\u00af<\/p>\n<p><\/p>\n<p>Ale velikost obrazu klesla o 150 MB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSIT\u00c1\u0158   TAG      ID OBRAZU       VYTVO\u0158ENO          VELIKOST\napp          latest   aa031edc315a   p\u0159ed 22 minutami   761MB<\/code><\/pre>\n<p><\/p>\n<p>Jdeme d\u00e1l.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">V\u00edce f\u00e1z\u00ed sestaven\u00ed<\/h2>\n<p><\/p>\n<p>Ne v\u0161echno, co je v obraze, pot\u0159ebujeme v produkci.<\/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>Pomoc\u00ed <code>docker run app ls -lah<\/code> Spustili jsme kontejner na z\u00e1klad\u011b na\u0161eho obrazu <code>app<\/code> a vykonali v n\u011bm p\u0159\u00edkaz <code>ls -lah<\/code>, po kter\u00e9m kontejner ukon\u010dil svou \u010dinnost.<\/p>\n<p><\/p>\n<p>Na produkci pot\u0159ebujeme pouze slo\u017eku <code>dist<\/code>. P\u0159itom je pot\u0159eba n\u011bjak\u00fdm zp\u016fsobem sd\u00edlet soubory ven. M\u016f\u017eeme spustit n\u011bjak\u00fd HTTP server na nodejs. Ale ud\u011bl\u00e1me to jednodu\u0161e. Uhodn\u011bte rusk\u00e9 slovo, kter\u00e9 m\u00e1 \u010dty\u0159i p\u00edsmena \u201e\u044b\u201c. Spr\u00e1vn\u011b! \u042b\u043d\u0436\u044b\u043d\u044b\u043a\u0441\u044b. Vezmeme obraz s nginx, vlo\u017e\u00edme do n\u011bj slo\u017eku <code>dist<\/code> a mal\u00fd konfigur\u00e1k:<\/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>To v\u0161e n\u00e1m pom\u016f\u017ee prov\u00e9st multi-stage build. Zm\u011bn\u00edme n\u00e1\u0161 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>Te\u010f m\u00e1me dv\u011b instrukce <code>FROM<\/code> v Dockerfile, ka\u017ed\u00e1 z nich spou\u0161t\u00ed sv\u016fj f\u00e1zi sestaven\u00ed. Prvn\u00ed jsme nazvali <code>builder<\/code>, ale od posledn\u00edho FROM se bude p\u0159ipravovat n\u00e1\u0161 fin\u00e1ln\u00ed obraz. Posledn\u00edm krokem je zkop\u00edrovat artefakt na\u0161eho sestaven\u00ed z p\u0159edchoz\u00ed f\u00e1ze do fin\u00e1ln\u00edho obrazu s nginx. Velikost obrazu se v\u00fdznamn\u011b zmen\u0161ila:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   2c6c5da07802   p\u0159ed 29 minutami   36MB<\/code><\/pre>\n<p><\/p>\n<p>Poj\u010fme spustit kontejner s na\u0161\u00edm obrazem a ujist\u011bme se, \u017ee v\u0161e funguje:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>S parametrem -p8080:80 jsme propojili port 8080 na na\u0161em hostitelsk\u00e9m stroji s portem 80 uvnit\u0159 kontejneru, kde b\u011b\u017e\u00ed nginx. Otev\u0159eme v prohl\u00ed\u017ee\u010di <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> a vid\u00edme na\u0161i aplikaci. V\u0161e funguje!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sn\u00ed\u017een\u00ed velikosti obrazu z 1,74 GB na 36 MB v\u00fdrazn\u011b zkracuje dobu dod\u00e1n\u00ed va\u0161\u00ed aplikace do produkce. Ale vra\u0165me se k \u010dasu sestaven\u00ed.<\/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\">M\u011bn\u00edme po\u0159ad\u00ed vrstev<\/h2>\n<p><\/p>\n<p>Prvn\u00ed t\u0159i kroky byly vyrovn\u00e1v\u00e1ny (n\u00e1pov\u011bda <code>Using cache<\/code>). V \u010dtvrt\u00e9m kroku se kop\u00edruj\u00ed v\u0161echny soubory projektu a v p\u00e1t\u00e9m kroku se instaluj\u00ed z\u00e1vislosti <code>RUN npm ci<\/code> \u2014 cel\u00fdch 47,338 s. Pro\u010d poka\u017ed\u00e9 znovu instalovat z\u00e1vislosti, kdy\u017e se m\u011bn\u00ed jen velmi z\u0159\u00eddka? Poj\u010fme si objasnit, pro\u010d se neulo\u017eily do cache. Je to t\u00edm, \u017ee Docker kontroluje vrstvu po vrstv\u011b, zda se nezm\u011bnily p\u0159\u00edkazy a souvisej\u00edc\u00ed soubory. Ve \u010dtvrt\u00e9m kroku kop\u00edrujeme v\u0161echny soubory na\u0161eho projektu a samoz\u0159ejm\u011b mezi nimi jsou zm\u011bny, tak\u017ee Docker nejen\u017ee nebere tuto vrstvu z cache, ale ani v\u0161echny n\u00e1sleduj\u00edc\u00ed! Poj\u010fme prov\u00e9st mal\u00e9 \u00fapravy v 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>Nejprve se zkop\u00edruj\u00ed package.json a package-lock.json, pot\u00e9 se nainstaluj\u00ed z\u00e1vislosti a a\u017e nakonec se zkop\u00edruje cel\u00fd projekt. V\u00fdsledek:<\/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 sekund m\u00edsto 3 minut \u2014 v\u00fdrazn\u011b lep\u0161\u00ed! D\u016fle\u017eit\u00fd je spr\u00e1vn\u00fd po\u0159\u00e1dek vrstev: nejprve kop\u00edrujeme to, co se nem\u011bn\u00ed, pot\u00e9 to, co se m\u011bn\u00ed z\u0159\u00eddka, a nakonec to, co se m\u011bn\u00ed \u010dasto.<\/p>\n<p><\/p>\n<p>D\u00e1le n\u011bkolik slov o sestaven\u00ed obraz\u016f v CI\/CD syst\u00e9mech.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Pou\u017eit\u00ed p\u0159edchoz\u00edch obraz\u016f pro cache<\/h2>\n<p><\/p>\n<p>Pokud pou\u017e\u00edv\u00e1me k sestaven\u00ed n\u011bjak\u00e9 SaaS \u0159e\u0161en\u00ed, m\u016f\u017ee b\u00fdt lok\u00e1ln\u00ed cache Dockeru \u010dist\u00e1 a \u010derstv\u00e1. Aby m\u011bl Docker odkud vz\u00edt upe\u010den\u00e9 vrstvy, dejte mu p\u0159edchoz\u00ed sestaven\u00fd obraz.<\/p>\n<p><\/p>\n<p>Pod\u00edvejme se na sestaven\u00ed na\u0161\u00ed aplikace v GitHub Actions. Pou\u017eijeme takovou konfiguraci.<\/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>Obraz je shrom\u00e1\u017ed\u011bn a nahr\u00e1n do GitHub Packages za dv\u011b minuty a 20 sekund:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nyn\u00ed zm\u011bn\u00edme sestaven\u00ed tak, aby pou\u017e\u00edvalo mezipam\u011b\u0165 zalo\u017eenou na p\u0159edchoz\u00edch shrom\u00e1\u017ed\u011bn\u00fdch obrazech:<\/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>Nejprve je t\u0159eba vysv\u011btlit, pro\u010d se spou\u0161t\u00ed dv\u011b p\u0159\u00edkazy <code>build<\/code>. To je proto, \u017ee v multi-stage sestaven\u00ed bude v\u00fdsledn\u00fdm obrazem sada vrstev z posledn\u00ed f\u00e1ze. P\u0159itom vrstvy z p\u0159edchoz\u00edch vrstev nebyly zahrnuty do obrazu. Proto, kdy\u017e se pou\u017e\u00edv\u00e1 kone\u010dn\u00fd obraz z p\u0159edchoz\u00edho sestaven\u00ed, Docker nebude moci naj\u00edt p\u0159ipraven\u00e9 vrstvy pro sestaven\u00ed obrazu s nodejs (f\u00e1ze builder). Abychom tento probl\u00e9m vy\u0159e\u0161ili, vytvo\u0159\u00edme meziprochodn\u00fd obraz <code>$IMAGE_NAME-builder-stage<\/code> a ode\u0161leme ho do GitHub Packages, aby ho bylo mo\u017en\u00e9 pou\u017e\u00edt v n\u00e1sledn\u00e9m sestaven\u00ed jako zdroj mezipam\u011bti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Celkov\u00fd \u010das sestaven\u00ed se zkr\u00e1til na jednu a p\u016fl minuty. P\u016fl minuty se ztr\u00e1c\u00ed p\u0159i stahov\u00e1n\u00ed p\u0159edchoz\u00edch obraz\u016f.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">P\u0159edb\u011b\u017en\u00e9 vytvo\u0159en\u00ed obraz\u016f<\/h2>\n<p><\/p>\n<p>Dal\u0161\u00ed zp\u016fsob, jak vy\u0159e\u0161it probl\u00e9m s \u010distou mezipam\u011bt\u00ed Dockeru, je \u010d\u00e1st vrstev vy\u010dlenit do jin\u00e9ho Dockerfile, sestavit ho samostatn\u011b, nahr\u00e1t do Container Registry a pou\u017e\u00edt jako rodi\u010dovsk\u00fd.<\/p>\n<p><\/p>\n<p>Vytv\u00e1\u0159\u00edme sv\u016fj obraz nodejs pro sestaven\u00ed Angular aplikace. V projektu vytvo\u0159te Dockerfile.node<\/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>Sestavujeme a nahr\u00e1v\u00e1me ve\u0159ejn\u00fd obraz do 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>Nyn\u00ed v na\u0161em hlavn\u00edm Dockerfile pou\u017eijeme hotov\u00fd obraz:<\/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>V na\u0161em p\u0159\u00edkladu se doba sestaven\u00ed nezkr\u00e1tila, ale p\u0159edem vytvo\u0159en\u00e9 obrazy mohou b\u00fdt u\u017eite\u010dn\u00e9, pokud m\u00e1te mnoho projekt\u016f a v ka\u017ed\u00e9m z nich mus\u00edte instalovat stejn\u00e9 z\u00e1vislosti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"N\u011bkolik tip\u016f, jak zrychlit build Docker obraz\u016f. Nap\u0159\u00edklad na 30 sekund.\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Prozkoumali jsme n\u011bkolik metod zrychlen\u00ed sestaven\u00ed docker obraz\u016f. Pokud chcete, aby nasazen\u00ed prob\u00edhalo rychle, zkuste ve sv\u00e9m projektu pou\u017e\u00edt:<\/p>\n<p><\/p>\n<ul>\n<li>sn\u00ed\u017een\u00ed kontextu;<\/li>\n<li>pou\u017e\u00edv\u00e1n\u00ed mal\u00fdch rodi\u010dovsk\u00fdch obraz\u016f;<\/li>\n<li>multi-stage build;<\/li>\n<li>zm\u011bnu po\u0159ad\u00ed instrukc\u00ed v Dockerfile, aby bylo mo\u017en\u00e9 efektivn\u011b vyu\u017e\u00edt mezipam\u011b\u0165;<\/li>\n<li>nastaven\u00ed mezipam\u011bti v CI\/CD syst\u00e9mech;<\/li>\n<li>p\u0159edb\u011b\u017en\u00e9 vytv\u00e1\u0159en\u00ed obraz\u016f.<\/li>\n<\/ul>\n<p><\/p>\n<p>Douf\u00e1m, \u017ee na p\u0159\u00edkladu bude jasn\u011bj\u0161\u00ed, jak Docker funguje, a budete moci optim\u00e1ln\u011b nastavit sv\u00e9 nasazen\u00ed. Abychom si mohli vyzkou\u0161et p\u0159\u00edklady z \u010dl\u00e1nku, byl vytvo\u0159en repozit\u00e1\u0159 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>Zdroj: <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.3 - 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\/cs\/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.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"cs_CZ\" \/>\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\/cs\/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\udd47N\u011bkolik tip\u016f, jak zrychlit sestaven\u00ed Docker obraz\u016f. Nap\u0159\u00edklad a\u017e 30 sekund | ProHoster","description":"Ne\u017e se funkce dostane do produkce, v dne\u0161n\u00ed dob\u011b slo\u017eit\u00fdch orchestr\u00e1tor\u016f a CI\/CD je t\u0159eba proj\u00edt dlouhou cestu od commitu po testy a dod\u00e1n\u00ed.","canonical_url":"https:\/\/prohoster.info\/cs\/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":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/81600","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}