Mehrere FROMs - was es bedeutet

112

Ich möchte ein Docker-Image für das Linkurious- Projekt auf github erstellen, für dessen Ausführung sowohl die Neo4j-Datenbank als auch Node.js erforderlich sind.

Mein erster Ansatz war, ein Basis-Image für mein Image zu deklarieren, das Neo4j enthält. Die Referenzdokumente definieren "Basisbild" nicht auf hilfreiche Weise:

Basisbild: Ein Bild ohne übergeordnetes Element ist ein Basisbild

von dem ich gelesen habe, dass ich möglicherweise nur ein Basisbild habe, wenn dieses Bild selbst kein Basisbild hat.

aber was ist ein Grundbild? Bedeutet dies, dass, wenn ich neo4j / neo4j in einer FROM-Direktive deklariere, die neo-Datenbank automatisch ausgeführt wird und im Container auf Port 7474 verfügbar ist, wenn mein Image ausgeführt wird?

Lesen der Docker-Referenz (siehe: https://docs.docker.com/reference/builder/#from ) Ich sehe:

FROM kann in einer einzelnen Docker-Datei mehrmals angezeigt werden, um mehrere Bilder zu erstellen. Notieren Sie sich einfach die letzte vom Commit ausgegebene Bild-ID vor jedem neuen FROM-Befehl.

möchte ich mehrere Bilder erstellen? Ich möchte anscheinend ein einzelnes Bild haben, das den Inhalt anderer Bilder enthält, z. B. neo4j und node.js.

Ich habe im Referenzhandbuch keine Anweisung gefunden, Abhängigkeiten zu deklarieren. Gibt es keine Abhängigkeiten wie in RPM, bei denen der aufrufende Kontext zum Ausführen meines Images zuerst die benötigten Images installieren muss?

Ich bin verwirrt...

ekkis
quelle
Hinweis: Im Mai 2017 haben Sie jetzt mehrere FROMin einem Dockerfile. Siehe meine bearbeitete Antwort unten.
VonC
Sehen Sie, ob Sie meine Antwort sauberer finden. Und wenn ja, akzeptieren Sie es.
Evan Carroll

Antworten:

113

Was ist ein Basisbild?

Eine Reihe von Dateien sowie EXPOSE'd Ports ENTRYPOINTund CMD.
Sie können Dateien hinzufügen und ein neues Image basierend auf diesem Basis-Image erstellen, wobei ein neues Dockerfilemit einer FROMDirektive beginnt : Das nachfolgend erwähnte Image FROMist "das Basis-Image" für Ihr neues Image.

Bedeutet dies, dass, wenn ich neo4j/neo4jin einer FROMDirektive deklariere , die Neo-Datenbank beim Ausführen meines Images automatisch ausgeführt wird und im Container auf Port 7474 verfügbar ist?

Nur wenn Sie nicht überschreiben CMDund ENTRYPOINT.
Aber das Bild an sich ist genug: Sie würden ein verwenden, FROM neo4j/neo4jwenn Sie Dateien hinzufügen müssten , die sich neo4jauf Ihre spezielle Verwendung von beziehen neo4j.

FROM kann innerhalb einer einzelnen Docker-Datei mehrmals vorkommen

Tu es nicht: Es gibt einen Vorschlag, diese "Funktion" trotzdem zu entfernen ( Problem 13026 ).

Ausgabe 14412 erwähnt:

Die Verwendung von Multiple FROMist nicht wirklich eine Funktion, sondern ein Fehler ( FROMna ja , das Limit ist eng und es gibt nur wenige Anwendungsfälle für Multiple in einer Docker-Datei).


Update Mai 2017 (18 Monate später) mit Docker (Moby) 17.05-ce .

In einer Docker-Datei können mehrere FROM verwendet werden.
Siehe " Builder-Muster vs. mehrstufige Builds in Docker " (von Alex Ellis ) und PR 31257 von Tõnis Tiigi .

Vor:

Das Builder-Muster umfasst die Verwendung von zwei Docker-Images - eines zum Ausführen eines Builds und eines zum Versenden der Ergebnisse des ersten Builds, ohne dass die Build-Kette und die Werkzeuge im ersten Image beeinträchtigt werden.

Nach dem:

Die allgemeine Syntax beinhaltet das Hinzufügen FROMzusätzlicher Zeiten in Ihrer Docker-Datei - je nachdem, welche letzte FROMAnweisung die endgültige ist , ist das endgültige Basis-Image. Verwenden Sie zum Kopieren von Artefakten und Ausgaben von Zwischenbildern COPY --from=<base_image_number>.

Erster Teil der Docker-Datei:

FROM golang:1.7.3 as builder
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 .

Zweiter Teil derselben (!) Docker-Datei:

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

Das Ergebnis wären zwei Bilder, eines zum Erstellen, eines nur mit der resultierenden App (viel, viel kleiner).

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  
VonC
quelle
2
Schade um das Entfernen mehrerer FROMs. es scheint mir am nützlichsten zu sein, insbesondere wenn kein Abhängigkeitsmechanismus vorhanden ist. Mit RPMs kann ich beispielsweise deklarieren, dass mein Paket ein anderes Paket benötigt, um ausgeführt zu werden, sodass bei der Installation alles für mich eingerichtet wird. Die Realität ist, dass fast alles mehrere Abhängigkeiten erfordern wird. Wie soll das funktionieren, wenn nicht mehrere FROMs vorhanden sind?
Ekkis
3
@ekkis Wie ich in meiner vorherigen Antwort ( stackoverflow.com/a/33295292/6309 ) erwähnt habe, führen Sie Ihr System aus, indem Sie mehrere Container orchestrieren, von denen jeder einen bestimmten Dienst bereitstellt, und über --link ( docs.docker.com/) kommunizieren. userguide / dockerlinks /… ).
VonC
2
@VonC Sicher, in einer idealen Welt, mit einer neuen App und allen Mustern verstanden. In der Zwischenzeit erwarte ich, dass es mehr Fälle gibt, in denen Benutzer versuchen, ihre Lösungen in Docker zu migrieren, und Anforderungen haben, die nicht durch Netzwerke gelöst werden, wie z. B. Softwareabhängigkeiten, die alle eine kompatible Basis verwenden, sondern von mehreren Docker-Dateien. Stattdessen ist das Beste, was ich bisher herausfinden kann, das Hacken ihrer Docker-Dateien, um meine eigenen zu erstellen.
rainabba
@rainabba Einverstanden. Legacy-Monolithen lassen sich nicht einfach migrieren. Interessante liest: martinfowler.com/articles/… , threedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC
2

