Docker - bir dosyayı bir görüntüden bir ana bilgisayara nasıl kopyalayabilirim?


120

Sorum, dosyaların konteynerlerden ana bilgisayarlara kopyalanması hakkındaki bu soru ile ilgili ; Bağımlılıkları getiren, kaynaktan bir yapı yapıtını derleyen ve bir yürütülebilir dosyayı çalıştıran bir Dockerfile'ım var. Ayrıca derleme yapıtını da kopyalamak istiyorum (benim durumumda '../ target /' .ziptarafından üretilmiştir sbt dist, ancak bu sorunun aynı zamanda kavanozlar, ikili dosyalar vb. İçin de geçerli olduğunu düşünüyorum.

docker cpgörüntüler değil kaplar üzerinde çalışır; Bir dosya almak için bir kapsayıcı başlatmam gerekiyor mu? Bir komut dosyasında, /bin/basharka planda etkileşimli modda çalışmayı , dosyayı kopyalamayı ve ardından kabı öldürmeyi denedim, ancak bu kludgey gibi görünüyor. Daha iyi bir yol var mı?

Öte yandan, yalnızca bir dosyayı çıkarmak için .tarçalıştırdıktan sonra bir dosyayı açmaktan kaçınmak isterim docker save $IMAGENAME(ancak bu, şu anda en yavaş olsa da en basit seçenek gibi görünüyor).

Docker birimlerini kullanırdım, örneğin:

docker run -v hostdir:out $IMAGENAME /bin/cp/../blah.zip /out

ancak boot2dockerOSX'te çalıştırıyorum ve mac ana bilgisayar dosya sistemime doğrudan nasıl yazacağımı bilmiyorum (okuma-yazma birimleri boot2docker sanal makinemin içine monte ediliyor, bu da blah.zipbir görüntüden ayıklamak için bir komut dosyasını kolayca paylaşamadığım anlamına geliyor. diğerleri. Düşünceler?

Yanıtlar:


172

Bir görüntüden dosya kopyalamak için geçici bir kap oluşturun, dosyayı buradan kopyalayın ve ardından silin:

id=$(docker create image-name)
docker cp $id:path - > local-tar-file
docker rm -v $id

create
Docker'ın

2
@ThorSummoner docker create, docker 1.3'te tanıtıldı, blog.docker.com/2014/10/…
Igor Bukanov

1
Bunun neden doğru cevap olarak seçilmediğini bilmiyorum.
CentAu

1
Kesinlikle doğru cevap !!! Kabın içindeki hiçbir şeye güvenmiyor ... Golang kazı kazanları için mümkün olan tek yol bu!
Marcello de Sales

2
stdout'a kopyalayıp yerel bir dosyaya yönlendirmek için herhangi bir neden var mı? Bunu yaptığımda, dosyanın içeriğinden önce ve sonra bir sürü kontrol karakteri döktü. doğrudan docker cp $id:path > local-tar-filemükemmel çalıştığı gibi çalıştırmak .
Yonatan

63

Maalesef dosyaları doğrudan Docker görüntülerinden kopyalamanın bir yolu yok gibi görünüyor. Önce bir konteyner oluşturmanız ve ardından dosyayı konteynerden kopyalamanız gerekir.

Ancak, görüntünüz bir catkomut içeriyorsa (ve çoğu durumda işe yarar ), bunu tek bir komutla yapabilirsiniz:

docker run --rm --entrypoint cat yourimage  /path/to/file > path/to/destination

Görüntünüz içermiyorsa cat, basitçe bir kap oluşturun ve docker cpIgor'un cevabında önerildiği gibi komutu kullanın .


1
Harika çözüm. Başlatıldıktan bir saniye sonra çöktüğü için kapsayıcıma erişemedim, ancak içinde bir dosya tutması gerekiyordu. Bu mükemmel çalıştı.
Mirodinho

23

Çok daha hızlı bir seçenek, dosyayı çalışan kapsayıcıdan takılı bir birime kopyalamaktır:

docker run -v $PWD:/opt/mount --rm --entrypoint cp image:version /data/libraries.tgz /opt/mount/libraries.tgz

gerçek 0a0.446s

** VS **

