So hängen Sie eine einzelne Datei in ein Volume ein


256

Ich versuche, eine PHP-Anwendung anzudocken. In der Docker-Datei lade ich das Archiv herunter, extrahiere es usw.

Alles funktioniert einwandfrei, aber wenn eine neue Version veröffentlicht wird und ich die Docker-Datei aktualisiere, muss ich die Anwendung neu installieren, da die config.php überschrieben wird.

Also dachte ich, ich kann die Datei als Volume mounten, so wie ich es mit der Datenbank mache.

Ich habe es auf zwei Arten versucht, mit einem Volume und einem direkten Pfad.

Docker-Compose:

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:

Was zu dem Fehler führt:

Und ich habe es mit einem bestimmten Pfad versucht, als gemountetes Volume.

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

Beide Möglichkeiten funktionieren jedoch nicht. Mit dem gemounteten Volume sehe ich, dass ein Upload erstellt wird.

Aber dann scheitert mit

/var/www/html/config.php \\ "verursacht \\" kein Verzeichnis \\ "\" "

Wenn ich es mit versuche

/src/docker/myapp/upload/config.php:/var/www/html/config.php

Docker erstellt den Upload-Ordner und anschließend einen config.php-Ordner. Keine Datei.

Oder gibt es eine andere Möglichkeit, die Konfiguration beizubehalten?


In meinem Fall ist es einfach, eine leere Datei zu "berühren", bevor der Container / das Volume erstellt wird. Wenn die Datei nicht vorhanden war, wurde ein Verzeichnis erstellt.
FreeSoftwareServers

Antworten:


311

TL; DR / Hinweis:

Wenn anstelle der Datei, die Sie bereitstellen möchten, ein Verzeichnis erstellt wird, haben Sie wahrscheinlich keinen gültigen und absoluten Pfad angegeben. Dies ist ein häufiger Fehler bei einem stillen und verwirrenden Fehlermodus.

Dateivolumes werden im Docker auf diese Weise erstellt (Beispiel für einen absoluten Pfad (kann env-Variablen verwenden), und Sie müssen den Dateinamen angeben):

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php

Sie können auch tun:

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

Wenn Sie den Docker-Compose aus /src/docker/myappOrdner auslösen


81
Wie gesagt, wenn ich /src/docker/myapp/upload/config.php:/var/www/html/config.php versuche, erstellt Docker den Upload-Ordner und dann einen config.php-Ordner. Keine Datei.
Jakub Juszczak

9
In deinem Beitrag hast du anders geschrieben. Wenn die Datei vorhanden ist, sollte sie als Datei bereitgestellt werden.
BlackStork

16
Damit dies funktioniert, musste ich einen absoluten Pfad angeben. Der Tipp mit PWD hat hier sehr geholfen, danke!
Steve Smith

4
Für mich ist das Erstellen eines Ordners anstelle der Dateien, aber ich denke, weil diese Datei später in diesen Pfad kopiert wird, gibt es trotzdem eine Möglichkeit, die Bindung zu verschieben?
eKelvin

18
Wenn /src/docker/myapp/upload/config.php nicht im Host-Docker vorhanden ist, wird ein Ordner erstellt. Ich erstelle ein Skript, das eine leere Datei erstellt, bevor Docker ausgeführt wird wenn ich Docker anweisen kann, dies für mich über cmd line args zu tun.
Cancerbero

78

Ich hatte unter einem ähnlichen Problem gelitten. Ich habe versucht, meine Konfigurationsdatei in meinen Container zu importieren, damit ich sie jedes Mal reparieren kann, ohne das Image neu zu erstellen.

Ich meine, ich dachte, der folgende Befehl würde $(pwd)/config.pyvom Docker-Host /root/app/config.pyals Datei in den Container abgebildet .

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image

Es wurde jedoch immer ein Verzeichnis mit dem Namen erstellt config.py, keine Datei.

Auf der Suche nach einem Hinweis fand ich den Grund (von hier )

Wenn Sie -v oder --volume verwenden, um eine Datei oder ein Verzeichnis zu binden, die noch nicht auf dem Docker-Host vorhanden sind, erstellt -v den Endpunkt für Sie. Es wird immer als Verzeichnis erstellt .

Daher wird es immer als Verzeichnis erstellt, da mein Docker-Host dies nicht hat $(pwd)/config.py.

