Docker ADD vs VOLUME

116

Saya mempelajari Docker dan saya ragu tentang kapan dan di mana harus menggunakan ADDdan VOLUME. Inilah yang menurut saya dilakukan oleh keduanya:

MENAMBAHKAN

Salin file ke gambar pada waktu pembuatan. Gambar memiliki semua file sehingga Anda dapat menerapkannya dengan sangat mudah. Di sisi lain, perlu membangun setiap saat bukanlah ide yang baik dalam pengembangan karena pembangunan memerlukan pengembang untuk menjalankan perintah untuk membangun kembali kontainer; Selain itu, membangun wadah bisa memakan waktu.

VOLUME

Saya memahami bahwa menggunakan docker run -vAnda dapat memasang folder host di dalam penampung Anda, dengan cara ini Anda dapat dengan mudah memodifikasi file dan melihat aplikasi di penampung Anda bereaksi terhadap perubahan. Ini terlihat bagus dalam pengembangan, tetapi saya tidak yakin bagaimana menyebarkan file saya dengan cara ini.

Cristian Garcia
sumber
3
Secara umum, yang terbaik untuk memilih COPYuntuk ADD. Mereka hampir sama, tetapi ADDmemiliki beberapa kemampuan ekstra untuk menulis URL dan file arsip yang dapat mengejutkan.
Adrian Mouat
2
@jamesmstone - tautan itu (dan dokumen resmi buruh pelabuhan) merekomendasikan sebaliknya - gunakan SALIN daripada TAMBAH.
Software Engineer
Ups, Anda benar - selamat!
jamesmstone

Jawaban:

183

MENAMBAHKAN

Perbedaan mendasar antara keduanya adalah ADDmembuat apa pun yang Anda tambahkan, baik itu folder atau hanya file yang sebenarnya menjadi bagian dari gambar Anda . Siapa pun yang menggunakan gambar yang Anda buat setelah itu akan memiliki akses ke apa pun Anda ADD. Ini benar bahkan jika Anda kemudian menghapusnya karena Docker berfungsi dalam lapisan dan ADDlapisan tersebut akan tetap ada sebagai bagian dari gambar. Untuk lebih jelasnya, Anda hanya memiliki ADDsesuatu pada waktu pembuatan dan tidak pernah dapat ADDpada saat berjalan.

Beberapa contoh kasus yang ingin Anda gunakan ADD:

  • Anda memiliki beberapa persyaratan dalam file requirement.txt yang ingin Anda rujuk dan instal di Dockerfile Anda. Anda kemudian dapat melakukan: ADD ./requirements.txt /requirements.txtdiikuti olehRUN pip install -r /requirements.txt
  • Anda ingin menggunakan kode aplikasi Anda sebagai konteks di Dockerfile Anda, misalnya, jika Anda ingin menyetel direktori aplikasi Anda sebagai direktori kerja di gambar Anda dan agar perintah default dalam wadah dijalankan dari gambar Anda benar-benar menjalankan aplikasi Anda, Anda bisa melakukan:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUME

Volume, di sisi lain, hanya memungkinkan sebuah kontainer berjalan dari gambar Anda memiliki akses ke beberapa jalur di mesin lokal apa pun tempat kontainer sedang dijalankan. Anda tidak dapat menggunakan file dari VOLUMEdirektori Anda di Dockerfile . Apa pun yang ada di direktori volume Anda tidak akan dapat diakses pada waktu pembuatan, tetapi akan dapat diakses pada waktu proses .

Beberapa contoh kasus yang ingin Anda gunakan VOLUME:

  • Aplikasi yang dijalankan di penampung Anda membuat log in /var/log/my_app. Anda ingin log tersebut dapat diakses di mesin host dan tidak dihapus saat container dihapus. Anda dapat melakukan ini dengan membuat titik pemasangan di /var/log/my_appdengan menambahkan VOLUME /var/log/my_appke Dockerfile Anda dan kemudian menjalankan container Anda dengandocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Anda memiliki beberapa file setelan lokal yang Anda ingin agar dapat diakses oleh aplikasi dalam penampung. Mungkin file pengaturan tersebut berbeda di komputer lokal Anda vs dev vs production. Terutama jika file pengaturan tersebut dirahasiakan, dalam hal ini Anda pasti tidak menginginkannya ada dalam gambar Anda . Strategi yang baik dalam hal ini adalah menambahkan VOLUME /etc/settings/my_app_settingske Dockerfile Anda, menjalankan container Anda dengan docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tag, dan memastikan / host / settings / dir ada di semua lingkungan yang Anda harapkan untuk menjalankan aplikasi Anda.
