Aggiungi un volume a Docker, ma escludi una sottocartella


210

Suppongo di avere un contenitore Docker e una cartella sul mio host /hostFolder. Ora, se voglio aggiungere questa cartella al contenitore Docker come un volume, allora posso farlo sia utilizzando ADDin Dockerfileo il montaggio come volume.

Fin qui tutto bene.

Ora /hostFoldercontiene una sottocartella, /hostFolder/subFolder.

Voglio montare /hostFoldernel contenitore Docker (sia che sia di sola lettura che di sola lettura non importa, funziona sia per me), ma NON voglio averlo incluso /hostFolder/subFolder. Voglio escluderlo e voglio anche che il contenitore Docker sia in grado di apportare modifiche a questa sottocartella, senza la conseguenza di averlo modificato anche sull'host.

È possibile? Se é cosi, come?


2
@AbhijitSarkar non è un commento molto costruttivo (né utile in alcun modo).
kano,

1
@Kano È un commento, non una risposta.
Abhijit Sarkar,

Risposte:


399

Usando docker-compose sono in grado di usare node_modules localmente, ma ignorarlo nel contenitore docker usando la sintassi seguente nel docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

Quindi tutto in ./angularAppè mappato/opt/app e quindi creo un altro volume di montaggio /opt/app/node_modules/che ora è una directory vuota, anche se nella mia macchina locale ./angularApp/node_modulesnon è vuota.


3
Funziona ma non riesco a rimuovere queste directory all'interno del contenitore Ad esempio: devo sostituire /opt/app/node_modules/con un'altra directory con lo stesso nome. Si verifica un errore: "volume occupato"
Stepan Yudin,

32
Non dimenticare la barra finale! per esempio. / opt / app / node_modules non funziona, verrà sovrascritto da ./angularApp/node_modules
Stingus

3
Questo trucco funzionava per me, ma non sembra più, anche per lo stesso file Compose. Curioso se smettesse di funzionare anche per gli altri.
Plinehan,

8
Grazie! Mi hai salvato la giornata! In caso di utilizzo di una semplice finestra mobile, non composta sembrerebbe: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart

3
Ho trovato il documento, docs.docker.com/storage/volumes/… . If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.
Hiroshi,

119

Se si desidera che le sottodirectory vengano ignorate da docker-compose ma persistenti, è possibile effettuare le seguenti operazioni in docker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

Questo monterà la directory corrente come volume condiviso, ma monterà un volume finestra mobile persistente al posto della node_modulesdirectory locale . Questo è simile alla risposta di @kernix, ma ciò consentirà node_modulesdi persistere tra le docker-compose upesecuzioni, che è probabilmente il comportamento desiderato.


20
I volumi nominati rappresentano un approccio superiore. Protip: assicurati di non utilizzare un nome volume sillabato. Trascorrerai una piccola parte della tua vita in un incubo di debug, solo per scoprire di essere stato nuovamente ingannato da una sfumatura ridicola.
dustintheweb

3
"Nota che la composizione docker-down eliminerà questi volumi persistenti." Questo non è vero in Docker per Mac v 17.0.5+ (e forse versioni precedenti). docker-compose downrimuoverà i contenitori, ma il volume persisterà fino a quando non docker system prune
eseguirai

3
Nel caso in cui qualcuno sia interessato a capire perché l' utilizzo del node_modules:volume denominato "ignora" il contenuto /app/node_modulesnel contenitore finestra mobile, questo post può essere utile Come la finestra mobile gestisce più tipi di montaggio?
ira,

3
Non so se sto facendo qualcosa di sbagliato, ma se lo faccio, avvia il container e quindi avvia npm install sulla macchina HOST, cambia anche node_modules all'interno del CONTAINER. Non riesco a immaginare perché qualcuno voglia farlo, ma sto ancora cercando una separazione più pulita.
Renra,

3
@Renra aveva lo stesso identico problema, la mia macchina host scriveva costantemente su node_modules anche se avevo il volume nominato ... causava ogni sorta di problemi di incompatibilità.
Ho smesso di

19

Per escludere un file, utilizzare quanto segue

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

