{"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\/da\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>F\u00f8r en feature g\u00e5r i produktion, skal den i dag gennem en lang vej fra commit til tests og deployment i en verden med komplekse orkestratorer og CI\/CD. Tidligere kunne man blot uploade nye filer via FTP (det g\u00f8r ingen l\u00e6ngere, vel?), og deployeringsprocessen tog sekunder. Nu skal man oprette en merge request og vente en del tid, f\u00f8r funktionen n\u00e5r brugerne.<\/p>\n<p><\/p>\n<p>En del af denne rejse er opbygningen af Docker-billedet. Nogle gange tager opbygningen minutter, nogle gange - titusinder af minutter, hvilket er sv\u00e6rt at kalde normalt. I denne artikel vil vi tage en simpel applikation, pakke den ind i et billede, anvende forskellige metoder til at fremskynde opbygningen og se p\u00e5 nuancerne i disse metoder.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/7d4775ca1ac64735dfcaba205416da50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Vi har en god erfaring med at oprette og supportere nyhedswebsites: <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;Nye avis&quot;<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>\u2026 For nylig udvidede vi vores portef\u00f8lje ved at lancere et website i produktion. <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>. Og mens vi hurtigt f\u00e6rdiggjorde nye features og rettede gamle fejl, blev den langsomme deployment et stort problem.<\/p>\n<p><\/p>\n<p>Vi foretager deployment p\u00e5 GitLab. Vi bygger billeder, pusher dem til GitLab Registry og udruller dem i produktion. Det, der tager l\u00e6ngst tid i denne proces, er opbygningen af billederne. Som eksempel: uden optimering tog hver backend-opbygning 14 minutter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Til sidst blev det klart, at vi ikke kunne forts\u00e6tte s\u00e5dan, s\u00e5 vi satte os ned for at finde ud af, hvorfor billederne tog s\u00e5 lang tid at opbygge. I sidste ende lykkedes det os at reducere opbygningstiden til 30 sekunder!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>For denne artikel, for ikke at knytte os til Reminder&#8217;s milj\u00f8, lad os se p\u00e5 et eksempel p\u00e5 opbygning af en tom applikation i Angular. S\u00e5 lad os oprette vores applikation:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>Vi tilf\u00f8jer PWA (vi er jo progressive):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>Mens millioner af npm-pakker downloades, lad os se p\u00e5, hvordan docker-billedet er opbygget. Docker giver mulighed for at pakke applikationer og k\u00f8re dem i et isoleret milj\u00f8 kaldet en container. Takket v\u00e6re isolation kan man k\u00f8re mange containere samtidigt p\u00e5 en server. Containere er betydeligt lettere end virtuelle maskiner, da de k\u00f8rer direkte p\u00e5 systemets kerne. For at k\u00f8re en container med vores applikation skal vi f\u00f8rst oprette et billede, hvor vi pakker alt, hvad der er n\u00f8dvendigt for at k\u00f8re vores applikation. I bund og grund er et billede et aftryk af filsystemet. For eksempel, lad os tage 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 er et s\u00e6t af instruktioner; ved at udf\u00f8re hver enkelt vil Docker gemme \u00e6ndringer i filsystemet og anvende dem p\u00e5 de tidligere. Hver kommando skaber sit lag. Det f\u00e6rdige billede er en samling af lagene.<\/p>\n<p><\/p>\n<p>Det er vigtigt at vide: hvert lag kan Docker cache. Hvis intet har \u00e6ndret sig siden den sidste bygning, vil Docker tage det allerede f\u00e6rdige lag i stedet for at udf\u00f8re kommandoen. Da den vigtigste hastighedsfor\u00f8gelse i bygningen vil v\u00e6re gennem brug af cache, vil vi i m\u00e5linger af byggehastighed s\u00e6rligt fokusere p\u00e5 bygningen af billedet med den eksisterende cache. S\u00e5 lad os g\u00e5 i gang:<\/p>\n<p><\/p>\n<ol>\n<li>Vi fjerner billeder lokalt, s\u00e5 tidligere k\u00f8rsel ikke p\u00e5virker testen.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>Vi k\u00f8rer bygningen f\u00f8rste gang.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>Vi \u00e6ndrer filen src\/index.html \u2014 simulerer programm\u00f8rens arbejde.<\/li>\n<li>Vi k\u00f8rer bygningen anden gang.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Hvis milj\u00f8et for at bygge billeder er korrekt konfigureret (som beskrevet lidt senere), vil Docker allerede have en masse caches tilg\u00e6ngelige, n\u00e5r bygningen startes. Vores opgave er at l\u00e6re at bruge cachen, s\u00e5 bygningen forl\u00f8ber s\u00e5 hurtigt som muligt. Da vi antager, at bygningen uden cache kun sker \u00e9n gang \u2014 den allerf\u00f8rste \u2014 kan vi ignorere, hvor langsom denne f\u00f8rste gang var. I vores tests er den anden bygning vigtig, n\u00e5r cachen allerede er klar, og vi er klar til at bage vores kage. Ikke desto mindre vil nogle r\u00e5d ogs\u00e5 p\u00e5virke den f\u00f8rste bygning.<\/p>\n<p><\/p>\n<p>Lad os placere Dockerfile, som beskrevet ovenfor, i projektmappen og starte bygningen. Alle n\u00e6vnte lister er forkortet for at lette l\u00e6sningen.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 409MB\nStep 1\/5 : FROM node:12.16.2\nStatus: Downloaded newer image for node:12.16.2\nStep 2\/5 : WORKDIR \/app\nStep 3\/5 : COPY . .\nStep 4\/5 : RUN npm ci\nadded 1357 packages in 22.47s\nStep 5\/5 : RUN npm run build --prod\nDate: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Time: 37581ms\nSuccessfully built c8c279335f46\nSuccessfully tagged app:latest\n\nreal 5m4.541s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>Vi \u00e6ndrer indholdet i src\/index.html og k\u00f8rer den anden gang.<\/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>For at se, om vi har f\u00e5et billedet, k\u00f8rer vi kommandoen <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   For omkring et minut siden   1.74GB<\/code><\/pre>\n<p><\/p>\n<p>F\u00f8r Docker bygger, tager den alle filer i den nuv\u00e6rende kontekst og sender dem til sin demon <code>Sender byggekontext til Docker-demon 409MB<\/code>. Bygge konteksten angives som det sidste argument i build-kommandoen. I vores tilf\u00e6lde er det den nuv\u00e6rende mappe \u2014 \u00ab.\u00bb, \u2014 og Docker tr\u00e6kker alt, hvad vi har i denne mappe. 409 MB er meget: lad os overveje, hvordan vi kan l\u00f8se dette.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">Reducerer konteksten<\/h2>\n<p><\/p>\n<p>For at reducere konteksten er der to muligheder. Enten l\u00e6g alle filer, der er n\u00f8dvendige for bygningen, i en separat mappe og angiv konteksten til Docker specifikt til den mappe. Dette kan ikke altid v\u00e6re bekvemt, s\u00e5 der er mulighed for at angive undtagelser: hvad der ikke skal medtages i konteksten. For at g\u00f8re dette l\u00e6gger vi en .dockerignore-fil i projektet og angiver, hvad der ikke er n\u00f8dvendigt til bygningen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>og vi k\u00f8rer bygningen igen:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSender byggekontext til Docker-demon 607.2kB\nTrin 1\/5: FROM node:12.16.2\nTrin 2\/5: WORKDIR \/app\n ---&gt; Bruger cache\nTrin 3\/5: COPY . .\nTrin 4\/5: RUN npm ci\ntilf\u00f8jet 1357 pakker p\u00e5 22.47s\nTrin 5\/5: RUN npm run build --prod\nDato: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Tid: 37313ms\nSuccesfuldt bygget 4942f010792a\nSuccesfuldt m\u00e6rket app:latest\n\nreal 1m47.763s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607.2 Kbyte \u2014 meget bedre end 409 MB. Og vi har ogs\u00e5 reduceret st\u00f8rrelsen af billedet fra 1.74 til 1.38GB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED         SIZE\napp          latest   4942f010792a   3 minutter siden   1.38GB<\/code><\/pre>\n<p><\/p>\n<p>Lad os pr\u00f8ve at reducere billedst\u00f8rrelsen yderligere.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Bruger Alpine<\/h2>\n<p><\/p>\n<p>En anden m\u00e5de at spare p\u00e5 billedst\u00f8rrelsen \u2014 er at bruge et lille for\u00e6ldrebillede. For\u00e6ldrebilledet er det billede, vores billede er baseret p\u00e5. Den nederste lag angives med kommandoen <code>FROM<\/code> i Dockerfile. I vores tilf\u00e6lde er vi ved at bruge et billede baseret p\u00e5 Ubuntu, som allerede har nodejs installeret. Og det vejer \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c 17 minutter siden 916MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 n\u00e6sten en gigabyte. Man kan betydeligt reducere st\u00f8rrelsen ved at bruge et billede baseret p\u00e5 Alpine Linux. Alpine er en meget lille Linux. Docker-billedet for nodejs baseret p\u00e5 Alpine vejer kun 88.5 MB. S\u00e5 lad os erstatte vores fede for\u00e6ldrebillede med:<\/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>Vi m\u00e5tte installere nogle ting, der er n\u00f8dvendige for at bygge applikationen. Ja, Angular bygger ikke uden Python \u00af(\u00b0_o)\u00af<\/p>\n<p><\/p>\n<p>Men billedst\u00f8rrelsen faldt med 150 MB:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   aa031edc315a   22 minutter siden   761MB<\/code><\/pre>\n<p><\/p>\n<p>Vi g\u00e5r videre.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">Multi-stage bygning<\/h2>\n<p><\/p>\n<p>Ikke alt, hvad der er i billedet, er n\u00f8dvendigt for os i produktionen.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker run app ls -lah\ntotal 576K\ndrwxr-xr-x 1 root root 4.0K Apr 16 19:54 .\ndrwxr-xr-x 1 root root 4.0K Apr 16 20:00 ..\n-rwxr-xr-x 1 root root 19 Apr 17 2020 .dockerignore\n-rwxr-xr-x 1 root root 246 Apr 17 2020 .editorconfig\n-rwxr-xr-x 1 root root 631 Apr 17 2020 .gitignore\n-rwxr-xr-x 1 root root 181 Apr 17 2020 Dockerfile\n-rwxr-xr-x 1 root root 1020 Apr 17 2020 README.md\n-rwxr-xr-x 1 root root 3.6K Apr 17 2020 angular.json\n-rwxr-xr-x 1 root root 429 Apr 17 2020 browserslist\ndrwxr-xr-x 3 root root 4.0K Apr 16 19:54 dist\ndrwxr-xr-x 3 root root 4.0K Apr 17 2020 e2e\n-rwxr-xr-x 1 root root 1015 Apr 17 2020 karma.conf.js\n-rwxr-xr-x 1 root root 620 Apr 17 2020 ngsw-config.json\ndrwxr-xr-x 1 root root 4.0K Apr 16 19:54 node_modules\n-rwxr-xr-x 1 root root 494.9K Apr 17 2020 package-lock.json\n-rwxr-xr-x 1 root root 1.3K Apr 17 2020 package.json\ndrwxr-xr-x 5 root root 4.0K Apr 17 2020 src\n-rwxr-xr-x 1 root root 210 Apr 17 2020 tsconfig.app.json\n-rwxr-xr-x 1 root root 489 Apr 17 2020 tsconfig.json\n-rwxr-xr-x 1 root root 270 Apr 17 2020 tsconfig.spec.json\n-rwxr-xr-x 1 root root 1.9K Apr 17 2020 tslint.json<\/code><\/pre>\n<p><\/p>\n<p>Ved hj\u00e6lp af <code>docker run app ls -lah<\/code> Vi har startet en container baseret p\u00e5 vores billede <code>app<\/code> og udf\u00f8rt kommandoen i den <code>ls -lah<\/code>, hvorefter containeren blev stoppet.<\/p>\n<p><\/p>\n<p>I produktionen har vi kun brug for mappen <code>dist<\/code>. Files skal deles p\u00e5 en eller anden m\u00e5de. Vi kan starte en HTTP-server med nodejs. Men vi g\u00f8r det lettere. G\u00e6t det russiske ord, der har fire bogstaver '\u044b'. Rigtigt! \u042b\u043d\u0436\u044b\u043d\u044b\u043a\u0441\u044b. Vi tager et billede med nginx, l\u00e6gger mappen <code>dist<\/code> og en lille konfiguration:<\/p>\n<p><\/p>\n<pre><code class=\"nginx\">server {\n    listen 80 default_server;\n    server_name localhost;\n    charset utf-8;\n    root \/app\/dist;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.html;\n    }\n}<\/code><\/pre>\n<p><\/p>\n<p>Multi-stage build vil hj\u00e6lpe os med dette. Lad os \u00e6ndre vores Dockerfile:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11 as builder\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++\nWORKDIR \/app\nCOPY . .\nRUN npm ci\nRUN npm run build --prod\n\nFROM nginx:1.17.10-alpine\nRUN rm \/etc\/nginx\/conf.d\/default.conf\nCOPY nginx\/static.conf \/etc\/nginx\/conf.d\nCOPY --from=builder \/app\/dist\/app .<\/code><\/pre>\n<p><\/p>\n<p>Nu har vi to instruktioner <code>FROM<\/code> i Dockerfile, hver af dem starter sin egen byggefase. Den f\u00f8rste kaldte vi <code>builder<\/code>, men fra den sidste FROM begynder vi at forberede vores endelige billede. Som det sidste skridt kopierer vi artefakten fra vores tidligere byggefase til det endelige billede med nginx. St\u00f8rrelsen p\u00e5 billedet er v\u00e6sentligt reduceret:<\/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>Lad os starte containeren med vores billede og sikre os, at alt fungerer:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>Med -p8080:80 har vi forwarded port 8080 p\u00e5 vores v\u00e6rtsmaskine til port 80 inde i containeren, hvor nginx k\u00f8rer. \u00c5bn i browseren <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> og se vores application. Alt fungerer!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Reduktionen af billedst\u00f8rrelsen fra 1,74 GB til 36 MB reducerer betydeligt tiden til at levere din applikation til produktion. Men lad os vende tilbage til byggetiden.<\/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\">Lad os \u00e6ndre r\u00e6kkef\u00f8lgen af lagene<\/h2>\n<p><\/p>\n<p>De f\u00f8rste tre trin har v\u00e6ret cached (hint <code>Using cache<\/code>). I det fjerde trin kopieres alle projekfiler og i det femte trin installeres afh\u00e6ngighederne <code>RUN npm ci<\/code> \u2014 hele 47,338 sek. Hvorfor skal man hver gang installere afh\u00e6ngighederne igen, n\u00e5r de sj\u00e6ldent \u00e6ndrer sig? Lad os finde ud af, hvorfor de ikke er blevet cachet. Sagen er, at Docker tjekker lag for lag, om kommandoen og de relaterede filer er \u00e6ndret. P\u00e5 det fjerde trin kopierer vi alle filerne fra vores projekt, og blandt dem er der selvf\u00f8lgelig \u00e6ndringer, hvilket betyder, at Docker ikke kun undlader at tage dette lag fra cachen, men ogs\u00e5 alle efterf\u00f8lgende! Lad os foretage en lille \u00e6ndring i Dockerfile.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11 as builder\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++\nWORKDIR \/app\nCOPY package*.json .\/\nRUN npm ci\nCOPY . .\nRUN npm run build --prod\n\nFROM nginx:1.17.10-alpine\nRUN rm \/etc\/nginx\/conf.d\/default.conf\nCOPY nginx\/static.conf \/etc\/nginx\/conf.d\nCOPY --from=builder \/app\/dist\/app .<\/code><\/pre>\n<p><\/p>\n<p>F\u00f8rst kopieres package.json og package-lock.json, derefter installeres afh\u00e6ngighederne, og f\u00f8rst derefter kopieres hele projektet. Resultatet:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSender byggekontext til Docker d\u00e6mon 608.8kB\nTrin 1\/12 : FROM node:12.16.2-alpine3.11 as builder\nTrin 2\/12 : RUN apk --no-cache --update --virtual build-dependencies add python make g++\n ---&gt; Bruger cache\nTrin 3\/12 : WORKDIR \/app\n ---&gt; Bruger cache\nTrin 4\/12 : COPY package*.json .\/\n ---&gt; Bruger cache\nTrin 5\/12 : RUN npm ci\n ---&gt; Bruger cache\nTrin 6\/12 : COPY . .\nTrin 7\/12 : RUN npm run build --prod\nDato: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Tid: 38287ms\n ---&gt; 1b9448c73558\nTrin 8\/12 : FROM nginx:stable-alpine\nTrin 9\/12 : WORKDIR \/app\n ---&gt; Bruger cache\nTrin 10\/12 : RUN rm \/etc\/nginx\/conf.d\/default.conf\n ---&gt; Bruger cache\nTrin 11\/12 : COPY nginx\/static.conf \/etc\/nginx\/conf.d\n ---&gt; Bruger cache\nTrin 12\/12 : COPY --from=builder \/app\/dist\/app .\nBygget succesfuldt a44dd7c217c3\nSuccesen tagget app:latest\n\nreal 0m46.497s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>46 sekunder i stedet for 3 minutter \u2014 betydeligt bedre! Den rette r\u00e6kkef\u00f8lge af lag er vigtig: F\u00f8rst kopierer vi det, der ikke \u00e6ndrer sig, derefter det, der sj\u00e6ldent \u00e6ndrer sig, og til sidst det, der ofte \u00e6ndrer sig.<\/p>\n<p><\/p>\n<p>Dern\u00e6st nogle ord om opbygning af billeder i CI\/CD-systemer.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Brug af tidligere billeder til caching<\/h2>\n<p><\/p>\n<p>Hvis vi bruger en SaaS-l\u00f8sning til opbygningen, kan den lokale Docker-cache vise sig at v\u00e6re ren og frisk. For at Docker har noget at hente de bagte lag fra, skal du give det det tidligere opbyggede billede.<\/p>\n<p><\/p>\n<p>Lad os tage et eksempel p\u00e5, hvordan vores applikation bygges i GitHub Actions. Vi bruger denne konfiguration<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">on:\n  push:\n    branches:\n      - master\n\nname: Test docker build\n\njobs:\n  deploy:\n    name: Build\n    runs-on: ubuntu-latest\n    env:\n      IMAGE_NAME: docker.pkg.github.com\/${{ github.repository }}\/app\n      IMAGE_TAG: ${{ github.sha }}\n\n    steps:\n    - name: Checkout\n      uses: actions\/checkout@v2\n\n    - name: Login to GitHub Packages\n      env:\n        TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN\n\n    - name: Build\n      run: |\n        docker build \n          -t $IMAGE_NAME:$IMAGE_TAG \n          -t $IMAGE_NAME:latest \n          .\n\n    - name: Push image to GitHub Packages\n      run: |\n        docker push $IMAGE_NAME:latest\n        docker push $IMAGE_NAME:$IMAGE_TAG\n\n    - name: Logout\n      run: |\n        docker logout docker.pkg.github.com<\/code><\/pre>\n<p><\/p>\n<p>Billed image is built and pushed to GitHub Packages in two minutes and 20 seconds:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Now let's modify the build to use cache based on previously built images:<\/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>First, we need to explain why two commands are executed <code>build<\/code>. The matter is that in a multi-stage build, the resulting image will consist of layers from the last stage. The layers from the previous stages will not be included in the image. So when using the final image from the previous build, Docker won't be able to find the ready layers to build the image with nodejs (builder stage). To solve this problem, an intermediate image is created <code>$IMAGE_NAME-builder-stage<\/code> and sent to GitHub Packages, so it can be used in the next build as a cache source.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>The total build time has been reduced to one and a half minutes. Half a minute is spent pulling previous images.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">Pre-building images<\/h2>\n<p><\/p>\n<p>En anden m\u00e5de at l\u00f8se problemet med ren Docker-cache p\u00e5 er at flytte nogle lag til en anden Dockerfile, bygge den separat, skubbe den til Container Registry og bruge den som for\u00e6lder.<\/p>\n<p><\/p>\n<p>Vi opretter vores eget Node.js-billede til at bygge et Angular-program. Opret Dockerfile.node i projektet.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM node:12.16.2-alpine3.11\nRUN apk --no-cache --update --virtual build-dependencies add \n    python \n    make \n    g++<\/code><\/pre>\n<p><\/p>\n<p>Vi bygger og skubber et offentligt billede til Docker Hub:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker build -t exsmund\/node-for-angular -f Dockerfile.node .\ndocker push exsmund\/node-for-angular:latest<\/code><\/pre>\n<p><\/p>\n<p>Nu bruger vi det f\u00e6rdige billede i vores hoved-Dockerfile:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">FROM exsmund\/node-for-angular:latest as builder\n...<\/code><\/pre>\n<p><\/p>\n<p>I vores eksempel er byggetiden ikke reduceret, men forudbyggede billeder kan v\u00e6re nyttige, hvis du har mange projekter, og hver af dem kr\u00e6ver de samme afh\u00e6ngigheder.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Nogle tips til, hvordan man kan accelerere opbygningen af Docker-billeder. For eksempel ned til 30 sekunder.\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi har gennemg\u00e5et flere metoder til at fremskynde bygningen af Docker-billeder. Hvis du \u00f8nsker, at deployment skal forl\u00f8be hurtigt, s\u00e5 pr\u00f8v at anvende f\u00f8lgende i dit projekt:<\/p>\n<p><\/p>\n<ul>\n<li>reduktion af konteksten;<\/li>\n<li>brug af sm\u00e5 for\u00e6ldre-billeder;<\/li>\n<li>multi-stage bygning;<\/li>\n<li>\u00e6ndring af r\u00e6kkef\u00f8lgen af instruktioner i Dockerfile for effektivt at bruge cachen;<\/li>\n<li>konfiguration af cachen i CI\/CD-systemer;<\/li>\n<li>forudg\u00e5ende oprettelse af billeder.<\/li>\n<\/ul>\n<p><\/p>\n<p>Jeg h\u00e5ber, eksemplet vil g\u00f8re det lettere at forst\u00e5, hvordan Docker fungerer, og at du kan optimalt indstille din deployment. For at lege med eksemplerne fra artiklen er der oprettet et repository. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>Kilde: <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\/da\/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=\"da_DK\" \/>\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\/da\/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\udd47Et par tips til, hvordan man kan fremskynde bygningen af Docker-billeder. For eksempel op til 30 sekunder | ProHoster","description":"F\u00f8r en funktion g\u00e5r i produktion, skal den i vores tid med komplekse orkestratorer og CI\/CD gennemg\u00e5 en lang proces fra commit til tests og levering.","canonical_url":"https:\/\/prohoster.info\/da\/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":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/81600","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}