Mevcut bir Docker kapsayıcısına nasıl birim ekleyebilirim?


298

Ben sadece Ubuntu Docker yükleyerek ve yaparak yarattığım bir Docker konteyner var:

sudo docker run -i -t ubuntu /bin/bash

Hemen Java ve diğer bazı araçları yüklemeye başladım, onunla biraz zaman geçirdim ve konteyneri

exit

Sonra bir hacim eklemek istedim ve bunun düşündüğüm kadar basit olmadığını fark ettim. Eğer kullanırsam sudo docker -v /somedir run ...o zaman yeni bir kap ile bitiririm, bu yüzden Java'yı yükledim ve daha önce yaptığım şeyi sadece monte edilmiş bir hacme sahip bir kaba ulaşmak için yapardım.

Ana bilgisayardan bir klasör takmayla ilgili tüm belgeler, bir birimin takılmasının bir kap oluştururken yapılabilecek bir şey olduğu anlamına gelir. Bu nedenle, yeni bir kabı sıfırdan yeniden yapılandırmaktan kaçınmak zorunda olduğum tek seçenek, mevcut kabı bir depoya koymak ve hacmi monte ederken yeni bir kabın temeli olarak kullanmaktır.

Gerçekten bu, mevcut bir kapsayıcıya bir birim eklemenin tek yolu mu?


1
Kapsayıcılardan sonra, bunlar Programcıların ayrılmaz bir parçası haline geldi ve bu nedenle bu tür sorular burada daha sık yayınlanıyor. Burada dockeretiketi kullanarak gönderilen sorular , bu iki siteden çok daha fazla olan 34k + 'dır stackoverflow.com/questions/tagged/docker
MA Hossain Tonu

Yanıtlar:


395

Mevcut kapsayıcınızı (kapsayıcı değişikliklerinden yeni bir resim oluşturmak) uygulayabilir ve daha sonra yeni bağlarınızla çalıştırabilirsiniz.

Misal:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash

Her şey yolundaysa, eski kabınızı durdurun ve bu yenisini kullanın.

Bu kadar :)


22
Ve herhangi bir nedenle eski adı almak için yeni kapsayıcıya ihtiyacınız varsa, eskisini kaldırdıktan sonra docker yeniden adlandırmasını kullanın .
Dirk

10
Sadece işaret etmek istediği Sözünü nerede Yukarıdaki newnameofcontainerbu muhtemelen adlandırılması gerektiği new_image_name- çünkü docker commityeni oluşturur görüntü sisteminizde. Daha sonra, aşağıda, yeni bir kapsayıcı çalıştırmak istediğiniz görüntünündocker run adını kullanırsınız . Yukarıdakiler işe yarıyor, ancak sadece yukarıdaki yer tutucu newnameofcontainer'ın aslında yeni bir görüntünün adı olduğunu açıklamak istiyordu. Teşekkürler! harika cevap. oh, kullanarak ilk docker kesinleştirme komutundan yeni oluşturulan görüntüyü görebilirsinizdocker image ls
FireDragon

3
Aslında, bir görüntüden başlamak istiyorsanız yeni bir kapsayıcıya ihtiyacınız yoktur. Sadece docker run -v /srv/a:/tmp ubuntu:14.04iyi.
YongHao Hu

Zaten tüm dosyalarla çalışan bir kapsayıcı var. Yukarıdaki yöntem yeni bir kapsayıcı oluşturuyorsa, her şeyi bir kez daha inşa edemiyorum. Bunu önlemek ve yeni kap veya görüntü oluşturmak zorunda kalmadan monte etmenin bir yolu var mı?
dhinar

Bu işlem, eski kapsayıcı eşlemelerini eski kapsayıcıdan koruyacak mı yoksa yeni kapsayıcıyla da yeniden bildirmeli miyim?
thebeancounter

80

Çalışan kapsayıcıya hacim eklemenin bir yolu yok, ancak bu hedefe ulaşmak için aşağıdaki komutları kullanabilirsiniz:

Bir kapsayıcı ile yerel dosya sistemi arasında dosya / klasör kopyalama: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Referans için bakınız:

https://docs.docker.com/engine/reference/commandline/cp/


47
Bir birimin montajı ile bir konteynere ve konteynırdan dosya kopyalanması arasında büyük bir fark vardır ...
Jules

31
Her neyse bana yardımcı oldu. 'Docker cp' komutunu bilmiyordum ve tam olarak bunu başarmaya çalışıyordum - dosyaları çalıştıran kaptan ana bilgisayara kopyalayın.
Ivan

3
bir bağ değil, ancak dosyaları konteyner ve yerel ana bilgisayar arasında geri ve köpük getirmek için kullanışlıdır.
linehrr

Bu, konteyner içeriklerinin yerel olarak çoğaltılması sorununu çözse de, bu bir birimin monte edilmesine eşdeğer değildir ve alternatif olarak düşünülmemelidir. Yani, çoğaltma kullanıcı tarafından yönetilmelidir ve veriler artık iki yerde bulunmaktadır.
Sebastian Gaweda

1
Neden bu kadar çok oy aldığını anlamıyorum, sorulan soru için bu çok yanlış bir cevap.
João Matos

33