Auch wenn ich config.py im Docker-Host erstelle. $(pwd)/config.pynur verdrahtet /root/app/config.pynicht exportieren /root/app/config.py.


16
Ich habe gerade ein touch path/to/filein hinzugefügt, Dockerfileso dass es beim Mounten immer noch eine Datei ist (kein erstelltes
Verzeichnis

8
Die linke Seite von :muss voller Pfad sein. Es funktioniert so
sdkks

Das touchwar die Antwort: Tun Sie dies in Dockerfile, dann funktioniert Ihr Docker-Compose-Volume-Mount ordnungsgemäß, ohne ein Verzeichnis zu erstellen
ctrlbrk

27

Verwenden Sie mount ( --mount) anstelle von volume ( -v)

Weitere Informationen: https://docs.docker.com/storage/bind-mounts/

Beispiel:

Stellen Sie sicher, dass /tmp/a.txt auf dem Docker-Host vorhanden ist

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh

Vielen Dank Subbu, @Jakub Juszczak dies sollte die akzeptierte Antwort sein, es ist die einzige Antwort, die die Frage überhaupt beantwortet, und es hat bei mir
funktioniert

2
Dies beantwortet die Frage nicht wirklich. Volumes funktionieren ebenfalls (da sich das Problem im absoluten Pfad befindet). Der einzige Unterschied zwischen --mountund -vist das Verhalten, wenn der Host-Teil des Volumes noch nicht vorhanden ist. Gemäß Ihrem Link:> Wenn Sie -v oder --volume verwenden, um eine Datei oder ein Verzeichnis, das noch nicht auf dem Docker-Host vorhanden ist, zu binden und zu mounten, erstellt -v den Endpunkt für Sie. Es wird immer als Verzeichnis erstellt.
Der Pate

2
Ich weiß nicht, wie ich das in eine Docker-Komposition übersetzen soll. 'Kleine Hilfe?
Msanford

@msanford Ich habe der Antwort ein Docker-Compose-Beispiel hinzugefügt.
Sebisnow

10

Wenn Sie einen Windows-Container wie mich verwenden, sollten Sie wissen, dass Sie einzelne Dateien mit dem Windows-Container NICHT binden oder bereitstellen können.

Die folgenden Beispiele schlagen fehl, wenn Windows-basierte Container verwendet werden, da das Ziel eines Volumes oder eines Bind-Mount im Container eines der folgenden sein muss: ein nicht vorhandenes oder leeres Verzeichnis; oder ein anderes Laufwerk als C:. Außerdem muss die Quelle eines Bind-Mount ein lokales Verzeichnis sein, keine Datei .

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

Es ist schwer zu erkennen, aber es ist da

Link zum Github-Problem bezüglich der Zuordnung von Dateien zum Windows-Container



7

Ab Docker-Compose-Datei Version 3.2 können Sie einen Volume-Mount vom Typ "bind" (anstelle des Standardtyps "volume") angeben , mit dem Sie eine einzelne Datei in den Container einbinden können. Suchen Sie in den Docker-Compose-Volume-Dokumenten nach "bind mount": https://docs.docker.com/compose/compose-file/#volumes

In meinem Fall habe ich versucht, eine einzelne ".secrets" -Datei in meine Anwendung einzubinden, die nur Geheimnisse für die lokale Entwicklung und das Testen enthielt. In der Produktion holt meine Anwendung stattdessen diese Geheimnisse von AWS.

Wenn ich diese Datei als Volume mit der Kurzsyntax gemountet habe:

volumes:
 - ./.secrets:/data/app/.secrets

Docker würde ein „.secrets“ erstellen Verzeichnis im Innern des Behälters statt Abbildung auf die Datei außerhalb des Behälters. Mein Code würde dann einen Fehler wie "IsADirectoryError: [Errno 21] Ist ein Verzeichnis: '.secrets'" auslösen.

Ich habe dies behoben, indem ich stattdessen die Langhandsyntax verwendet habe und meine Geheimdatei mit einem schreibgeschützten "Bind" -Volume-Mount angegeben habe:

volumes:
 - type: bind
   source: ./.secrets
   target: /data/app/.secrets
   read_only: true

Jetzt hängt Docker meine .secrets-Datei korrekt in den Container ein und erstellt eine Datei im Container anstelle eines Verzeichnisses. Hoffe, andere finden dieses Beispiel hilfreich!


Danke mein Herr! Das war die Lösung, die ich brauchte, um meine WordPress-Datei wp-config.php zu mounten (und zu verhindern, dass sie als Verzeichnis erstellt wird)
Jono

6

Sie können auch einen relativen Pfad zu Ihrer docker-compose.ymlDatei wie folgt verwenden (getestet auf Windows-Host, Linux-Container):

 volumes:
      - ./test.conf:/fluentd/etc/test.conf

1
Ich habe dies auf einem Mac mit der version: '3.7'in der docker-compose.ymlDatei angegebenen Docker-Compose-Version 1.24.1, Build 4667896b, getestet und es hat funktioniert.
Acumenus

6
Ich bekomme immer noch ein Verzeichnis anstelle einer Datei.
Chovy

0

Für mich war das Problem, dass ich einen fehlerhaften symbolischen Link in der Datei hatte, die ich in den Container einbinden wollte


0

Ich hatte das gleiche Problem unter Windows Docker 18.06.1-ce-win73 (19507).

Entfernen und erneutes Hinzufügen des freigegebenen Laufwerks über das Docker-Einstellungsfeld und alles funktionierte wieder.


0

Wenn Sie in Windows die Umgebungsvariable $ {PWD} in Ihrer Datei docker-compose.yml benötigen, können Sie eine ENV-Datei im selben Verzeichnis wie Ihre Datei docker-compose.yml erstellen und dann manuell den Speicherort Ihres Ordners einfügen.

CMD (pwd_var.bat):

echo PWD=%cd% >> .env

Powershell (pwd_var.ps1):

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env

Es gibt weitere gute Funktionen für Docker-Compose-ENV-Variablen: https://docs.docker.com/compose/reference/envvars/, insbesondere für die COMPOSE_CONVERT_WINDOWS_PATHSEnv-Variable, mit der Docker Compose Windows-Pfade mit Baskslash akzeptieren kann "\".

Wenn Sie eine Datei unter Windows freigeben möchten, muss die Datei vorhanden sein, bevor Sie sie für den Container freigeben können.


Sie können PowerShell nicht mit Docker verwenden, es erstellt eine Lieferantenbindung und verletzt die Community ...
Matej 'Yin' Gagyi

0

Vielleicht hilft das jemandem.

Ich hatte dieses Problem und habe alles versucht. Datenträgerbindungen sahen gut aus und selbst wenn ich ein Verzeichnis (keine Dateien) gemountet hatte, hatte ich die Dateinamen im gemounteten Verzeichnis korrekt, aber als Verzeichnisse gemountet.

Ich habe versucht, freigegebene Laufwerke wieder zu aktivieren, und Docker hat sich beschwert, dass die Firewall aktiv ist.

Nach dem Deaktivieren der Firewall funktionierte alles einwandfrei.


Danke für das! Ihr Beitrag hat mir klar gemacht, dass mein Selinux auf Durchsetzung gesetzt war und dass dies alle meine Probleme verursachte. Ich weiß nicht, warum du herabgestimmt wurdest ¯_ (ツ) _ / ¯
Octavian

0

Sie können Dateien oder Verzeichnisse / Ordner bereitstellen, die von der Quelldatei oder dem Quellverzeichnis abhängen. Außerdem müssen Sie den vollständigen Pfad angeben oder wenn Sie nicht sicher sind, ob Sie PWD verwenden können. Hier ist ein einfaches Arbeitsbeispiel.

In diesem Beispiel mounte ich eine env-Befehlsdatei, die bereits in meinem Arbeitsverzeichnis vorhanden ist

$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"

-1

Ich habe das gleiche Problem unter Windows 8.1

Es stellte sich heraus, dass dies auf die Groß- und Kleinschreibung des Pfades zurückzuführen war. Ich habe docker-compose upaus dem Verzeichnis aufgerufen cd /c/users/alex/und im Container wurde eine Datei in ein Verzeichnis umgewandelt.

Aber als ich es tat cd /c/Users/alex/(nicht Benutzer groß geschrieben) und docker-compose upvon dort aus anrief, funktionierte es.

In meinem System werden sowohl Users dir als auch Alex dir großgeschrieben, obwohl es so aussieht, als ob nur Users dir eine Rolle spielt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.