Come montare un singolo file in un volume


257

Sto cercando di dockerizzare un'applicazione php. Nel file docker scarico l'archivio, lo estraggo ecc.

Tutto funziona bene, tuttavia se viene rilasciata una nuova versione, e aggiorno il file docker devo reinstallare l'applicazione, perché config.php viene sovrascritto.

Quindi ho pensato di poter montare il file come volume, come faccio con il database.

L'ho provato in due modi, con un volume e un percorso diretto.

finestra mobile-composizione:

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:

Che provoca l'errore:

E l'ho provato con un determinato percorso, come volume montato.

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

Tuttavia entrambi i modi non funzionano. Con il volume montato vedo che viene creato il caricamento.

Ma poi fallisce

/var/www/html/config.php \\ "causato \\" non una directory \\ "\" "

Se lo provo con

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

Docker crea la cartella di caricamento e quindi una cartella config.php. Non è un file.

O c'è un altro modo per persistere nella configurazione?


Nel mio caso, è semplice "toccare" un file vuoto prima di creare il contenitore / volume. Se il file non esisteva, creava una directory.
FreeSoftwareServers

Risposte:


312

TL; DR / Avviso:

Se si verifica una directory creata al posto del file che si sta tentando di montare, probabilmente non è stato possibile fornire un percorso valido e assoluto . Questo è un errore comune con una modalità di errore silenziosa e confusa.

I volumi di file vengono eseguiti in questo modo nella finestra mobile (esempio di percorso assoluto (è possibile utilizzare variabili env) ed è necessario menzionare il nome del file):

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

Puoi anche fare:

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

Se si attiva la finestra mobile-componi dalla /src/docker/myappcartella


81
Come ho detto, se provo /src/docker/myapp/upload/config.php:/var/www/html/config.php Docker crea la cartella di upload e quindi una cartella config.php. Non è un file.
Jakub Juszczak,

9
Nel tuo post hai scritto diversamente. Se il file è lì, dovrebbe essere montato come file.
BlackStork,

16
Affinché ciò funzionasse, dovevo fornire un percorso assoluto. Il suggerimento che utilizza PWD ha aiutato molto qui, grazie!
Steve Smith,

4
Per me sta creando una cartella anziché i file, ma penso che, poiché quel file viene copiato più avanti in quel percorso, c'è comunque modo di posticipare l'associazione?
eKelvin,

18
se /src/docker/myapp/upload/config.php non esiste nella finestra mobile host creerà una cartella ... Quello che sto facendo è creare uno script che crea un file vuoto prima di eseguire la finestra mobile - sarebbe l'ideale se posso dare istruzioni alla finestra mobile di farlo per me tramite arg cmd line.
cancerbero,

78

Avevo sofferto di un problema simile. Stavo cercando di importare il mio file di configurazione nel mio contenitore in modo da poterlo riparare ogni volta che ho bisogno senza ricostruire l'immagine.

Voglio dire, ho pensato che il comando seguente sarebbe stato $(pwd)/config.pymappato dall'host Docker al /root/app/config.pycontenitore come file.

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

Tuttavia, ha sempre creato una directory denominata config.py, non un file.

mentre cercavo un indizio, ho trovato il motivo (da qui )

Se si utilizza -v o --volume per eseguire il bind-mount di un file o directory che non esiste ancora sull'host Docker, -v creerà l'endpoint per voi. Viene sempre creato come directory .

Pertanto, viene sempre creato come directory perché il mio host docker non ha $(pwd)/config.py.

Anche se creo config.py nell'host docker. $(pwd)/config.pysolo overwirte /root/app/config.pynon esportando /root/app/config.py.


16
Ho appena aggiunto a touch path/to/filein Dockerfilemodo che quando monterò sarebbe ancora un file (non una directory creata)
Shadi

8
il lato sinistro di :deve essere percorso completo. Funziona in questo modo
sdkks il

La touchrisposta è stata, fatelo in Dockerfile, quindi il montaggio del volume composto da docker funzionerà correttamente senza creare una directory
ctrlbrk,

27

Usa mount ( --mount) invece volume ( -v)

Ulteriori informazioni: https://docs.docker.com/storage/bind-mounts/

Esempio:

Assicurarsi che /tmp/a.txt esista sull'host docker

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

Grazie Subbu, @Jakub Juszczak questa dovrebbe essere la risposta accettata, è l'unica risposta che risponde alla domanda e ha funzionato per me
neokyle

2
Questo non risponde davvero alla domanda. funzioneranno anche i volumi (perché il problema è nel percorso assoluto). L'unica differenza tra --mounte -vè il comportamento quando la parte host del volume non esiste ancora. Come per il tuo link:> Se usi -v o --volume per eseguire il bind-mount di un file o di una directory che non esiste ancora sull'host Docker, -v crea l'endpoint per te. Viene sempre creato come directory.
Il padrino

2
Non so come tradurre questo in una finestra mobile-componi. 'Poco aiuto?
msanford,

@msanford Ho aggiunto un esempio di composizione mobile alla risposta.
sebisnow,

10