Eli
sumber
13
Sejauh ini posting paling berguna yang saya temukan sejauh ini di ADD dan VOLUME
Jasmeet
5
Apa yang terjadi jika VOLUME ditentukan, namun tidak tersedia selama menjalankan buruh pelabuhan (misalnya parameter -v xxx hilang)? Apakah resp tersebut. VOLUME kemudian secara efektif menjadi sementara?
col.panic
Di dalam Dockerfile, volume mungkin dimaksudkan hanya untuk persistensi dan / atau debugging, tetapi Anda dapat menggunakan tombol baris perintah volume untuk memasukkan aplikasi ke dalam image yang ada (tidak diperlukan Dockerfile) dan menjalankannya seperti ini docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro
detail "lapisan" yang bagus
stratovarius
27

The VOLUMEinstruksi menciptakan volume data dalam kontainer Docker Anda saat runtime. Direktori yang diberikan sebagai argumen ke VOLUMEadalah direktori yang melewati Sistem File Union , dan terutama digunakan untuk data persisten dan bersama.

Jika Anda menjalankan docker inspect <your-container>, Anda akan melihat di bawah Mountsbagian ada Sourceyang mewakili lokasi direktori pada host, dan Destinationyang mewakili lokasi direktori yang dipasang di wadah. Sebagai contoh,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Berikut 3 kasus penggunaan untuk docker run -v:

  1. docker run -v /data: Ini analog dengan menentukan VOLUMEinstruksi di Dockerfile Anda.
  2. docker run -v $host_path:$container_path: Ini memungkinkan Anda untuk memasang $host_pathdari host Anda ke $container_pathdalam penampung Anda selama runtime. Dalam pengembangan, ini berguna untuk berbagi kode sumber di host Anda dengan penampung. Dalam produksi, ini dapat digunakan untuk memasang hal-hal seperti informasi DNS host (ditemukan di /etc/resolv.conf) atau rahasia ke dalam penampung. Sebaliknya, Anda juga dapat menggunakan teknik ini untuk menulis log penampung ke dalam folder tertentu di host. Keduanya $host_pathdan $container_pathharus jalur absolut.
  3. docker run -v my_volume:$container_path: Ini membuat volume data dalam penampung Anda di $container_pathdan menamainya my_volume. Ini pada dasarnya sama dengan membuat dan menamai volume menggunakan docker volume create my_volume. Penamaan volume seperti ini berguna untuk volume data kontainer dan volume penyimpanan bersama menggunakan driver penyimpanan multi-host seperti Flocker .

Perhatikan bahwa pendekatan pemasangan folder host sebagai volume data tidak tersedia di Dockerfile. Mengutip dokumentasi buruh pelabuhan ,

Catatan: Ini tidak tersedia dari Dockerfile karena portabilitas dan tujuan berbagi. Karena direktori host, pada dasarnya, bergantung pada host, direktori host yang ditentukan dalam Dockerfile mungkin tidak akan berfungsi pada semua host.

Sekarang jika Anda ingin menyalin file Anda ke kontainer di lingkungan non-pengembangan, Anda dapat menggunakan ADDatau COPYinstruksi di Dockerfile Anda. Ini adalah apa yang biasanya saya gunakan untuk penerapan non-pengembangan.

ivan.sim
sumber
3
Haruskah saya membuat 2 file buruh pelabuhan? Satu untuk pengembangan dan satu untuk penerapan?
Cristian Garcia
Saya kira tidak. Tidak ada yang salah dengan memiliki ADDinstruksi di Dockerfile Anda, karena ini hanya dijalankan oleh docker buildperintah. Ini diperlukan saat orang lain membangun penampung Anda untuk pertama kali, dan saat Anda siap untuk menerapkannya ke lingkungan non-pengembangan lainnya.
ivan.sim
3
Tetapi bukankah akan lebih efisien untuk membuat gambar tanpa file dan menggunakan -vperintah untuk pengembangan, dan meminta file buruh pelabuhan lain membuat gambar yang menyertakan file ADDuntuk penyebaran?
Cristian Garcia
1
Ini adalah pertukaran yang harus Anda putuskan. Pilih apa yang cocok untuk Anda. Berapa lama membangun dengan ADDwaktu itu? Total beberapa detik? Jika Anda memiliki dua file Dockerfile, dan Anda membaginya dengan orang lain (atau menerbitkannya di registri buruh pelabuhan ), mana yang default? Anda akan memiliki beberapa overhead pemeliharaan tambahan untuk memastikan Dockerfile default yang benar sampai ke pengguna yang tepat. Tetapi pada akhirnya, Anda memutuskan mana yang terbaik untuk Anda. Secara pribadi, saya ingin memastikan bahwa hanya ada satu Dockerfile untuk membangun container saya.
ivan.sim
11
Ngomong-ngomong, menurut saya tidak masalah untuk menambahkan terlebih dahulu, lalu menimpa add itu dengan -v untuk pengembangan. Dengan begitu Anda tidak perlu Dockerfiles terpisah.
Attila Szeremi