{"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\/de\/blog\/administrirovanie\/neskolko-sovetov-o-tom-kak-uskorit-sborku-docker-obrazov-naprimer-do-30-sekund","title":{"rendered":"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Bevor ein neues Feature live geht, muss es in der heutigen Welt komplexer Orchestratoren und CI\/CD einen langen Weg vom Commit \u00fcber Tests bis zur Bereitstellung zur\u00fccklegen. Fr\u00fcher konnte man einfach neue Dateien per FTP hochladen (so macht das doch heute niemand mehr, oder?), und der \"Deployment\"-Prozess dauerte nur Sekunden. Jetzt hingegen muss man einen Merge-Request erstellen und oftmals lange warten, bis das Feature die Nutzer erreicht.<\/p>\n<p><\/p>\n<p>Ein Teil dieses Prozesses ist der Aufbau des Docker-Images. Manchmal dauert der Aufbau Minuten, manchmal sogar Dutzende von Minuten, was schwerlich als normal bezeichnet werden kann. In diesem Artikel nehmen wir eine einfache Anwendung, packen sie in ein Image, wenden einige Methoden an, um den Aufbau zu beschleunigen, und betrachten die Feinheiten der Funktionsweise dieser Methoden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" 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>Wir haben gute Erfahrungen in der Erstellung und Unterst\u00fctzung von Medienwebsites: <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\/\">\"Neue Zeitung\"<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/republic.ru\/\">Republic<\/a><\/noindex>Vor nicht allzu langer Zeit haben wir unser Portfolio erweitert, indem wir die Website <noindex><a rel=\"nofollow\" href=\"https:\/\/reminder.media\">Reminder<\/a><\/noindex>in Produktion gebracht haben. Und w\u00e4hrend wir schnell neue Features entwickelten und alte Bugs beheben, wurde das langsame Deployment zu einem gro\u00dfen Problem.<\/p>\n<p><\/p>\n<p>Das Deployment erfolgt \u00fcber GitLab. Wir erstellen Images, pushen sie in das GitLab Registry und setzen sie in der Produktion ein. Der zeitaufw\u00e4ndigste Schritt in dieser Liste ist die Erstellung der Images. Zum Beispiel dauerte ohne Optimierung jede Backend-Bauzeit 14 Minuten.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/043bc8ad67c34e1c7bd705433c5e4e77.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Schlie\u00dflich wurde klar, dass es so nicht weitergehen kann, und wir haben uns zusammengesetzt, um herauszufinden, warum die Images so lange zum Erstellen ben\u00f6tigen. Am Ende gelang es uns, die Bauzeit auf 30 Sekunden zu reduzieren!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/d035eb1c7b95e0345a110ee59f472693.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>F\u00fcr diesen Artikel, um uns nicht an das Umfeld von Reminder zu binden, betrachten wir ein Beispiel f\u00fcr den Aufbau einer leeren Anwendung mit Angular. Lassen Sie uns also unsere Anwendung erstellen:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng n app<\/code><\/pre>\n<p><\/p>\n<p>Wir f\u00fcgen PWA hinzu (wir sind schlie\u00dflich progressiv):<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ng add @angular\/pwa --project app<\/code><\/pre>\n<p><\/p>\n<p>W\u00e4hrend Millionen von npm-Paketen heruntergeladen werden, lassen Sie uns kl\u00e4ren, wie ein Docker-Image funktioniert. Docker erm\u00f6glicht es, Anwendungen zu verpacken und in einer isolierten Umgebung, dem sogenannten Container, auszuf\u00fchren. Dank der Isolation k\u00f6nnen viele Container gleichzeitig auf einem Server betrieben werden. Container sind erheblich leichter als virtuelle Maschinen, da sie direkt auf dem Systemkern laufen. Um einen Container f\u00fcr unsere Anwendung zu starten, m\u00fcssen wir zun\u00e4chst ein Image erstellen, in dem wir alles verpacken, was f\u00fcr den Betrieb unserer Anwendung erforderlich ist. Im Grunde genommen ist ein Image ein Abbild des Dateisystems. Nehmen wir beispielsweise die folgende 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>Die Dockerfile ist eine Sammlung von Anweisungen; bei der Ausf\u00fchrung jeder einzelnen speichert Docker \u00c4nderungen im Dateisystem und wendet diese auf die vorherigen an. Jeder Befehl erzeugt eine eigene Schicht. Das fertige Image ist ein Zusammenschluss dieser Schichten.<\/p>\n<p><\/p>\n<p>Wichtige Informationen: Jedes Docker-Layer kann gecached werden. Wenn sich seit dem letzten Build nichts ver\u00e4ndert hat, wird Docker anstelle der Ausf\u00fchrung des Befehls das bereits vorhandene Layer verwenden. Der Hauptgewinn an Build-Geschwindigkeit wird durch die Nutzung des Caches erzielt, daher werden wir bei der Messung der Build-Zeiten insbesondere die Erstellung des Images mit vorhandenem Cache ber\u00fccksichtigen. Also, Schritt f\u00fcr Schritt:<\/p>\n<p><\/p>\n<ol>\n<li>Wir entfernen die Images lokal, damit fr\u00fchere Ausf\u00fchrungen die Tests nicht beeinflussen.<br \/>\n<code>docker rmi $(docker images -q)<\/code><\/li>\n<li>Wir starten den Build zum ersten Mal.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<li>Wir \u00e4ndern die Datei src\/index.html \u2013 simulieren die Arbeit eines Programmierers.<\/li>\n<li>Wir starten den Build ein zweites Mal.<br \/>\n<code>time docker build -t app .<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Wenn die Umgebung zum Erstellen von Images richtig konfiguriert ist (dar\u00fcber sp\u00e4ter mehr), hat Docker beim Start des Builds bereits eine Menge Caches im Gep\u00e4ck. Unsere Aufgabe ist es, zu lernen, wie wir den Cache so nutzen, dass der Build m\u00f6glichst schnell abl\u00e4uft. Da wir davon ausgehen, dass der erste Build ohne Cache nur einmal durchgef\u00fchrt wird \u2014 beim allerersten Mal \u2014 k\u00f6nnen wir ignorieren, wie langsam dieser erste Durchlauf war. F\u00fcr unsere Tests ist der zweite Durchlauf des Builds wichtig, wenn die Caches bereits vorgew\u00e4rmt sind und wir bereit sind, unseren Kuchen zu backen. Dennoch wird sich der eine oder andere Tipp auch auf den ersten Build auswirken.<\/p>\n<p><\/p>\n<p>Legen wir die oben beschriebene Dockerfile in den Projektordner und starten den Build. Alle angegebenen Listings sind zur besseren Lesbarkeit gek\u00fcrzt.<\/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>\u00c4ndern wir den Inhalt von src\/index.html und f\u00fchren wir den Build ein zweites Mal aus.<\/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>Um zu \u00fcberpr\u00fcfen, ob unser Image erfolgreich erstellt wurde, f\u00fchren wir den Befehl aus: <code>docker images<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED              SIZE\napp          latest   79f335df92d3   Vor etwa einer Minute   1,74GB<\/code><\/pre>\n<p><\/p>\n<p>Vor dem Build nimmt Docker alle Dateien im aktuellen Kontext und sendet sie an seinen Daemon. <code>Sending build context to Docker daemon 409MB<\/code>Der Build-Kontext wird als letztes Argument des Build-Befehls angegeben. In unserem Fall ist das das aktuelle Verzeichnis \u2014 \u201e.\u201c, und Docker holt alles, was wir in diesem Ordner haben. 409 MB ist viel: Lassen Sie uns dar\u00fcber nachdenken, wie wir das verbessern k\u00f6nnen.<\/p>\n<p><\/p>\n<h2 id=\"umenshaem-kontekst\">Kontext reduzieren<\/h2>\n<p><\/p>\n<p>Um den Kontext zu reduzieren, gibt es zwei Optionen. Entweder alle f\u00fcr den Build ben\u00f6tigten Dateien in einen separaten Ordner legen und Docker genau auf diesen Ordner verweisen. Das kann nicht immer praktisch sein, daher gibt es die M\u00f6glichkeit, Ausnahmen anzugeben: was nicht in den Kontext aufgenommen werden soll. Dazu legen wir eine Datei .dockerignore im Projekt an und geben an, was nicht f\u00fcr den Build ben\u00f6tigt wird:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">.git\n\/node_modules<\/code><\/pre>\n<p><\/p>\n<p>und f\u00fchren den Build noch einmal aus:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSending build context to Docker daemon 607.2kB\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:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Time: 37313ms\nSuccessfully built 4942f010792a\nSuccessfully tagged app:latest\n\nreal 1m47.763s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>607,2 KB \u2014 deutlich besser als 409 MB. Au\u00dferdem haben wir die Bildgr\u00f6\u00dfe von 1,74 auf 1,38 GB reduziert:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED         SIZE\napp          latest   4942f010792a   vor 3 Minuten   1,38 GB<\/code><\/pre>\n<p><\/p>\n<p>Lassen Sie uns versuchen, die Bildgr\u00f6\u00dfe weiter zu reduzieren.<\/p>\n<p><\/p>\n<h2 id=\"ispolzuem-alpine\">Wir verwenden Alpine<\/h2>\n<p><\/p>\n<p>Eine weitere M\u00f6glichkeit, die Gr\u00f6\u00dfe des Images zu sparen, besteht darin, ein kleineres Basis-Image zu verwenden. Das Basis-Image ist das Image, auf dessen Grundlage unser Image erstellt wird. Die untere Schicht wird mit dem Befehl <code>FROM<\/code> im Dockerfile angegeben. In unserem Fall verwenden wir ein auf Ubuntu basierendes Image, das bereits nodejs installiert hat. Es wiegt \u2026<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ docker images -a | grep node\nnode 12.16.2 406aa3abbc6c vor 17 Minuten 916 MB<\/code><\/pre>\n<p><\/p>\n<p>\u2026 fast ein Gigabyte. Die Gr\u00f6\u00dfe kann erheblich reduziert werden, indem man ein auf Alpine Linux basierendes Image verwendet. Alpine ist ein sehr kleines Linux. Das Docker-Image f\u00fcr nodejs basierend auf Alpine wiegt nur 88,5 MB. Lassen Sie uns also unser schweres Image ersetzen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">VON 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>Wir mussten einige Dinge installieren, die f\u00fcr den Build des Applications erforderlich sind. Ja, Angular l\u00e4sst sich ohne Python nicht erstellen \u00af(\u00b0_o)\/\u00af<\/p>\n<p><\/p>\n<p>Aber daf\u00fcr haben wir die Gr\u00f6\u00dfe des Images um 150 MB reduziert:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   aa031edc315a   vor 22 Minuten   761MB<\/code><\/pre>\n<p><\/p>\n<p>Lass uns noch weiter gehen.<\/p>\n<p><\/p>\n<h2 id=\"multisteydzh-sborka\">Multi-Stage Build<\/h2>\n<p><\/p>\n<p>Nicht alles, was im Image ist, ben\u00f6tigen wir in der Produktion.<\/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>Mit <code>docker run app ls -lah<\/code> Wir haben einen Container basierend auf unserem Image gestartet <code>app<\/code> und darin den Befehl ausgef\u00fchrt <code>ls -lah<\/code>, danach hat der Container seine Arbeit beendet.<\/p>\n<p><\/p>\n<p>In der Produktion ben\u00f6tigen wir nur den Ordner <code>dist<\/code>. Die Dateien m\u00fcssen irgendwie nach au\u00dfen gegeben werden. Man k\u00f6nnte einen HTTP-Server mit Node.js starten. Aber wir machen es einfacher. Erratet das russische Wort, das vier Buchstaben \u201e\u044b\u201c enth\u00e4lt. Richtig! \u042b\u043d\u0436\u044b\u043d\u044b\u043a\u0441\u044b. Wir nehmen ein Image mit nginx, f\u00fcgen den Ordner <code>dist<\/code> und eine kleine Konfiguration hinzu:<\/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>Das alles erm\u00f6glicht uns der Multi-Stage Build. Wir werden unser Dockerfile \u00e4ndern:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">VON node:12.16.2-alpine3.11 als 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\nVON 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>Jetzt haben wir zwei Anweisungen <code>FROM<\/code> im Dockerfile, jede davon startet ihren eigenen Build-Schritt. Die erste haben wir genannt <code>builder<\/code>, und ab dem letzten FROM wird unser endg\u00fcltiges Image vorbereitet. Im letzten Schritt kopieren wir das Artefakt unseres Builds aus dem vorherigen Schritt in das finale Image mit nginx. Die Gr\u00f6\u00dfe des Images wurde erheblich reduziert:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">REPOSITORY   TAG      IMAGE ID       CREATED          SIZE\napp          latest   2c6c5da07802   vor 29 Minuten   36MB<\/code><\/pre>\n<p><\/p>\n<p>Lassen Sie uns den Container mit unserem Image starten und \u00fcberpr\u00fcfen, ob alles funktioniert:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">docker run -p8080:80 app<\/code><\/pre>\n<p><\/p>\n<p>Mit der Option -p8080:80 haben wir den Port 8080 auf unserem Host-Rechner zu Port 80 innerhalb des Containers weitergeleitet, wo nginx l\u00e4uft. \u00d6ffnen Sie im Browser <noindex><a rel=\"nofollow\" href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a><\/noindex> und sehen Sie unsere Anwendung. Alles funktioniert!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/ab37d9576a84954f4e4860dd49a75f3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Reduzierung der Gr\u00f6\u00dfe des Images von 1,74 GB auf 36 MB verk\u00fcrzt erheblich die Zeit, die ben\u00f6tigt wird, um Ihre Anwendung in die Produktion zu bringen. Aber lassen Sie uns zum Build-Zeitpunkt zur\u00fcckkehren.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .\nSende Build-Kontext an den Docker-Daemon 608,8 kB\nSchritt 1\/11 : VON node:12.16.2-alpine3.11 als Builder\nSchritt 2\/11 : F\u00dcHREN apk --no-cache --update --virtual build-dependencies hinzuzuf\u00fcgen python make g++ aus\n ---&gt; Cache verwenden\nSchritt 3\/11 : WORKDIR \/app\n ---&gt; Cache verwenden\nSchritt 4\/11 : KOPIEREN . .\nSchritt 5\/11 : F\u00dcHREN npm ci aus\n1357 Pakete in 47,338 s hinzugef\u00fcgt\nSchritt 6\/11 : F\u00dcHREN npm run build --prod aus\nDatum: 2020-04-16T21:16:03.899Z - Hash: fffa0fddaa3425c55dd3 - Zeit: 39948ms\n ---&gt; 27f1479221e4\nSchritt 7\/11 : VON nginx:stable-alpine\nSchritt 8\/11 : WORKDIR \/app\n ---&gt; Cache verwenden\nSchritt 9\/11 : F\u00dcHREN rm \/etc\/nginx\/conf.d\/default.conf aus\n ---&gt; Cache verwenden\nSchritt 10\/11 : KOPIEREN nginx\/static.conf \/etc\/nginx\/conf.d\n ---&gt; Cache verwenden\nSchritt 11\/11 : KOPIEREN --von=builder \/app\/dist\/app .\nErfolgreich d201471c91ad gebaut\nErfolgreich mit app:latest markiert\n\nreal 2m17.700s\nuser 0m0.000s\nsys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<h2 id=\"menyaem-poryadok-sloyov\">Wir \u00e4ndern die Reihenfolge der Schichten<\/h2>\n<p><\/p>\n<p>Die ersten drei Schritte wurden im Cache gespeichert (Hinweis <code>Cache verwenden<\/code>). Im vierten Schritt werden alle Projektdateien kopiert und im f\u00fcnften Schritt werden die Abh\u00e4ngigkeiten installiert <code>F\u00dcHREN npm ci aus<\/code> \u2014 ganze 47,338s. Warum sollten wir jede Abh\u00e4ngigkeit von neuem installieren, wenn sie sich nur selten \u00e4ndern? Lassen Sie uns herausfinden, warum sie nicht im Cache gespeichert wurden. Das liegt daran, dass Docker schichtweise \u00fcberpr\u00fcft, ob sich das Kommando und die damit verbundenen Dateien ge\u00e4ndert haben. In Schritt vier kopieren wir alle Dateien unseres Projekts, und nat\u00fcrlich gibt es darunter \u00c4nderungen, weshalb Docker nicht nur diese Schicht nicht aus dem Cache nimmt, sondern auch alle folgenden! Lassen Sie uns kleine \u00c4nderungen in der Docker-Datei vornehmen.<\/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>Zuerst werden package.json und package-lock.json kopiert, dann werden die Abh\u00e4ngigkeiten installiert, und erst danach wird das gesamte Projekt kopiert. Das Ergebnis:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ time docker build -t app .<br>Sending build context to Docker daemon 608.8kB<br>Step 1\/12 : FROM node:12.16.2-alpine3.11 as builder<br>Step 2\/12 : RUN apk --no-cache --update --virtual build-dependencies add python make g++<br> ---&gt; Using cache<br>Step 3\/12 : WORKDIR \/app<br> ---&gt; Using cache<br>Step 4\/12 : COPY package*.json .\/<br> ---&gt; Using cache<br>Step 5\/12 : RUN npm ci<br> ---&gt; Using cache<br>Step 6\/12 : COPY . .<br>Step 7\/12 : RUN npm run build --prod<br>Date: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Time: 38287ms<br> ---&gt; 1b9448c73558<br>Step 8\/12 : FROM nginx:stable-alpine<br>Step 9\/12 : WORKDIR \/app<br> ---&gt; Using cache<br>Step 10\/12 : RUN rm \/etc\/nginx\/conf.d\/default.conf<br> ---&gt; Using cache<br>Step 11\/12 : COPY nginx\/static.conf \/etc\/nginx\/conf.d<br> ---&gt; Using cache<br>Step 12\/12 : COPY --from=builder \/app\/dist\/app .<br>Successfully built a44dd7c217c3<br>Successfully tagged app:latest<br><br>real 0m46.497s<br>user 0m0.000s<br>sys 0m0.000s<\/code><\/pre>\n<p><\/p>\n<p>46 Sekunden statt 3 Minuten \u2014 das ist deutlich besser! Die richtige Reihenfolge der Schichten ist wichtig: Zuerst kopieren wir, was sich nicht \u00e4ndert, dann das, was sich selten \u00e4ndert, und zum Schluss das, was h\u00e4ufig ge\u00e4ndert wird.<\/p>\n<p><\/p>\n<p>Jetzt ein paar Worte zum Erstellen von Images in CI\/CD-Systemen.<\/p>\n<p><\/p>\n<h2 id=\"ispolzovanie-predyduschih-obrazov-dlya-kesha\">Verwendung vorheriger Images f\u00fcr den Cache<\/h2>\n<p><\/p>\n<p>Wenn wir ein SaaS-Produkt zum Bauen verwenden, kann der lokale Docker-Cache leer und frisch sein. Um Docker die M\u00f6glichkeit zu geben, gebaute Schichten zu \u00fcbernehmen, geben Sie ihm das vorherige gebaute Image.<\/p>\n<p><\/p>\n<p>Betrachten wir als Beispiel den Aufbau unserer Anwendung in GitHub Actions. Wir verwenden eine solche 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>Das Image wird in GitHub Packages in zwei Minuten und 20 Sekunden erstellt und gepusht:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/76b81216922f7ef2c4e777b60238acd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lassen Sie uns das Build anpassen, damit der Cache auf der Grundlage der zuvor erstellten Images verwendet wird:<\/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>Zuerst ist es wichtig zu erkl\u00e4ren, warum zwei Befehle ausgef\u00fchrt werden. <code>build<\/code>. Es ist so, dass in einem Multi-Stage-Build als Ergebnis eine Schicht aus der letzten Stufe erstellt wird. Dabei gelangen die Schichten aus den vorherigen Stufen nicht ins Image. Deshalb kann Docker beim Einsatz des finalen Images mit der vorherigen Build-Version die erforderlichen Schichten f\u00fcr den Build des Node.js-Images (Stadium Builder) nicht finden. Um dieses Problem zu l\u00f6sen, wird ein Zwischen-Image erstellt. <code>$IMAGE_NAME-builder-stage<\/code> und in GitHub Packages hochgeladen, damit es in der folgenden Build-Phase als Cache-Quelle verwendet werden kann.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/acaa70ae528589f4be2258650d8eb5de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die gesamte Build-Zeit wurde auf anderthalb Minuten reduziert. Eine halbe Minute entf\u00e4llt auf das Herunterladen der vorherigen Images.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnoe-sozdanie-obrazov\">Vorab-Bilder erstellen<\/h2>\n<p><\/p>\n<p>Eine weitere M\u00f6glichkeit, das Problem des sauberen Docker-Caches zu l\u00f6sen, besteht darin, einige Schichten in eine andere Dockerfile auszulagern, sie separat zu bauen, in das Container Registry zu pushen und sie als \u00fcbergeordnetes Image zu verwenden.<\/p>\n<p><\/p>\n<p>Wir erstellen unser Node.js-Image zum Bauen einer Angular-Anwendung. Wir erstellen eine Dockerfile.node in unserem Projekt.<\/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>Wir bauen und pushen das \u00f6ffentliche Image in 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>Jetzt verwenden wir das fertige Image in unserem Haupt-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>In unserem Beispiel blieb die Build-Zeit gleich, jedoch k\u00f6nnen vorab erstellte Images n\u00fctzlich sein, wenn Sie viele Projekte haben und in jedem von ihnen dieselben Abh\u00e4ngigkeiten installieren m\u00fcssen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Einige Tipps, wie Sie den Aufbau von Docker-Images beschleunigen k\u00f6nnen. Zum Beispiel auf bis zu 30 Sekunden.\" src=\"\/wp-content\/uploads\/2020\/05\/5b4e4bd1d4b96a3f07305d2dd0f6d680.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir haben verschiedene Methoden zur Beschleunigung des Docker-Image-Builds betrachtet. Wenn Sie einen schnellen Deployment-Prozess w\u00fcnschen, probieren Sie in Ihrem Projekt Folgendes aus:<\/p>\n<p><\/p>\n<ul>\n<li>Reduzierung des Kontextes;<\/li>\n<li>Verwendung kleinerer Basis-Images;<\/li>\n<li>Multi-Stage-Builds;<\/li>\n<li>\u00c4nderung der Anweisungsreihenfolge im Dockerfile, um den Cache effektiv zu nutzen;<\/li>\n<li>Konfiguration des Caches in CI\/CD-Systemen;<\/li>\n<li>Vorab-Erstellung von Images.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ich hoffe, das Beispiel macht klarer, wie Docker funktioniert, und Sie k\u00f6nnen Ihr Deployment optimal konfigurieren. Um mit den Beispielen aus dem Artikel zu experimentieren, wurde ein Repository erstellt. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/devopsprodigy\/test-docker-build\">https:\/\/github.com\/devopsprodigy\/test-docker-build<\/a><\/noindex>.<\/p>\n<p>Quelle: <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 4.9.10 - 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. \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\" \/>\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\/de\/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) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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. \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\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/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\udd47Einige Tipps zur Beschleunigung des Builds von Docker-Images. Zum Beispiel in nur 30 Sekunden | ProHoster","description":"Bevor ein Feature in die Produktion geht, muss es in der heutigen Welt komplexer Orchestratoren und CI\/CD einen langen Weg vom Commit \u00fcber Tests bis zur Auslieferung zur\u00fccklegen. Fr\u00fcher konnte man einfach neue Dateien per FTP hochladen (das macht heute wirklich niemand mehr, oder?), und der \"Deploy\"-Prozess dauerte Sekunden. Jetzt muss man einen Merge-Request erstellen und eine betr\u00e4chtliche Zeit warten, bis das Feature","canonical_url":"https:\/\/prohoster.info\/de\/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":"de_DE","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. \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","og:url":"https:\/\/prohoster.info\/de\/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"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/81600","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=81600"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/81600\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/81601"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=81600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=81600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=81600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}