Kısaca: Hayır, senin VOLUME
talimatınız doğru değil.
Dockerfile, VOLUME
konteyner tarafı yolları verilen bir veya daha fazla birimi belirtir. Ancak görüntü yazarının bir ana bilgisayar yolu belirlemesine izin vermez. Ana bilgisayar tarafında, birimler Docker kökü içinde çok uzun bir ID benzeri adla oluşturulur. Benim makinemde bu/var/lib/docker/volumes
.
Not: Otomatik olarak oluşturulmuş ad çok uzun olduğundan ve insan açısından bir anlam ifade etmediğinden, bu ciltlere genellikle "adsız" veya "anonim" denir.
Bir '.' Kullanan örneğiniz Noktayı birinci veya ikinci argüman yapsam da karakter makinemde çalışmayacak bile. Bu hata mesajını alıyorum:
docker: daemon'dan gelen hata yanıtı: oci çalışma zamanı hatası: container_linux.go: 265: "process_linux.go: 368: kapsayıcı başlatmaya neden oldu \" open / dev / ptmx: böyle bir dosya veya dizin yok \ "".
Bu noktaya kadar söylenenlerin muhtemelen anlamaya çalışan biri için çok değerli olmadığını VOLUME
ve başarmaya çalıştığınız şey -v
için kesinlikle bir çözüm sağlamadığını biliyorum. Bu nedenle, umarım aşağıdaki örnekler bu konulara biraz daha ışık tutacaktır.
Minitutorial: Hacimleri belirleme
Bu Dockerfile verildiğinde:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(Bu mini öğreticinin sonucu için, şunu belirtmemiz fark etmez vol1 vol2
veya/vol1 /vol2
- nedenini sorma)
İnşa et:
docker build -t my-openjdk
Çalıştırmak:
docker run --rm -it my-openjdk
Kabın ls
içinde, komut satırında çalıştırın ve iki dizin olduğunu fark edeceksiniz; /vol1
ve/vol2
.
Kapsayıcıyı çalıştırmak ayrıca ana bilgisayar tarafında iki dizin veya "birimler" oluşturur.
Konteyner çalıştıran sahip iken, yürütme docker volume ls
üzerindeki ana makinede ve böyle bir şey göreceksiniz (ben kısalık için üç noktalı adının orta kısmını yerini almıştır):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
Geri içinde konteyner , yürütme touch /vol1/weird-ass-file
(söz konusu yerde Boş bir dosya oluşturur).
Bu dosya artık ana makinede, adsız ciltlerden biri olan lol'de mevcuttur. İlk listelenen birimi denediğim için iki denememi aldı, ancak sonunda ana makinede şu komutu kullanarak dosyamı listelenen ikinci ciltte buldum:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
Benzer şekilde, bu dosyayı ana bilgisayardan silmeyi deneyebilirsiniz ve bu dosya da kapsayıcıda silinecektir.
Not: _data
Klasöre ayrıca "bağlama noktası" da denir.
Kapsayıcıdan çıkın ve ana bilgisayardaki birimleri listeleyin. Gittiler. --rm
Konteyneri çalıştırırken bayrağı kullandık ve bu seçenek sadece çıkışta konteyneri değil aynı zamanda hacimleri de etkili bir şekilde siler.
Yeni bir kap çalıştırın, ancak şunu kullanarak bir birim belirtin -v
:
docker run --rm -it -v /vol3 my-openjdk
Bu , üçüncü bir cilt ekler ve tüm sistem üç adsız cilde sahip olur. Komut sadece biz belirtmiş olsaydık çökebilirdi -v vol3
. Argüman , konteyner içinde mutlak bir yol olmalıdır . Ana bilgisayar tarafında, yeni üçüncü cilt anonimdir ve diğer iki cilt ile birlikte/var/lib/docker/volumes/
.
Daha önce, Dockerfile
çalışma zamanı sırasında ana bilgisayardan konteynere dosya getirmeye çalışırken bizim için sorun teşkil eden bir ana bilgisayar yoluna eşlenemediği belirtilmişti. Farklı bir -v
sözdizimi bu sorunu çözer.
Proje dizinimde, konteynerin içinde ./src
senkronize etmek istediğim bir alt klasörüm olduğunu düşünün /src
. Bu komut hile yapar:
docker run -it -v $(pwd)/src:/src my-openjdk
:
Karakterin her iki tarafı da mutlak bir yol bekliyor. Sol taraf, ana makinede mutlak bir yoldur, sağ taraf ise kabın içinde mutlak bir yoldur. pwd
"geçerli / çalışma dizini yazdır" komutudur. Komutu devreye sokmak$()
parantez içindeki komutu alır, bir alt kabukta çalıştırır ve proje dizinimize mutlak yolu geri verir.
Hepsini bir araya getirerek, ./src/Hello.java
ana makinedeki proje klasörümüzde aşağıdaki içeriğe sahip olduğumuzu varsayalım :
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
Bu Dockerfile'ı oluşturuyoruz:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
Bu komutu çalıştırıyoruz:
docker run -v $(pwd)/src:/src my-openjdk
Bu, "Merhaba, Dünya!" Yazdırır.
En iyi yanı, .java dosyasını ikinci bir çalıştırmada başka bir çıktı için yeni bir mesajla değiştirmekte tamamen özgür olmamızdır - görüntüyü yeniden oluşturmak zorunda kalmadan =)
Son açıklamalar
Docker'da oldukça yeniyim ve yukarıda bahsedilen "eğitim" 3 günlük bir komut satırı hackathonundan topladığım bilgileri yansıtıyor. İfadelerimi destekleyen net İngilizce benzeri belgelere bağlantı sağlayamadığım için neredeyse utanıyorum, ancak dürüst olmak gerekirse bunun kişisel çaba değil belge eksikliğinden kaynaklandığını düşünüyorum. Örneklerin "Windows 10 -> Vagrant 2.0.0 -> Docker 17.09.0-ce" olan mevcut kurulumumu kullanarak reklamı yapılan şekilde çalıştığını biliyorum.
Öğretici, "kapsayıcının Dockerfile içindeki yolunu nasıl belirtiriz ve çalıştır komutunun yalnızca ana bilgisayar yolunu belirtmesine izin veririz" sorununu çözmez. Bir yolu olabilir, sadece bulamadım.
Son olarak, VOLUME
Dockerfile'da belirtmenin sadece alışılmadık bir şey değil, muhtemelen asla kullanılmaması gereken en iyi uygulama olduğuna dair içimden bir his var VOLUME
. İki nedenden dolayı. Önceden belirlemiş olmamızın ilk nedeni: Ana bilgisayar yolunu belirleyemiyoruz - bu iyi bir şey çünkü Dockerfiles, bir ana makinenin özelliklerine çok agnostik olmalıdır. Ancak ikinci neden, insanların --rm
konteyneri çalıştırırken bu seçeneği kullanmayı unutabilmeleridir . Kişi kabı çıkarmayı hatırlayabilir ancak hacmi çıkarmayı unutabilir. Ayrıca, en iyi insan belleğiyle bile, tüm anonim ciltlerden hangilerinin kaldırılmasının güvenli olduğunu bulmak göz korkutucu bir görev olabilir.