6
Soluzione perfetta per ciò di cui avevo bisogno (NON mappare node_modules sull'host perché roba symlink si è rotta su un host Windows). Indicare / dev / null non ha funzionato, ma creare una directory vuota e mapparla su quella ha funzionato perfettamente e risolto i problemi che stavo avendo - grazie per questa idea.
Liam Hammett,

1
Questo non funziona in Docker for Mac 18.09.0: Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. L'aggiunta di una barra finale non ha aiutato.
Blaise,

Posso confermare che non funziona neanche su Ubuntu 16.04 con Docker 18.09.3.
Dirk,

Questo non funziona per me. Tutto ciò che fa è copiare /dev/nullnel contenitore, come file del dispositivo.
Radon Rosborough,

1
Si noti che questo funziona solo per l'esclusione di FILE! / dev / null è un file e così deve essere l'obiettivo, il messaggio di errore è abbastanza chiaro su questo: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. Questo non è esattamente ciò che l'OP stava cercando, ma è stato molto utile per me, poiché avevo bisogno di escludere un singolo file.
Avius,

13

Innanzitutto, l'utilizzo ADDdell'istruzione in un file Docker è molto diverso dall'uso di un volume (tramite l' -vargomento docker runo l' VOLUMEistruzione in un file Docker). I comandi ADDe COPYprendono solo una copia dei file al momento docker builddell'esecuzione. Questi file non vengono aggiornati fino a quando non viene creata una nuova immagine con il docker buildcomando. Al contrario, l'utilizzo di un volume in sostanza sta dicendo "questa directory non deve essere archiviata nell'immagine contenitore; utilizzare invece una directory sull'host"; ogni volta che un file all'interno di un volume viene modificato, sia l'host che il contenitore lo vedranno immediatamente.

Non credo che tu possa ottenere ciò che vuoi usando i volumi, dovrai ripensare la struttura della tua directory se vuoi farlo.

Tuttavia, è abbastanza semplice da ottenere utilizzando COPY(che dovrebbe essere preferito a ADD). È possibile utilizzare un .dockerignorefile per escludere la sottodirectory oppure è possibile COPYeseguire tutti i fileRUN rm bla per rimuovere la sottodirectory.

Ricorda che tutti i file che aggiungi all'immagine con COPYo ADDdevono trovarsi all'interno del contesto di compilazione, ovvero all'interno o sotto la directory da cui esegui docker build.


1
impara qualcosa di nuovo ogni giorno :-) i lavori COPIA e AGGIUNGI dal contesto di compilazione (non l'host). Sarebbe possibile usare un volume per mascherare la sottocartella? L'OP vuole montare / hostFolder (credo), e rendere / hostFolder / subFolder disconnessi. Se ci fosse un VOLUME per ciascuno, ma solo la cartella host fosse 'montata' (-v), questo isolerebbe le modifiche alla sottocartella nel contenitore?
Greg

Non sono sicuro, non ho mai provato a nidificare i volumi. Non sono convinto che sia una buona idea, ma dovrei esaminarlo.
Adrian Mouat,

1
Non riesco a trovare un esempio da nessuna parte di cosa mettere in un .dockerignorefile per escludere una sottodirectory (o anche una directory). Dato che è lo scopo dichiarato del file, è abbastanza strano.
Lukas Oberhuber,

1
una volta aggiunti i file, questi finiscono comunque in alcuni livelli. Quindi rimuoverli non ti aiuterà a nasconderli se sensibili alla sicurezza o ridurre le dimensioni dell'immagine (perché saranno nei livelli sottostanti). Ci sono opzioni per squashi livelli. Uno è github.com/goldmann/docker-squash e un altro viene utilizzato oc ex dockerbuilddal progetto openshift.
Akostadinov l'

6

Sembra che la vecchia soluzione non funzioni più (almeno per me). La creazione di una cartella vuota e la mappatura della cartella di destinazione su di essa sono state di aiuto.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/

Non funziona neanche con me, con la docker-compose 1.25.0-rc3sintassi dei file v3.
thisismydesign

6

Con la riga di comando della finestra mobile:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

L' -vopzione può anche essere utilizzata (credito a Bogdan Mart ), ma --mountè più chiara e consigliata .


6

per le persone che avevano anche il problema che la cartella node_modules continuava a sovrascrivere dal sistema locale e viceversa

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/

Questa è la soluzione, con il trailing /dopo che node_modules è la correzione.


0

Per escludere un file montato contenuto nel volume del tuo computer, dovrai sovrascriverlo allocando un volume a questo stesso file. Nel tuo file di configurazione:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

Un esempio nel tuo file docker:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
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.