wake-up-neo.com

Gibt es eine Möglichkeit, Docker-Bilder in einem Container zu kombinieren?

Ich habe jetzt ein paar Dockerfiles.

Eine ist für Cassandra 3.5, und es ist FROM cassandra:3.5

Ich habe auch ein Dockerfile für Kafka, aber es ist ein bisschen komplexer. Es ist FROM Java:openjdk-8-fre und führt einen langen Befehl aus, um Kafka und Zookeeper zu installieren.

Schließlich habe ich eine Anwendung in Scala, die SBT verwendet. 

Für dieses Dockerfile ist es FROM broadinstitute/scala-baseimage, was mir Java 8, Scala 2.11.7 und STB 0.13.9 bringt, was ich brauche.

Vielleicht verstehe ich nicht, wie Docker funktioniert, aber mein Scala-Programm hat Cassandra und Kafka als Abhängigkeiten und zu Entwicklungszwecken. Ich möchte, dass andere mein Repo einfach mit der Dockerfile klonen und es dann mit Cassandra bauen können. Kafka, Scala, Java und SBT haben alles eingebacken, damit sie nur die Quelle kompilieren können. Ich habe jedoch viele Probleme damit. 

Wie kombiniere ich diese Dockerfiles? Wie mache ich einfach eine Umgebung, in der diese Dinge gebacken werden?

21
David

Sie können Docker-Dateien nicht kombinieren, da Konflikte auftreten können. Sie möchten eine neue Docker-Datei erstellen oder ein benutzerdefiniertes Image erstellen.

TL; DR; Wenn Ihr aktueller Entwicklungscontainer alle Tools enthält, die Sie benötigen und funktionieren, speichern Sie sie als Image und darauf in einem Repo und erstellen Sie eine Docker-Datei, um dieses Repo aus diesem Image abzurufen.

Details: Das Erstellen eines benutzerdefinierten Images ist bei weitem einfacher als das Erstellen einer Docker-Datei mit einem öffentlichen Image, da Sie beliebige Hacks und Mods im Image speichern können. Starten Sie dazu einen leeren Container mit einem Linux-Basisabbild (oder broadinstitute/scala-baseimage), installieren Sie die gewünschten Tools und konfigurieren Sie sie so lange, bis alles ordnungsgemäß funktioniert, und speichern Sie es (den Container) als Image. Erstellen Sie einen neuen Container aus diesem Image, und testen Sie, ob Sie Ihren Code über Docker-Compose (oder wie auch immer Sie ihn erstellen möchten) darauf erstellen können. Wenn es funktioniert, haben Sie ein funktionierendes Basis-Image, das Sie in ein Repo hochladen können, damit andere es ziehen können.

Um eine Docker-Datei mit einem öffentlichen Image zu erstellen, müssen Sie alle Hacks, Mods und Setups auf der Docker-Datei selbst ablegen. Das heißt, Sie müssen jede Befehlszeile, die Sie verwendet haben, in eine Textdatei einfügen und alle Hacks, Mods und Setups in Befehlszeilen reduzieren. Am Ende erstellt Ihre Docker-Datei automatisch ein Bild, und Sie müssen dieses Bild nicht in einem Repo speichern. Alles, was Sie tun müssen, ist, den anderen die Docker-Datei zu geben, und sie können das Bild an ihrem eigenen Docker hochfahren.

Wenn Sie eine funktionierende Docker-Datei haben, können Sie diese leicht anpassen, da bei jeder Verwendung der Docker-Datei ein neues Bild erstellt wird. Bei einem benutzerdefinierten Image können Probleme auftreten, bei denen Sie das Image aufgrund von Konflikten neu erstellen müssen. Beispielsweise funktionieren alle Tools mit openjdk, bis Sie eines installieren, das nicht funktioniert. Das Update kann die Deinstallation von openjdk und die Verwendung des Oracle-Pakets beinhalten. Die gesamte Konfiguration, die Sie für alle installierten Tools vorgenommen haben, ist jedoch defekt.

11
Hin Fan Chan

Sie können dies mit der in Docker 1.17 eingeführten Funktion multi-stage builds tun

Schau dir das an:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM Alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

Dann bauen Sie das Bild normal auf:

docker build -t alexellis2/href-counter:latest

Von: https://docs.docker.com/develop/develop-images/multistage-build/