Die erste Antwort ist zu komplex, historisch und für meinen Geschmack nicht informativ.


Es ist eigentlich ziemlich einfach. Docker bietet eine Funktionalität, die als mehrstufige Builds bezeichnet wird. Die Grundidee hier ist:

  • Befreien Sie sich von der Notwendigkeit, manuell zu entfernen, was Sie nicht möchten, indem Sie gezwungen werden, eine Whitelist für das zu erstellen, was Sie möchten.
  • Kostenlose Ressourcen, die sonst aufgrund der Implementierung von Docker in Anspruch genommen würden.

Beginnen wir mit dem ersten. Sehr oft mit so etwas wie Debian werden Sie sehen.

RUN apt-get update \ 
  && apt-get dist-upgrade \
  && apt-get install <whatever> \
  && apt-get clean

All dies können wir mit den obigen Ausführungen erklären. Der obige Befehl ist verkettet, sodass er eine einzelne Änderung darstellt, ohne dass Zwischenbilder erforderlich sind. Wenn es so geschrieben wurde,

RUN apt-get update ;
RUN apt-get dist-upgrade;
RUN apt-get install <whatever>;
RUN apt-get clean;

Dies würde zu 3 weiteren temporären Zwischenbildern führen. Wenn es auf ein Image reduziert wird, gibt es noch ein Problem: apt-get cleanBereinigt keine bei der Installation verwendeten Artefakte. Wenn ein Debian-Betreuer in seine Installation ein Skript einbezieht, das das System ändert, ist diese Änderung auch in der endgültigen Lösung vorhanden (siehe etwa pepperflashplugin-nonfreeein Beispiel dafür).

Durch die Verwendung eines mehrstufigen Builds erhalten Sie alle Vorteile einer einzelnen geänderten Aktion. Sie müssen jedoch manuell Dateien auf die Whitelist setzen und kopieren, die im temporären Image mit der COPY --fromhier dokumentierten Syntax eingeführt wurden. Darüber hinaus ist es eine großartige Lösung, bei der es keine Alternative (wie eine apt-get clean) gibt und Sie sonst viele nicht benötigte Dateien in Ihrem endgültigen Bild hätten.

Siehe auch

Evan Carroll
quelle
Danke, aber ich verstehe nicht, wie Sie mein Problem angehen. Für mich ist FROM ein Vererbungsmechanismus. Wenn ich mehrere Anweisungen habe, kann ich von mehreren Eltern erben. In Ihrer Antwort erwähnen Sie weder FROM noch das Konzept, die Verpackung von Software durch andere zu nutzen
ekkis
1
Vielleicht ist das die Verwirrung. FROMist hauptsächlich eine Namespace-Deklaration. Das Qualifikationsmerkmal dort ist eher eine Erweiterung als eine Vererbung. Sie können mehrere Namespaces deklarieren. Und jeder dieser Namespaces kann einen weiteren Namespace erweitern. @ekkis Wenn die andere Antwort für Sie funktioniert, dann bleiben Sie auf jeden Fall dabei.
Evan Carroll