Wie kann ich Dateien von außerhalb des Docker-Build-Kontexts mit dem Befehl "ADD" in die Docker-Datei aufnehmen?
Aus der Docker-Dokumentation:
Der Pfad muss sich im Kontext des Builds befinden. Sie können nicht hinzufügen ../something/something, da der erste Schritt eines Docker-Builds darin besteht, das Kontextverzeichnis (und die Unterverzeichnisse) an den Docker-Daemon zu senden.
Ich möchte nicht mein gesamtes Projekt umstrukturieren, nur um Docker in dieser Angelegenheit unterzubringen. Ich möchte alle meine Docker-Dateien im selben Unterverzeichnis behalten.
Außerdem scheint Docker Symlinks noch nicht (und möglicherweise auch nie) zu unterstützen: Der Befehl Dockerfile ADD folgt nicht den Symlinks auf Host # 1676.
Das einzige andere, was mir einfällt, ist, einen Vorab-Schritt zum Kopieren der Dateien in den Docker-Build-Kontext einzuschließen (und meine Versionskontrolle so zu konfigurieren, dass diese Dateien ignoriert werden). Gibt es dafür eine bessere Problemumgehung?
FROM
und von dort aus fortfahren. Ich würde die Projektstruktur nicht ändern, um Docker (oder Build-Tools) aufzunehmen.Antworten:
Der beste Weg, dies zu umgehen, besteht darin, die Docker-Datei unabhängig vom Build-Kontext mit -f anzugeben.
Mit diesem Befehl erhält der Befehl ADD beispielsweise Zugriff auf alle Elemente in Ihrem aktuellen Verzeichnis.
Update : Docker erlaubt jetzt, die Docker-Datei außerhalb des Build-Kontexts zu haben (behoben in 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Sie können also auch so etwas tun
quelle
dockerfile:
Eigenschaft in dembuild:
Abschnitt in der Compose-Datei docs.docker.com/compose/compose-file/#/compose-file-referenceADD
eine Datei außerhalb des Kontextverzeichnisses zu wollen? Das ist es, was ich versuche, aber ich glaube nicht, dass die Verwendung-f
externe Dateien addierbar macht.build: context: .., dockerfile: dir/Dockerfile
. Jetzt ist mein Build-Kontext das übergeordnete Verzeichnis!Ich nutze die
--build-arg
Option oft für diesen Zweck. Zum Beispiel, nachdem Sie Folgendes in die Docker-Datei eingefügt haben:Sie können einfach tun:
Beachten Sie jedoch die folgende Warnung aus der Docker-Dokumentation :
Warnung: Es wird nicht empfohlen, Build-Time-Variablen zum Übergeben von Geheimnissen wie Github-Schlüsseln, Benutzeranmeldeinformationen usw. zu verwenden. Build-Time-Variablenwerte sind für jeden Benutzer des Images mit dem Docker-Verlaufsbefehl sichtbar.
quelle
Unter Linux können Sie andere Verzeichnisse bereitstellen, anstatt sie zu verknüpfen
Weitere Informationen finden Sie unter /superuser/842642 .
Ich weiß nicht, ob für andere Betriebssysteme etwas Ähnliches verfügbar ist. Ich habe auch versucht, mit Samba einen Ordner freizugeben und ihn erneut im Docker-Kontext bereitzustellen, was ebenfalls funktioniert hat.
quelle
Ich habe viel Zeit damit verbracht, ein gutes Muster herauszufinden und besser zu erklären, was mit dieser Funktionsunterstützung los ist. Mir wurde klar, dass der beste Weg, dies zu erklären, folgender war ...
Nach alledem ist hier ein Beispiel für die Docker-Datei, die eine aufgerufene Datei wiederverwenden muss
start.sh
Dockerfile
Es
ALWAYS
wird von seinem relativen Pfad geladen, wobei das aktuelle Verzeichnis alslocal
Referenz auf die von Ihnen angegebenen Pfade verwendet wird.Dateien
In Anbetracht dieser Idee können wir uns vorstellen, mehrere Kopien für die Docker-Dateien zu haben, die bestimmte Dinge erstellen, aber alle benötigen Zugriff auf die
start.sh
.In Anbetracht dieser Struktur und der obigen Dateien ist hier eine docker-compose.yml
docker-compose.yaml
shared
Kontextverzeichnis dasruntime
Verzeichnis.context
.dockerfile
.Das
docker-compose.yml
ist wie folgtall-service
wird als Kontext festgelegt, wird die gemeinsam genutzte Dateistart.sh
dort sowie die jeweils angegebene Docker- Datei kopiertdockerfile
.Prost!
quelle
a/b/c
, dann ja laufendocker build .
inc
werden Sie nicht den Zugriff erlauben../file-in-b
. Aber ich denke, das allgemeine Missverständnis in diesem (oder zumindest meinem) war, dass der Kontext durch den Ort definiert wird, der durch das erste Argument des Befehls build angegeben wird, nicht durch den Ort der Docker-Datei. Also wie in der akzeptierten Antwort angegeben: vona
:docker build -f a/b/c/Dockerfile .
bedeutet, dass in der Docker-Datei.
jetzt der Ordner ista
Wenn Sie die Diskussion in der Ausgabe 2745 lesen, unterstützt Docker möglicherweise nicht nur niemals Symlinks, sondern auch niemals das Hinzufügen von Dateien außerhalb Ihres Kontexts. Es scheint eine Designphilosophie zu sein, dass Dateien, die in den Docker-Build aufgenommen werden, explizit Teil des Kontexts sein sollten oder von einer URL stammen, bei der sie vermutlich auch mit einer festen Version bereitgestellt werden, damit der Build mit bekannten URLs oder Dateien wiederholt werden kann, die mit dem geliefert werden Docker-Container.
Nur meine Meinung, aber ich denke, Sie sollten sich umstrukturieren, um die Code- und Docker-Repositorys zu trennen. Auf diese Weise können die Container generisch sein und zur Laufzeit eine beliebige Version des Codes abrufen, anstatt sie zu erstellen.
Alternativ können Sie Docker als grundlegendes Code-Bereitstellungsartefakt verwenden und dann die Docker-Datei im Stammverzeichnis des Code-Repositorys ablegen. Wenn Sie diesen Weg gehen, ist es wahrscheinlich sinnvoll, einen übergeordneten Docker-Container für allgemeinere Details auf Systemebene und einen untergeordneten Container für die für Ihren Code spezifische Einrichtung zu haben.
quelle
Ich glaube, die einfachere Problemumgehung wäre, den "Kontext" selbst zu ändern.
Also zum Beispiel anstatt zu geben:
Angenommen, Sie möchten das übergeordnete Verzeichnis als Kontext festlegen. Verwenden Sie dazu einfach Folgendes:
quelle
make build
und alle benötigten Dateien abrufen , wenn sie aktualisiert wurden. Dann wird der entsprechende Docker-Build aufgerufen. Ich muss zusätzliche Arbeit leisten, aber es funktioniert einwandfrei, weil ich die volle Kontrolle habe.Sie können auch einen Tarball erstellen, der zeigt, was das Bild zuerst benötigt, und diesen als Kontext verwenden.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
quelle
tar zc /dir1 /dir2 |docker build -
. Dies war in meinem Fall sehr hilfreich.Mit Docker-Compose habe ich dies erreicht, indem ich einen Dienst erstellt habe, der die benötigten Volumes bereitstellt und das Image des Containers festschreibt. Im nachfolgenden Dienst verlasse ich mich dann auf das zuvor festgeschriebene Image, in dem alle Daten an bereitgestellten Speicherorten gespeichert sind. Sie müssen diese Dateien dann an ihr endgültiges Ziel kopieren, da vom Host bereitgestellte Verzeichnisse beim Ausführen eines
docker commit
Befehls nicht festgeschrieben werdenquelle
Ich hatte das gleiche Problem mit einem Projekt und einigen Datendateien, die ich aus HIPPA-Gründen nicht in den Repo-Kontext verschieben konnte. Am Ende habe ich 2 Dockerfiles verwendet. Man erstellt die Hauptanwendung ohne das Zeug, das ich außerhalb des Containers brauchte, und veröffentlicht das im internen Repo. Dann zieht eine zweite Docker-Datei dieses Image und fügt die Daten hinzu und erstellt ein neues Image, das dann bereitgestellt und nirgendwo gespeichert wird. Nicht ideal, aber es hat funktioniert, um vertrauliche Informationen aus dem Repo herauszuhalten.
quelle
Eine einfache Problemumgehung könnte darin bestehen, das Volume einfach mit dem Flag -v oder --mount in den Container einzubinden, wenn Sie es ausführen und auf diese Weise auf die Dateien zugreifen.
Beispiel:
Weitere Informationen finden Sie unter: https://docs.docker.com/storage/volumes/
quelle
docker run
ist es zu spät.Wie in diesem GitHub-Problem beschrieben, findet der Build tatsächlich statt
/tmp/docker-12345
, sodass ein relativer Pfad wie../relative-add/some-file
relativ zu ist/tmp/docker-12345
. Es würde also suchen/tmp/relative-add/some-file
, was auch in der Fehlermeldung angezeigt wird. *Es ist nicht gestattet, Dateien von außerhalb des Build-Verzeichnisses einzuschließen, daher wird die Meldung "Verbotener Pfad" angezeigt.
quelle
Eine schnelle und schmutzige Möglichkeit besteht darin, den Build-Kontext so viele Ebenen einzurichten, wie Sie benötigen - dies kann jedoch Konsequenzen haben. Wenn Sie in einer Microservices-Architektur arbeiten, die folgendermaßen aussieht:
Sie können den Build-Kontext auf das übergeordnete
Code
Verzeichnis setzen und dann auf alles zugreifen. Es stellt sich jedoch heraus, dass bei einer großen Anzahl von Repositorys der Build sehr lange dauern kann.Eine Beispielsituation könnte sein, dass ein anderes Team ein Datenbankschema verwaltet
Repo1
und der Code Ihres TeamsRepo2
davon abhängt. Sie möchten diese Abhängigkeit mit einigen Ihrer eigenen Seed-Daten andocken, ohne sich Gedanken über Schemaänderungen machen oder das Repository des anderen Teams verschmutzen zu müssen (je nachdem, welche Änderungen Sie vornehmen müssen, müssen Sie möglicherweise noch Ihre Seed-Daten-Skripte ändern). Der zweite Ansatz ist zwar hackig umgeht das Problem der langen Builds:Erstellen Sie ein sh- (oder ps1-) Skript,
./Code/Repo2
um die benötigten Dateien zu kopieren, und rufen Sie die gewünschten Docker-Befehle auf, zum Beispiel:Legen Sie in der Docker-Compose-Datei einfach den Kontext als
Repo2
root fest und verwenden Sie den Inhalt des./db/schema
Verzeichnisses in Ihrer Docker-Datei, ohne sich um den Pfad zu kümmern. Bedenken Sie, dass Sie das Risiko eingehen, dieses Verzeichnis versehentlich der Quellcodeverwaltung zuzuweisen. Die Bereinigungsaktionen für Skripte sollten jedoch einfach genug sein.quelle
In meinem Fall ist meine Docker-Datei wie eine Vorlage geschrieben, die Platzhalter enthält, die ich mithilfe meiner Konfigurationsdatei durch einen echten Wert ersetze.
Daher konnte ich diese Datei nicht direkt angeben, sondern sie wie folgt in den Docker-Build einfügen:
Aber wegen der Pipe
COPY
funktionierte der Befehl nicht. Aber der obige Weg löst es durch-f -
(explizit sagen Datei nicht bereitgestellt). Wenn Sie nur-
auf das-f
Flag verzichten, werden der Kontext UND die Docker-Datei nicht bereitgestellt, was eine Einschränkung darstellt.quelle
Der Trick besteht darin, zu erkennen, dass Sie den Kontext im Build-Befehl angeben können, um Dateien aus dem übergeordneten Verzeichnis einzuschließen, wenn Sie den Docker-Pfad angeben. Ich würde meine Docker-Datei so ändern, dass sie folgendermaßen aussieht:
Dann kann mein Build-Befehl folgendermaßen aussehen:
Aus dem Projektverzeichnis
Vom Projekt / Docker
quelle