it-swarm.com.de

Wie werden Dateien außerhalb des Builder-Kontextes von Docker eingefügt

Wie kann ich Dateien außerhalb des Builder-Kontexts von Docker mit dem Befehl "ADD" in die Docker-Datei einfügen?

Aus der Docker-Dokumentation:

Der Pfad muss sich im Kontext des Builds befinden. Sie können nicht hinzufügen ../something/something, weil der erste Schritt eines Docker-Builds ist Senden Sie das Kontextverzeichnis (und die Unterverzeichnisse) an den Docker-Daemon.

Ich möchte mein gesamtes Projekt nicht umstrukturieren, um Docker in dieser Angelegenheit zu unterstützen. Ich möchte alle meine Docker-Dateien im selben Unterverzeichnis behalten.

Es scheint auch, dass Docker Symlinks noch nicht unterstützt (und möglicherweise auch nie): Der Dockerfile-Befehl ADD folgt den Symlinks auf Host # 1676 nicht.

Die einzige andere Sache, die ich mir vorstellen kann, ist, einen Vorbereitungsschritt einzuschließen, um die Dateien in den Docker-Build-Kontext zu kopieren (und meine Versionskontrolle so zu konfigurieren, dass diese Dateien ignoriert werden). Gibt es eine bessere Lösung für das Problem?

240
ben_frankly

Um dies zu umgehen, können Sie die Dockerfile unabhängig vom Build-Kontext mit -f angeben.

Mit diesem Befehl kann der ADD-Befehl beispielsweise auf alles in Ihrem aktuellen Verzeichnis zugreifen.

docker build -f docker-files/Dockerfile .