Per chiunque utilizzi il contenitore Windows come me, sappi che NON PUOI legare o montare singoli file usando il contenitore Windows.

Gli esempi seguenti non funzioneranno quando si utilizzano contenitori basati su Windows, poiché la destinazione di un volume o di un bind mount all'interno del contenitore deve essere una di: una directory inesistente o vuota; o un'unità diversa da C :. Inoltre, l'origine di un mount bind deve essere una directory locale, non un file .

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 ...

È difficile da individuare ma è lì

Collegamento al problema di Github relativo alla mappatura dei file nel contenitore di Windows



7

A partire dalla versione 3.2 del file comporre docker è possibile specificare un montaggio di volume di tipo "bind" (anziché il tipo predefinito "volume") che consente di montare un singolo file nel contenitore. Cerca "bind mount" nei documenti di volume comporre docker: https://docs.docker.com/compose/compose-file/#volumes

Nel mio caso, stavo cercando di montare un singolo file ".secrets" nella mia applicazione che conteneva segreti solo per lo sviluppo e il test locali. In produzione la mia applicazione recupera invece questi segreti da AWS.

Se ho montato questo file come volume usando la sintassi abbreviata:

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

Docker creerebbe un ".secrets" directory all'interno del contenitore, invece di mappatura del file al di fuori del contenitore. Il mio codice genererebbe quindi un errore del tipo "IsADirectoryError: [Errno 21] È una directory: '.secrets'".

Ho risolto questo problema usando invece la sintassi a mano lunga, specificando il mio file di segreti usando un mount di volume "bind" di sola lettura:

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

Ora Docker monta correttamente il mio file .secrets nel contenitore, creando un file all'interno del contenitore anziché una directory. Spero che altri trovino utile questo esempio!


Grazie Signore! Questa era la soluzione di cui avevo bisogno per montare il mio file wp-config.php di WordPress (e impedirne la creazione come directory)
Jono,

6

Puoi anche usare un percorso relativo al tuo docker-compose.ymlfile in questo modo (testato su host Windows, contenitore Linux):

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

1
Ho provato questo su Mac con version: '3.7'specificato nel docker-compose.ymlfile con docker-compose versione 1.24.1, build 4667896b e ha funzionato.
Acumenus,

6
Ricevo ancora una directory anziché un file.
Chovy

0

Per me, il problema era che avevo un collegamento simbolico interrotto sul file che stavo provando a montare nel contenitore


0

Ho avuto lo stesso problema su Windows Docker 18.06.1-ce-win73 (19507).

Rimuovere e aggiungere nuovamente l'unità condivisa tramite il pannello delle impostazioni di Docker e tutto ha funzionato di nuovo.


0

In Windows, se hai bisogno di una variabile env $ {PWD} nel tuo docker-compose.yml puoi creare un file .env nella stessa directory del tuo file docker-compose.yml, quindi inserire manualmente il percorso della tua cartella.

CMD (pwd_var.bat):

echo PWD=%cd% >> .env

Powershell (pwd_var.ps1):

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

Esistono altre buone funzionalità per le variabili .env docker-compose: https://docs.docker.com/compose/reference/envvars/ specialmente per la COMPOSE_CONVERT_WINDOWS_PATHSvariabile env che consente alla composizione docker di accettare il percorso di Windows con baskslash "\".

Quando si desidera condividere un file su Windows, il file deve esistere prima di condividerlo con il contenitore.


Non è possibile utilizzare PowerShell con la finestra mobile, crea un blocco del fornitore e danneggia la comunità ...
Matej 'Yin' Gagyi

0

Forse questo aiuta qualcuno.

Ho avuto questo problema e ho provato di tutto. Le associazioni del volume sembravano buone e anche se ho montato la directory (non i file), avevo i nomi dei file nella directory montata correttamente ma montato come dirs.

Ho provato a riattivare le unità condivise e Docker si è lamentato che il firewall è attivo.

Dopo aver disabilitato il firewall tutto funzionava bene.


Grazie per questo! Il tuo post mi ha fatto capire che il mio selinux era impostato per far rispettare e che stava causando tutti i miei problemi. Non so perché eri sotto votato ¯_ (ツ) _ / ¯
Ottaviano

0

Puoi montare file o directory / cartelle, tutto dipende dal file o dalla directory di origine. Inoltre, devi fornire il percorso completo o se non sei sicuro di poter utilizzare PWD. Ecco un semplice esempio funzionante.

In questo esempio, sto montando il file env-command che esiste già nella mia directory di lavoro

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

-1

Ho lo stesso problema sul mio Windows 8.1

Si è scoperto che era dovuto alla distinzione tra maiuscole e minuscole del percorso. Ho chiamato docker-compose updalla directory cd /c/users/alex/e all'interno del contenitore un file è stato trasformato in directory.

Ma quando l'ho fatto cd /c/Users/alex/(non gli utenti in maiuscolo) e ho chiamato docker-compose upda lì, ha funzionato.

Nel mio sistema sia la directory Users sia la directory Alex sono in maiuscolo, anche se sembra che contino solo la directory Users.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.