Das Endergebnis ist das gleiche winzige Produktionsbild wie zuvor, mit einer erheblichen Verringerung der Komplexität. Sie müssen keine Zwischenbilder erstellen und müssen keinerlei Artefakte in Ihr lokales System extrahieren.

Wie funktioniert es? Der zweite FROM-Befehl startet eine neue Baustufe mit dem Alpine: Latest Image als Basis. Die COPY - from = 0 -Zeile kopiert nur das eingebaute Artefakt aus der vorherigen Stufe in diese neue Stufe. Das Go-SDK und alle Zwischenartefakte werden zurückgelassen und nicht im endgültigen Bild gespeichert.

25

Ja, Sie can rollen eine ganze Menge Software in ein einzelnes Docker-Image ( GitLab führt dies mit einem Image aus, das Postgres und alles andere enthält), aber generalhenry ist richtig - Das ist nicht die typische Art, Docker zu verwenden.

Wie Sie sagen, sind Cassandra und Kafka Abhängigkeiten für Ihre Scala-App. Sie sind nicht Teil der App, daher gehören sie nicht alle zum selben Bild. 

Wenn Sie viele Container mit Docker Compose koordinieren möchten, wird eine zusätzliche Verwaltungsebene hinzugefügt, die jedoch viel mehr Flexibilität bietet:

  • ihre Container können unterschiedliche Lebensdauer haben. Wenn Sie also eine neue Version Ihrer App bereitstellen möchten, müssen Sie nur einen neuen App-Container ausführen. Sie können die Abhängigkeiten jedoch laufen lassen.
  • sie können dasselbe App-Image in jeder Umgebung verwenden, indem Sie unterschiedliche Konfigurationen für Ihre Abhängigkeiten verwenden, z. In dev können Sie einen grundlegenden Kafka-Container ausführen. In prod ist dieser Cluster auf vielen Knoten gruppiert. Der App-Container ist derselbe.
  • ihre Abhängigkeiten können auch von anderen Apps verwendet werden. So können mehrere Konsumenten in verschiedenen Containern ausgeführt werden und alle arbeiten mit denselben Kafka- und Cassandra-Containern.
  • sowie die bereits erwähnte Skalierbarkeit, Protokollierung usw.
4
Elton Stoneman

Die folgende Antwort gilt für Docker 1.7 und höher:

Ich würde es vorziehen, --from=NAME und from image as NAME Warum? Sie können --from=0 und höher, aber dies kann etwas schwierig werden, wenn Sie viele Docker-Phasen in dockerfile haben.

beispielbeispiel:

FROM golang:1.7.3 as backend
WORKDIR /backend
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN  #install some stuff, compile assets....

FROM golang:1.7.3 as assets
WORKDIR /assets
RUN ./getassets.sh

FROM nodejs:latest as frontend 
RUN npm install
WORKDIR /assets
COPY --from=assets /asets .
CMD ["./app"] 

FROM Alpine:latest as mergedassets
WORKDIR /root/
COPY --from=merge ./
COPY --from=backend ./backend .
CMD ["./app"]

Hinweis: Wenn Sie die Docker-Datei richtig verwalten, kann ein Docker-Image schneller erstellt werden. Intern verwendet Docker das Docker-Layer-Caching, um diesen Prozess zu unterstützen, sofern das Image neu erstellt werden muss.

3
РАВИ

Sie konnten Andockbilder nicht in einem Container kombinieren. Siehe die ausführlichen Diskussionen in der Moby-Ausgabe, Wie kombiniere ich mehrere Bilder über Dockerfile zu einem Bild.

Für Ihren Fall ist es besser, nicht die gesamten Cassandra- und Kafka-Bilder einzuschließen. Die Anwendung würde nur den Cassandra Scala-Treiber und den Kafka Scala-Treiber benötigen. Der Container sollte nur die Treiber enthalten.

1
CloudStax

Docker führt keine Zusammenführung der Bilder durch, aber es gibt nichts, was Sie daran hindert, die Docker-Dateien zu kombinieren, sofern verfügbar, und in ein fettes Image zu rollen, das Sie erstellen müssen. Es gibt Zeiten, in denen dies sinnvoll ist, da für das Ausführen mehrerer Prozesse in einem Container die meisten Docker-Dogmen besonders in der Microservice-Architektur als weniger wünschenswert erscheinen (jedoch gibt es Regeln, die nicht korrekt sind?)

1
Amos Folarin