Update: Docker erlaubt jetzt das Dockerfile außerhalb des Build-Kontextes (behoben in 18.03.0-ce, https://github.com/docker/cli/pull/886 ). So kannst du auch so etwas machen

docker build -f ../Dockerfile .
234
Cyberwiz

Unter Linux können Sie andere Verzeichnisse einbinden, anstatt sie zu verknüpfen

mount --bind olddir newdir

Weitere Informationen erhalten Sie unter https://superuser.com/questions/842642 .

Ich weiß nicht, ob etwas ähnliches für andere Betriebssysteme verfügbar ist ... Ich habe auch versucht, mit Samba einen Ordner freizugeben und ihn im Docker-Kontext erneut bereitzustellen, was ebenfalls funktioniert.

35

Ich benutze oft die --build-arg-Option für diesen Zweck. Zum Beispiel, nachdem Sie Folgendes in die Docker-Datei eingefügt haben:

ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa

Sie können einfach tun:

docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

Beachten Sie jedoch die folgende Warnung aus der Docker-Dokumentation :

Warnung: Es wird nicht empfohlen, Build-Time-Variablen für die Weitergabe von Geheimnissen wie Github-Schlüsseln, Benutzeranmeldeinformationen usw. zu verwenden. Build-Time-Variablenwerte sind für jeden Benutzer des Images mit dem Befehl docker history sichtbar.

35
user2658308

Wenn Sie die Diskussion in der Ausgabe 2745 lesen, werden möglicherweise nicht nur Anderseiten symbolische Links unterstützt, sondern möglicherweise auch das Hinzufügen von Dateien außerhalb Ihres Kontexts. Es scheint eine Designphilosophie zu sein, dass Dateien, die in Docker Build eingehen, explizit Teil ihres Kontextes sein sollten oder von einer URL stammen sollten, an der sie vermutlich auch mit einer festen Version bereitgestellt werden, sodass der Build mit bekannten URLs oder Dateien, die mit dem Server ausgeliefert werden, wiederholt werden kann Docker-Container. 

Ich ziehe es vor, von einer versiongesteuerten Quelle aus zu bauen - dh Docker-Build -t stuff http://my.git.org/repo - ansonsten baue ich aus zufälligen Orten mit zufälligen Dateien.

im Grunde nein ... - SvenDowideit, Docker Inc

Nur meine Meinung, aber ich denke, Sie sollten sich umstrukturieren, um die Code- und Docker-Repositories zu trennen. Auf diese Weise können die Container generisch sein und zum Zeitpunkt der Ausführung eine beliebige Version des Codes einlesen. 

Alternativ können Sie das Andockfenster als Ihr grundlegendes Code-Implementierungsartefakt verwenden und dann legen Sie die Andockdatei im Stammverzeichnis des Code-Repositorys ab. Wenn Sie diese Route wählen, ist es wahrscheinlich sinnvoll, einen übergeordneten Docker-Container für allgemeinere Systemebenendetails und einen untergeordneten Container für die Einrichtung zu haben, die für Ihren Code spezifisch ist. 

17
Usman Ismail

Ich habe eine gute Zeit damit verbracht, ein gutes Muster zu finden und zu erläutern, was mit dieser Funktionsunterstützung besser zu erklären ist. Mir wurde klar, dass der beste Weg, es zu erklären, wie folgt war ...

  • Dockerfile: Zeigt nur Dateien unter einem eigenen relativen Pfad an
  • Kontext: Ein Ort im "Space", in den die Dateien, die Sie freigeben möchten, und Ihre Docker-Datei kopiert werden

Nachdem dies gesagt wurde, folgt hier ein Beispiel der Docker-Datei, die eine Datei mit dem Namen start.sh wiederverwenden muss.

Dockerfile

ALWAYS wird von seinem relativen Pfad geladen, wobei das aktuelle Verzeichnis als local-Verweis auf die von Ihnen angegebenen Pfade angegeben wird.

COPY start.sh /runtime/start.sh

Dateien

Wenn man diese Idee in Betracht zieht, können wir uns vorstellen, mehrere Kopien für die Dockerfiles zu haben, die bestimmte Dinge erstellen, aber alle benötigen Zugriff auf den start.sh.

./all-services/
   /start.sh
   /service-X/Dockerfile
   /service-Y/Dockerfile
   /service-Z/Dockerfile
./docker-compose.yaml

In Anbetracht dieser Struktur und der obigen Dateien ist hier eine Docker-compose.yml

docker-compose.yaml

  • In diesem Beispiel ist Ihr shared Kontextverzeichnis das runtime dir .
    • Dasselbe Modell wie hier, denken Sie, dass alle Dateien unter diesem Verzeichnis in die sogenannte context verschoben werden. 
    • Genauso geben Sie einfach die Docker-Datei an, die Sie in dasselbe Verzeichnis kopieren möchten. Sie können dies mit dockerfile angeben.
  • das Verzeichnis, in dem sich Ihr Hauptinhalt befindet, ist der tatsächlich einzustellende Kontext.

Der docker-compose.yml lautet wie folgt

version: "3.3"
services:

  service-A
    build:
      context: ./all-service
      dockerfile: ./service-A/Dockerfile

  service-B
    build:
      context: ./all-service
      dockerfile: ./service-B/Dockerfile

  service-C
    build:
      context: ./all-service
      dockerfile: ./service-C/Dockerfile
  • all-service wird als Kontext festgelegt, die gemeinsam genutzte Datei start.sh wird dorthin sowie die Docker-Datei kopiert, die von jeder dockerfile angegeben wird.
  • Jeder wird auf seine eigene Art und Weise gebaut und teilt die Startdatei!

Prost!

8

Ich glaube, die einfachere Lösung wäre, den Kontext selbst zu ändern. 

So zum Beispiel anstatt zu geben:

docker build -t hello-demo-app .

hier wird das aktuelle Verzeichnis als Kontext festgelegt. Angenommen, Sie wollten das übergeordnete Verzeichnis als Kontext.

docker build -t hello-demo-app ..
4
Anshuman Manral

Sie können auch ein Archiv erstellen, das das Bild zuerst benötigt, und dieses als Kontext verwenden.

https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts

1
Laurent Picquet

Ich hatte das gleiche Problem mit einem Projekt und einigen Datendateien, die ich aus HIPPA-Gründen nicht in den Repokontext verschieben konnte. Am Ende habe ich 2 Dockerfiles verwendet. Man erstellt die Hauptanwendung ohne das, was ich außerhalb des Containers benötige, und veröffentlicht dies im internen Repo. Dann holt eine zweite Docker-Datei dieses Abbild und fügt die Daten hinzu und erstellt ein neues Abbild, das dann eingesetzt und niemals irgendwo gespeichert wird. Nicht ideal, aber es funktionierte für meine Zwecke, um vertrauliche Informationen aus dem Repo herauszuhalten.

0

Mit Docker-Compose habe ich dies geschafft, indem ich einen Dienst erstellt habe, der die von mir benötigten Datenträger bereitstellt, und das Image des Containers festschreibt. In dem darauffolgenden Dienst verlasse ich mich dann auf das zuvor festgeschriebene Image, in dem alle Daten an gemounteten Orten gespeichert sind. Sie müssen diese Dateien dann an das endgültige Ziel kopieren, da vom Host eingebundene Verzeichnisse beim Ausführen des Befehls docker commit nicht festgeschrieben werden

Sie müssen dafür kein Docker-Compose verwenden, aber das macht das Leben ein bisschen einfacher

# docker-compose.yml

version: '3'
  services:
    stage:
      image: Alpine
      volumes:
        - /Host/machine/path:/tmp/container/path
      command: bash -c "cp -r /tmp/container/path /final/container/path"
    setup:
      image: stage
# setup.sh

# Start "stage" service
docker-compose up stage

# Commit changes to an image named "stage"
docker commit $(docker-compose ps -q stage) stage

# Start setup service off of stage image
docker-compose up setup
0
Kris Rivera