/home/<user-name>Ana bilgisayarımın /mntklasörünü var olan (çalışmayan) kabın klasörüne başarıyla bağladım . Bunu aşağıdaki şekilde yapabilirsiniz:

  1. Durdurulan kapsayıcıya karşılık gelen ve adresinde /var/lib/docker/containers/99d...1fb/config.v2.jsonbulunabilir config.json(docker'ın eski sürümleri için olabilir) yapılandırma dosyasını açın .

  2. Bul MountPointsbenim durumumda boştu ki, bölüm: "MountPoints":{}. Sonra içeriği böyle bir şeyle değiştirin (uygun ayarları başka bir kapsayıcıdan uygun ayarlarla kopyalayabilirsiniz):

"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

veya aynı (biçimlendirilmiş):

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
  1. Liman hizmetini yeniden başlatın: service docker restart

Bu benim için Ubuntu 18.04.1 ve Docker 18.09.0 ile çalışıyor


3
Cevap için teşekkürler. Adım 3 çok önemlidir. Ayrıca, yazmayı yapmadan önce docker kapsayıcısını durdurmanın daha iyi olduğunu da ekleyeceğim.
buzypi

7
Bu, mevcut konteyneri tamamen koruduğu için en iyi cevaptır. Yaptığım bu: 1. Liman işçisi motorunu durdurun: systemctl stop docker.service2. Düzenleme config.v2.json: vim <(jq . /var/lib/docker/containers/<container-ID>/config.v2.json)3. Güncellemeleri bir dosyaya kaydedin: :w config.v2.json4. Çıkış vim: :q!5. Mevcut dosyayı güncelleyin: jq -c . config.v2.json > /var/lib/docker/containers/<container-ID>/config.v2.json6. Liman işçisi motorunu başlatın: systemctl start docker.service7. Gerekirse konteyneri başlatın : docker start <container-name/ID>8. Enjoy :-)
Android Kontrolü

2
Bir anahtar aşama, bir service docker restart. Daha docker restart <container>sonra yeni yapılandırma alınmadı denedim ve eski yapılandırma tarafından üzerine yazılıyor.
KFL

1
Ayrıca jqgüzel JSON yazdırmaya yardımcı olacak, bu yüzden mroe insan düzenlenebilir:cat config.v2.json | jq . > config.json
KFL

14

Jérôme Petazzoni , çalışırken bir kaba nasıl bir birim ekleyeceğine dair oldukça ilginç bir blog yayınına sahiptir . Bu, Docker'a kutudan çıkmış bir şey değil, ancak başarılması mümkün.

Ayrıca işaret ettiği gibi

Bu, blok cihazlara dayalı olmayan dosya sistemlerinde çalışmaz.

Yalnızca / proc / mounts, blok cihaz düğümünü doğru bir şekilde listelerse (yukarıda gördüğümüz gibi, mutlaka doğru değildir) çalışır.

Ayrıca, bunu yalnızca yerel ortamımda test ettim; Bir bulut örneğini ya da bunun gibi bir şeyi bile denemedim

YMMV


8

Maalesef bir birimi bağlama seçeneği yalnızca runkomutta bulunur.

docker run --help

-v, --volume list Bind mount a volume (default [])

Bununla birlikte, bu sorunu gidermek için bir yol vardır, böylece kapsayıcıda önceden ayarladığınız uygulamaları yeniden yüklemek zorunda kalmazsınız.

  1. Konteynerinizi dışa aktarın docker container export -o ./myimage.docker mycontainer
  2. Görüntü olarak içe aktar docker import ./myimage.docker myimage
  3. Sonra docker run -i -t -v /somedir --name mycontainer myimage /bin/bash

1
FYI - docker container1.11.2'de geçerli bir komut değildir (bu yazıdan itibaren Synology tarafından desteklenen en son sürümdür). Ne zaman eklendiğini söyleyen hiçbir belge bulamıyorum. Bu durumda ilk komut docker export -o ./myimage.docker mycontainer.
Chris R. Donnelly

2

Bu sorunu uzun süre aramak zorunda kaldıktan sonra Docker Windows kapsayıcılarını kullanmak için bir not!

Condiditions:

  • Windows 10
  • Docker Desktop (en son sürüm)
  • microsoft / mssql-server-windows-developer için Docker Windows Container'ı kullanma

Sorun:

  • Windows kapsayıcıya bir ana bilgisayar sözlüğü eklemek istedim.

Kısmen burada açıklanan çözüm:

  • liman işçisi konteyneri oluştur

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • kaptaki komut kabuğuna git

docker exec -it <CONTAINERID> cmd.exe

  • DIR oluştur

mkdir DirForMount

  • konteyneri durdur

docker container stop <CONTAINERID>

  • konteynır yapmak

docker commit <CONTAINERID> <NEWIMAGENAME>

  • eski kapsayıcıyı sil

docker container rm <CONTAINERID>

  • yeni görüntü ve hacim montajı ile yeni bir kap oluşturun

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

Bundan sonra docker windows kapsayıcılar bu sorunu çözdü.


-3

En iyi yol, yerel dosya sisteminizdeki bir dizindeki tüm dosya ve klasörleri şu şekilde kopyalamaktır: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATHkonteyner DEST_PATHüzerinde localhost üzerinde

Daha sonra docker-compose downaynı birime bir birim ekleyin DEST_PATHve kullanarak Docker kapsayıcılarını çalıştırın.docker-compose up -d

Aşağıdakileri takip ederek hacim ekleyin docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH

Yukarıda başka, daha iyi seçenekler var.
19R

Aslında, yukarıda daha iyi seçenekler var ve dosyaları kopyalamak onları monte etmiyor. Ayrıca, docker-compose seçeneği için verilen "volumes" tanımı ise tam tersi: volumes: - HOST_PATH: CONTAINER_PATH
Guillaume S.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.