docker run --rm --entrypoint cat image:version /data/libraries.tgz > libraries.tgz

gerçek 0d9.014'ler


Bunun muhtemelen, ikinci örnekte dosyanın baytlarını kopyalamaya kıyasla, ilk örnekte dosyanın tembel / yüzeysel bir kopyasını (yazma üzerine kopyalamayı düşünün) gerçekleştiren temel dosya sistemi ile daha fazla ilgisi vardır. Yararlı bir testi görmek için olurdu cat a >bvs cp a bburada gösterildiği gibi benzer zamanlamaları var. Ayrıca, kaynak yolu ve hedef yolu farklı dosya sistemlerinde bulunuyorsa, her iki örnek de bayt için tam bir kopyaya yol açacaktır.
KevinOrr

14

Ana yorum zaten kedinin nasıl kullanılacağını gösterdi . Katranı da benzer şekilde kullanabilirsiniz:

docker run yourimage tar -c -C /my/directory subfolder | tar x

1
Bu cevap, orijinal sorunun sorduğu gibi dosyalar yerine dizinleri kopyalamaktır. Bununla birlikte, +1 çünkü dosyalarla da çalışır ve ek bir özellikle gelir: izin ve sahip koruması. Harika!
caligari

5
Aslında, kullanıyorumdocker run --rm --entrypoint tar _image_ cC _img_directory_ . | tar xvC _host_directory_
kaligari

7
docker cp $(docker create registry.example.com/ansible-base:latest):/home/ansible/.ssh/id_rsa ./hacked_ssh_key

saf docker işlevselliğine dayalı tek hatlı bir çözüm sağlamak istedi (bash gerekmez)

düzenleme: kapsayıcı bu çözümde çalıştırılmak zorunda bile değil


1

Bu soruna başka bir (kısa) cevap:

docker run -v $PWD:/opt/mount --rm -ti image:version bash -c "cp /source/file /opt/mount/"

Güncelleme - @Elytscha Smith tarafından belirtildiği gibi, bu yalnızca görüntünüz yerleşik bash varsa çalışır


1
* bash çalıştırılabilir alpin içeren resimler için başka bir kısa cevap varsayılan olarak değildir ve sıfırdan oluşturulmuş resimler de aynı değildir
Elytscha Smith

0

MacOS'ta boot2docker kullanıyorum. "Docker cp" tabanlı betiklerin taşınabilir olduğunu garanti edebilirim. Herhangi bir komut boot2docker içinde aktarıldığı için ancak daha sonra ikili akış, Mac'inizde çalışan docker komut satırı istemcisine geri aktarılır. Bu nedenle docker istemcisinden yazma işlemleri sunucu içinde yürütülür ve çalıştırılan istemci örneğine geri yazılır!

Sağladığım herhangi bir docker container ile docker birimleri için bir yedekleme betiği paylaşıyorum ve yedekleme betiklerim boot2docker ile hem linux hem de MacOS üzerinde test ediliyor. Yedeklemeler platformlar arasında kolaylıkla değiştirilebilir. Temel olarak komut dosyamın içinde aşağıdaki komutu çalıştırıyorum:

docker run --name=bckp_for_volume --rm --volumes-from jenkins_jenkins_1 -v /Users/github/jenkins/backups:/backup busybox tar cf /backup/JenkinsBackup-2015-07-09-14-26-15.tar /jenkins

Yeni bir busybox kapsayıcısı çalıştırır ve jenkins kapsayıcımın hacmini jenkins_jenkins_1 adıyla bağlar. Tüm birim dosya yedeklerine / JenkinsBackup-2015-07-09-14-26-15.tar'a yazılır.

Yedekleme veya geri yükleme betiğinde herhangi bir ayarlama yapmadan arşivleri linux kapsayıcısı ile mac kapsayıcım arasında zaten taşıdım. İstediğiniz buysa, tüm komut dosyasını burada bir öğretici bulabilirsiniz: blacklabelops / jenkins


0

Sen olabilir bağlayan konteyner üzerinde bir yola ana bilgisayardaki yerel bir yolu ve sonra cpda komut sonunda bu yola istenen dosya (s).

$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

O zaman daha sonra kopyalamaya gerek yoktur.

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.