Tambahkan volume ke Docker, tetapi kecualikan sub-folder

210

Misalkan saya memiliki wadah Docker dan folder di host saya /hostFolder. Sekarang jika saya ingin menambahkan folder ini ke wadah Docker sebagai volume, maka saya bisa melakukan ini dengan menggunakan ADDdi Dockerfileatau memasangnya sebagai volume.

Sejauh ini baik.

Sekarang /hostFolderberisi sub-folder /hostFolder/subFolder,.

Saya ingin me-mount /hostFolderke dalam wadah Docker (apakah sebagai read-write atau read-only tidak masalah, bekerja baik untuk saya), tapi saya tidak ingin memilikinya termasuk /hostFolder/subFolder. Saya ingin mengecualikan ini, dan saya juga ingin wadah Docker dapat membuat perubahan pada sub-folder ini, tanpa konsekuensi mengubahnya di host juga.

Apakah ini mungkin? Jika ya, bagaimana caranya?

Golo Roden
sumber
2
@AbhijitSarkar itu bukan komentar yang sangat konstruktif (juga tidak membantu).
kano
1
@Kano Ini adalah komentar, bukan jawaban.
Abhijit Sarkar

Jawaban:

398

Menggunakan docker-compose saya bisa menggunakan node_modules secara lokal, tetapi abaikan saja dalam wadah buruh pelabuhan menggunakan sintaks berikut di docker-compose.yml

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

Jadi semuanya ./angularAppdipetakan ke /opt/appdan kemudian saya membuat volume mount lain /opt/app/node_modules/yang sekarang direktori kosong - bahkan jika di mesin lokal saya ./angularApp/node_modulestidak kosong.

kernel
sumber
3
Ini berfungsi tetapi saya tidak dapat menghapus dir ini di dalam wadah. Sebagai contoh: saya perlu mengganti /opt/app/node_modules/dengan direktori lain dengan nama yang sama. Kesalahan terjadi: 'volume sibuk'
Stepan Yudin
32
Jangan lupa garis miringnya! misalnya. / opt / app / node_modules tidak berfungsi, itu akan ditimpa oleh ./angularApp/node_modules
Stingus
3
Trik ini digunakan untuk saya, tetapi sepertinya tidak lagi, bahkan untuk file Tulis yang sama. Penasaran apakah itu juga berhenti bekerja untuk orang lain.
Plinehan
8
Terima kasih! Kamu menyelamatkan hariku! Dalam hal menggunakan buruh pelabuhan sederhana, bukan kompos itu akan terlihat seperti: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart
3
Saya menemukan dokumen tersebut, 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
118

Jika Anda ingin subdirektori diabaikan oleh komposisi buruh pelabuhan tetapi gigih, Anda dapat melakukan hal berikut di docker-compose.yml:

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

Hal ini akan me-mount direktori Anda saat ini sebagai volume bersama, tapi me-mount volume buruh pelabuhan terus-menerus di tempat lokal Anda node_modulesdirektori. Ini mirip dengan jawaban oleh @kernix, tetapi ini akan memungkinkan node_modulesuntuk bertahan di antara proses docker-compose up, yang kemungkinan merupakan perilaku yang diinginkan.

Nate T
sumber
20
Volume yang dinamai adalah pendekatan yang unggul. Protip: pastikan Anda tidak menggunakan nama volume ditulis dgn tanda penghubung. Anda akan menghabiskan sebagian kecil hidup Anda dalam mimpi buruk debug, hanya untuk mengetahui bahwa Anda sekali lagi tertipu oleh nuansa konyol.
dustintheweb
3
"Perhatikan bahwa menulis buruh pelabuhan akan membunuh volume persisten ini." Ini tidak benar di Docker untuk Mac v 17.0.5+ (dan mungkin versi yang lebih lama). docker-compose downakan menghapus wadah, tetapi volumenya akan tetap ada sampai Anda menjalankan sesuatu sepertidocker system prune
BrDaHa
3
Jika seseorang tertarik untuk memahami mengapa menggunakan node_modules:volume bernama "abaikan" /app/node_moduleswadah penampung, dapat menemukan posting ini bermanfaat Bagaimana buruh pelabuhan menangani beberapa jenis pemasangan?
ira
3
Saya tidak tahu apakah saya melakukan sesuatu yang salah, tetapi jika saya melakukan ini, mulai wadah dan kemudian jalankan npm install pada mesin HOST, itu mengubah node_modules di dalam CONTAINER juga. Saya tidak bisa membayangkan mengapa ada orang yang mau melakukan itu, tetapi saya masih mencari pemisahan yang lebih bersih.
Renra
3
@Renra memiliki masalah yang sama persis, mesin host saya akan terus menulis melalui node_modules meskipun saya memiliki volume bernama ... menyebabkan semua jenis masalah ketidakcocokan. Menyerah untuk memperbaikinya dan mengatasinya dengan hanya menyalin folder src saya alih-alih seluruh repo
dancypants
19

