Singkatnya: Tidak, VOLUME
instruksi Anda tidak benar.
Dockerfile's VOLUME
menentukan satu atau lebih volume yang diberikan jalur sisi wadah. Tapi itu tidak memungkinkan penulis gambar untuk menentukan jalur host. Di sisi host, volume dibuat dengan nama seperti ID yang sangat panjang di dalam akar Docker. Di mesin saya ini /var/lib/docker/volumes
.
Catatan: Karena nama yang di-autogenerasi sangat panjang dan tidak masuk akal dari sudut pandang manusia, volume ini sering disebut sebagai "tanpa nama" atau "anonim".
Contoh Anda yang menggunakan '.' karakter bahkan tidak akan berjalan di mesin saya, tidak masalah jika saya membuat titik argumen pertama atau kedua. Saya mendapatkan pesan kesalahan ini:
buruh pelabuhan: Respons kesalahan dari daemon: kesalahan runtime oci: container_linux.go: 265: memulai proses wadah disebabkan "process_linux.go: 368: init kontainer disebabkan \" open / dev / ptmx: tidak ada file atau direktori seperti itu \ "".
Saya tahu bahwa apa yang telah dikatakan sampai saat ini mungkin tidak terlalu berharga bagi seseorang yang mencoba memahami VOLUME
dan -v
dan itu tentu saja tidak memberikan solusi untuk apa yang Anda coba capai. Jadi, mudah-mudahan, contoh-contoh berikut akan menjelaskan lebih lanjut tentang masalah ini.
Minitutorial: Menentukan volume
Diberikan Dockerfile ini:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(Untuk hasil minitutorial ini, tidak ada bedanya jika kita menentukan vol1 vol2
atau/vol1 /vol2
- jangan tanya kenapa)
Bangun itu:
docker build -t my-openjdk
Lari:
docker run --rm -it my-openjdk
Di dalam wadah, jalankan ls
di baris perintah dan Anda akan melihat dua direktori ada; /vol1
dan/vol2
.
Menjalankan wadah juga menciptakan dua direktori, atau "volume", di sisi host.
Sambil menjalankan wadah, jalankan docker volume ls
di mesin host dan Anda akan melihat sesuatu seperti ini (saya telah mengganti bagian tengah nama dengan tiga titik untuk singkatnya):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
Kembali ke dalam wadah , jalankan touch /vol1/weird-ass-file
(buat file kosong di lokasi tersebut).
File ini sekarang tersedia di mesin host, di salah satu volume lol yang tidak disebutkan namanya. Butuh saya dua kali mencoba karena saya pertama kali mencoba volume yang tercantum pertama, tetapi akhirnya saya menemukan file saya di volume yang tercantum kedua, menggunakan perintah ini pada mesin host:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
Demikian pula, Anda dapat mencoba menghapus file ini pada host dan itu akan dihapus dalam wadah juga.
Catatan: _data
Folder ini juga disebut sebagai "titik mount".
Keluar dari wadah dan daftarkan volume pada host. Mereka sudah pergi. Kami menggunakan --rm
bendera saat menjalankan wadah dan opsi ini secara efektif menghapus tidak hanya wadah saat keluar, tetapi juga volume.
Jalankan wadah baru, tetapi tentukan volume menggunakan -v
:
docker run --rm -it -v /vol3 my-openjdk
Ini menambahkan volume ketiga dan seluruh sistem akhirnya memiliki tiga volume yang tidak disebutkan namanya. Perintahnya akan crash jika kita tentukan saja -v vol3
. Argumen harus menjadi jalur absolut di dalam wadah. Di sisi host, volume ketiga yang baru bersifat anonim dan berada bersama dengan dua volume lainnya di /var/lib/docker/volumes/
.
Telah dinyatakan sebelumnya bahwa Dockerfile
tidak dapat memetakan ke jalur host yang semacam menimbulkan masalah bagi kami ketika mencoba untuk membawa file dari host ke wadah selama runtime. -v
Sintaks yang berbeda memecahkan masalah ini.
Bayangkan saya memiliki subfolder di direktori proyek ./src
saya yang ingin saya sinkronkan ke /src
dalam wadah. Perintah ini melakukan trik:
docker run -it -v $(pwd)/src:/src my-openjdk
Kedua sisi :
karakter mengharapkan jalur absolut. Sisi kiri menjadi jalur absolut pada mesin host, sisi kanan menjadi jalur absolut di dalam wadah. pwd
adalah perintah yang "mencetak direktori saat ini / bekerja". Memasukkan perintah $()
mengambil perintah dalam tanda kurung, menjalankannya dalam subkulit dan mengembalikan jalur absolut ke direktori proyek kami.
Menyatukan semuanya, asumsikan ada ./src/Hello.java
di folder proyek kami di mesin host dengan konten berikut:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
Kami membangun Dockerfile ini:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
Kami menjalankan perintah ini:
docker run -v $(pwd)/src:/src my-openjdk
Ini mencetak "Halo, Dunia!".
Bagian terbaiknya adalah kita benar-benar bebas untuk memodifikasi file .java dengan pesan baru untuk output lain pada proses kedua - tanpa harus membangun kembali gambar =)
Komentar akhir
Saya cukup baru untuk Docker, dan "tutorial" yang disebutkan di atas mencerminkan informasi yang saya kumpulkan dari hackathon baris perintah 3 hari. Saya hampir malu saya belum dapat memberikan tautan ke dokumentasi yang jelas seperti bahasa Inggris yang mendukung pernyataan saya, tetapi saya jujur berpikir ini disebabkan oleh kurangnya dokumentasi dan bukan upaya pribadi. Saya tahu contoh berfungsi seperti yang diiklankan menggunakan pengaturan saya saat ini yaitu "Windows 10 -> Vagrant 2.0.0 -> Docker 17.09.0-ce".
Tutorial tidak menyelesaikan masalah "bagaimana kita menentukan jalur wadah di Dockerfile dan biarkan perintah jalankan hanya menentukan jalur host". Mungkin ada cara, saya belum menemukannya.
Akhirnya, saya punya firasat bahwa menentukan VOLUME
di Dockerfile bukan hanya tidak biasa, tetapi mungkin merupakan praktik terbaik untuk tidak pernah menggunakan VOLUME
. Karena dua alasan. Alasan pertama yang telah kami identifikasi: Kami tidak dapat menentukan jalur host - yang merupakan hal yang baik karena Dockerfiles harus sangat agnostik dengan spesifikasi mesin host. Tapi alasan kedua adalah orang mungkin lupa menggunakan --rm
opsi saat menjalankan wadah. Orang mungkin ingat untuk menghapus wadah tetapi lupa untuk menghapus volume. Plus, bahkan dengan ingatan manusia terbaik, mungkin merupakan tugas yang menakutkan untuk mencari tahu mana dari semua volume anonim yang aman untuk dihapus.