Untuk mengecualikan file, gunakan yang berikut ini

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded
Frank Wong
sumber
6
Solusi sempurna untuk apa yang saya butuhkan (untuk TIDAK memetakan node_modules ke host karena hal-hal symlink rusak pada host Windows). Menunjuk ke / dev / null tidak berfungsi, tetapi membuat direktori kosong dan memetakannya agar bekerja dengan sempurna dan menyelesaikan masalah yang saya alami - terima kasih untuk ide ini.
Liam Hammett
1
Ini tidak bekerja di Docker untuk 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. Menambahkan garis miring tidak membantu.
Blaise
Saya dapat mengkonfirmasi bahwa itu tidak berfungsi baik di Ubuntu 16.04 dengan Docker 18.09.3.
Dirk
Itu tidak berhasil untuk saya. Yang dilakukannya hanyalah menyalin /dev/nullke dalam wadah, sebagai file perangkat.
Radon Rosborough
1
Harap perhatikan ini hanya berfungsi untuk mengecualikan FILES! / dev / null adalah sebuah file dan begitu harus target, pesan kesalahan cukup jelas tentang ini: 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. Ini bukan apa yang dicari OP, tapi itu sangat berguna bagi saya, karena saya perlu mengecualikan satu file.
Avius
13

Pertama, menggunakan ADDinstruksi dalam Dockerfile sangat berbeda dari menggunakan volume (baik melalui -vargumen ke docker runatau VOLUMEinstruksi dalam Dockerfile). The ADDdan COPYperintah hanya mengambil salinan file pada saat docker builddijalankan. File-file ini tidak diperbarui sampai gambar baru dibuat dengan docker buildperintah. Sebaliknya, menggunakan volume pada dasarnya mengatakan "direktori ini tidak boleh disimpan dalam gambar wadah; melainkan gunakan direktori pada host"; setiap kali file di dalam volume diubah, tuan rumah dan wadah akan melihatnya segera.

Saya tidak percaya Anda dapat mencapai volume yang Anda inginkan, Anda harus memikirkan kembali struktur direktori Anda jika Anda ingin melakukan ini.

Namun, cukup mudah untuk menggunakan COPY(yang harus disukai ADD). Anda dapat menggunakan .dockerignorefile untuk mengecualikan subdirektori, atau Anda dapat melakukan COPYsemua file kemudian RUN rm blauntuk menghapus subdirektori.

Ingat bahwa setiap file yang Anda tambahkan ke gambar dengan COPYatau ADDharus berada di dalam konteks build yaitu di dalam atau di bawah direktori tempat Anda menjalankan docker build.

Adrian Mouat
sumber
1
pelajari sesuatu yang baru setiap hari :-) COPY dan ADD bekerja dari konteks build (bukan host). Apakah mungkin menggunakan volume untuk menutupi subfolder? OP ingin me-mount / hostFolder (saya pikir), dan membuat / hostFolder / subFolder terputus. Jika ada VOLUME untuk masing-masing, tetapi hanya hostFolder yang 'dipasang' (-v), apakah itu akan mengisolasi perubahan subFolder ke wadah?
Greg
Saya tidak yakin, saya belum pernah mencoba volume bersarang. Saya tidak yakin itu ide yang bagus, tetapi saya harus memeriksanya.
Adrian Mouat
1
Sepertinya saya tidak dapat menemukan contoh di mana saja dari apa yang dimasukkan ke dalam .dockerignorefile untuk mengecualikan sub direktori (atau bahkan direktori). Mengingat itu adalah tujuan file yang dinyatakan, itu cukup aneh.
Lukas Oberhuber
1
setelah Anda menambahkan file, mereka masih berakhir di beberapa lapisan. Jadi penghapusan mereka tidak akan membantu Anda menyembunyikannya jika keamanan sensitif atau mengurangi ukuran gambar (karena mereka akan berada di lapisan yang mendasarinya). Ada opsi untuk squashlapisan. Salah satunya adalah github.com/goldmann/docker-squash dan lainnya menggunakan oc ex dockerbuilddari proyek openshift.
akostadinov
6

Sepertinya solusi lama tidak berfungsi lagi (setidaknya untuk saya). Namun, membuat folder kosong dan memetakan folder target membantu.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/
pegangan
sumber
Juga tidak bekerja untuk saya docker-compose 1.25.0-rc3, sintaksis file v3.
desain iniism
6

Dengan baris perintah buruh pelabuhan:

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

The -vpilihan juga dapat digunakan (kredit untuk Bogdan Mart ), tapi --mountlebih jelas dan direkomendasikan .

DS.
sumber
6

untuk orang-orang yang juga memiliki masalah bahwa folder node_modules masih akan menimpa dari sistem lokal Anda dan sebaliknya

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

Ini solusinya, Dengan membuntuti /setelah node_modules menjadi perbaikan.

Daenor
sumber
0

Untuk mengecualikan file yang dipasang yang terkandung dalam volume mesin Anda, Anda harus menimpanya dengan mengalokasikan volume ke file yang sama. Dalam file konfigurasi Anda:

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

Contoh di dockerfile Anda:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
Emmario Delar
sumber