Docker kapsayıcısından ana bilgisayara dosya kopyalama


1708

Docker'ı bir Sürekli Entegrasyon (CI) sunucusunda bağımlılıklarımı oluşturmak için kullanmayı düşünüyorum, böylece aracıların tüm çalışma zamanlarını ve kitaplıklarını yüklemem gerekmiyor.

Bunu başarmak için, konteynerin içine inşa edilmiş yapı yapılarını tekrar ana bilgisayara kopyalamam gerekir. Mümkün mü?


hacker yöntemimi burada
beğenebilirsiniz

1
Cevapların altındaki docker kaptanından doğru ve gerçek cevap.
burtsevyg

Yanıtlar:


2946

Bir dosyayı kapsayıcıdan ana bilgisayara kopyalamak için şu komutu kullanabilirsiniz:

docker cp <containerId>:/file/path/within/container /host/path/target

İşte bir örnek:

$ sudo docker cp goofy_roentgen:/out_read.jpg .

İşte goofy_roentgen aşağıdaki komuttan aldığım kapsayıcı adı:

$ sudo docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                            NAMES
1b4ad9311e93        bamos/openface      "/bin/bash"         33 minutes ago      Up 33 minutes       0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp   goofy_roentgen

Kapsayıcı Kimliğini de (bir kısmını) kullanabilirsiniz . Aşağıdaki komut ilk komutla eşdeğerdir

$ sudo docker cp 1b4a:/out_read.jpg .

42
Burada sadece bir geçici Linux ortamı için liman işçisi olarak kullanıyorsanız, en son konteyner ulaşmak için kullanışlı bir yoludur: docker ps -alq.
Josh Habdas

37
bu cp komutu dizin ağaçlarını kopyalamak için olduğu gibi çalışır (sadece tek bir dosya değil).
ecoe

88
Eğer liman işçisi daha yeni sürümlerinde olabilir çift yönlü kopyalama (konteyner veya ana bilgisayara kaba ana bilgisayar) iledocker cp ...
Freedom_Ben

9
docker cp -LSembolleri kopyalamam gerekiyordu
Harrison Powers

24
Not: kap cp komutunu kullanmak için çalışıyor olması gerekmez. Konteynırınız sürekli çökerse kullanışlı.
Martlark

219

Kullanmanıza gerek yok docker run.

İle yapabilirsiniz docker create.

Gönderen docs :

docker createKomut Belirtilen resmin üzerine yazılabilir bir konteyner tabakası oluşturur ve belirli bir komutu çalıştırmak için hazırlar. Kapsayıcı kimliği daha sonra üzerine yazdırılır STDOUT. Bu, docker run -dkabın hiç başlatılmaması dışındakine benzer .

Böylece şunları yapabilirsiniz:

docker create -ti --name dummy IMAGE_NAME bash
docker cp dummy:/path/to/file /dest/to/file
docker rm -f dummy

Burada, kabı asla başlatmazsınız. Bu bana çok faydalı geldi.


19
Bunun için daha fazla oy gerekiyor. Sadece bir kapta bir şey inşa etmeniz ve çıktıları kopyalamanız gerektiğinde idealdir.
Honza Kalfus

4
@HonzaKalfus Bunun daha yüksek olması gerektiğine katılıyorum. Ben de tam olarak bundan sonraydım. Bunu, bilinen bir ortam (belirli bir sürümde amazon linux) kullanarak bazı ikili dosyalar oluşturabilmem için kullandım. tamamen liman işçisini inşa eden ve sonuçtaki ikili dosyayı çıkaran bir kabuk betiği yapabildi! Mükemmel.
Mark

1
Is -tigerekli ve bashzorunlu?
jII

@jII, ben yaptım çünkü daha sonra üzerinde docker çalıştırıyorum. Basit durumlarda, gerekli değildir, ancak burada da zarar vermez.
Ishan Bhatt

Joker karakter kullanmak bir şekilde mümkün mü? Yani ... Kopyalamam gereken dosyanın tam adını bilmiyorum çünkü üzerinde bir sürüm numarası var.
juzzlin

87

Bir "birim" takın ve eserleri buraya kopyalayın:

mkdir artifacts
docker run -i -v ${PWD}/artifacts:/artifacts ubuntu:14.04 sh << COMMANDS
# ... build software here ...
cp <artifact> /artifacts
# ... copy more artifacts into `/artifacts` ...
COMMANDS

Derleme tamamlandığında ve kap artık çalışmadığında, yapıdaki yapıları artifactsana bilgisayardaki dizine zaten kopyalamıştır .

Düzenle

Uyarı: Bunu yaptığınızda, docker kullanıcısının kullanıcı kimliğiyle geçerli çalışan kullanıcının kullanıcı kimliğiyle eşleşen sorunlarla karşılaşabilirsiniz. Yani içindeki dosyalar /artifacts, docker kapsayıcısında kullanılan kullanıcının UID'si ile kullanıcının sahip olduğu olarak gösterilir. Bunun bir yolu, arayan kullanıcının UID'sini kullanmak olabilir:

docker run -i -v ${PWD}:/working_dir -w /working_dir -u $(id -u) \
    ubuntu:14.04 sh << COMMANDS
# Since $(id -u) owns /working_dir, you should be okay running commands here
# and having them work. Then copy stuff into /working_dir/artifacts .
COMMANDS

7
Aslında chownana makinedeki kullanıcı kimliği ve grup kimliğini eşleştirmek için komutu kullanabilirsiniz .
Dimchansky

@Frondor Cilt yapılandırma referansına bakın docs.docker.com/compose/compose-file/…
djhaskin987

Zaten yaptı ve bu işe yaramayacak. Kapsayıcı dosyaları birime ilk kez kopyaladıktan sonra, bir dahaki sefere, birim artık boş olmaz ve dosyalar daha yenileri tarafından geçersiz kılınmaz. Kapsayıcı ana bilgisayar dosyalarına öncelik veriyor (kapsayıcı görüntüsünü ilk kez taktığınızda kopyalananlar).
Frondor

kendi SO sorusu olabilecek bir şey gibi geliyor @Frondor
djhaskin987

1
Sana bir bira arkadaşı alıyorum! Teşekkürler!
Dimitar Vukman

27

Bir birim bağlayın, eserleri kopyalayın, sahip kimliğini ve grup kimliğini ayarlayın:

mkdir artifacts
docker run -i --rm -v ${PWD}/artifacts:/mnt/artifacts centos:6 /bin/bash << COMMANDS
ls -la > /mnt/artifacts/ls.txt
echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -u)
chown -R $(id -u):$(id -u) /mnt/artifacts
COMMANDS

24

TLDR;

$ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
chown $(id -u):$(id -g) my-artifact.tar.xz
cp -a my-artifact.tar.xz /host-volume
EOF

Açıklama

docker runbir ana bilgisayar hacmi, chownartefakt, cpana bilgisayar hacminin artefaktı ile:

$ docker build -t my-image - <<EOF
> FROM busybox
> WORKDIR /workdir
> RUN touch foo.txt bar.txt qux.txt
> EOF
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> 00f017a8c2a6
Step 2/3 : WORKDIR /workdir
 ---> Using cache
 ---> 36151d97f2c9
Step 3/3 : RUN touch foo.txt bar.txt qux.txt
 ---> Running in a657ed4f5cab
 ---> 4dd197569e44
Removing intermediate container a657ed4f5cab
Successfully built 4dd197569e44

$ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
chown -v $(id -u):$(id -g) *.txt
cp -va *.txt /host-volume
EOF
changed ownership of '/host-volume/bar.txt' to 10335:11111
changed ownership of '/host-volume/qux.txt' to 10335:11111
changed ownership of '/host-volume/foo.txt' to 10335:11111
'bar.txt' -> '/host-volume/bar.txt'
'foo.txt' -> '/host-volume/foo.txt'
'qux.txt' -> '/host-volume/qux.txt'

$ ls -n
total 0
-rw-r--r-- 1 10335 11111 0 May  7 18:22 bar.txt
-rw-r--r-- 1 10335 11111 0 May  7 18:22 foo.txt
-rw-r--r-- 1 10335 11111 0 May  7 18:22 qux.txt

Bu hile işe yarar çünkü heredocchown içindeki çağırma , çalışan kabın dışından değerleri alır ; yani, docker ana bilgisayarı.$(id -u):$(id -g)

Avantajları:

  • yapmak zorunda değilsin docker container run --nameya da docker container create --nameönce
  • docker container rmpeşinden gitmek zorunda değilsin

2
cpVe hacme dayalı cevaplar arasındaki karşılaştırma için oylandı . Ayrıca, idmülkiyet hilesi için, bu bazen gerçek bir baş ağrısıdır
Marc Ghorayeb

18

Cevapların çoğu, kabın çalışması için önce docker cpçalışması gerektiğini göstermez :

docker build -t IMAGE_TAG .
docker run -d IMAGE_TAG
CONTAINER_ID=$(docker ps -alq)
# If you do not know the exact file name, you'll need to run "ls"
# FILE=$(docker exec CONTAINER_ID sh -c "ls /path/*.zip")
docker cp $CONTAINER_ID:/path/to/file .
docker stop $CONTAINER_ID

3
BTW, İster konteyner şıra / olabilir edilmesi çalışan / durdurulmuş / ya bağlı gibi görünüyor konak / sanallaştırma-tekniğinin türüne . Mevcut docker dokümanı "CONTAINER çalışan veya durdurulan bir kap olabilir" diyor. Kabul edilen cevaba bir yorum da dahil olmak üzere SO'da birden fazla yer "bu aynı zamanda durdurulmuş bir kapsayıcıda da çalışır" deyin. Altında Windows Hyper-V, görünüşe göre gerekli üzere bir dosya kopyalanırken önce kabı durdurun .
ToolmakerSteve

Kopyalama ayrıca kap durdurulduğunda da çalışır.
Luke W

17

Çalışan bir kapsayıcı, yalnızca bir resminiz yoksa ve yalnızca bir metin dosyasını kopyalamak istediğinizi varsayarsak, şöyle bir şey yapabilirsiniz:

docker run the-image cat path/to/container/file.txt > path/to/host/file.txt

7

Bunu Mac için Docker kullanan herkes için gönderiyorum. Benim için işe yarayan buydu:

 $ mkdir mybackup # local directory on Mac

 $ docker run --rm --volumes-from <containerid> \
    -v `pwd`/mybackup:/backup \  
    busybox \                   
    cp /data/mydata.txt /backup 

-vBu backupdizini kullanarak bağlandığında otomatik olarak oluşturulduğunu unutmayın.

Umarım bu bir gün için faydalıdır. :)


Docker-compose kullanıyorsanız, sürüm 3'te ve sonrasında birimlerden kaldırılır.
mulg0r

Mulg0r'ın yorumuna eklemek için, bkz. Stackoverflow.com/a/45495380/199364 - v.3 volumessürümünde, birden çok kapsayıcı tarafından erişilebilir birimlere erişmek için config.yml köküne bir komut yerleştirirsiniz .
ToolmakerSteve

5

Yalnızca bir dosyayı görüntüden (çalışan bir kapsayıcı yerine) çekmek istiyorsanız, bunu yapabilirsiniz:

docker run --rm <image> cat <source> > <local_dest>

Bu kapsayıcıyı getirir, yeni dosyayı yazar ve sonra kapsayıcıyı kaldırır. Bununla birlikte bir dezavantaj, dosya izinlerinin ve değiştirilme tarihinin korunmayacağıdır.



5

Docker 19.03 sürümüyle, kapsayıcı oluşturmayı ve hatta bir görüntü oluşturmayı atlayabilirsiniz. Çıktı hedefini değiştirmek için BuildKit tabanlı derlemelerde bir seçenek vardır. Bunu, yapının sonuçlarını bir görüntü yerine yerel dizininize yazmak için kullanabilirsiniz. Örneğin, bir go binary derlemesi:

$ ls
Dockerfile  go.mod  main.go

$ cat Dockerfile
FROM golang:1.12-alpine as dev
RUN apk add --no-cache git ca-certificates
RUN adduser -D appuser
WORKDIR /src
COPY . /src/
CMD CGO_ENABLED=0 go build -o app . && ./app

FROM dev as build
RUN CGO_ENABLED=0 go build -o app .
USER appuser
CMD [ "./app" ]

FROM scratch as release
COPY --from=build /etc/passwd /etc/group /etc/
COPY --from=build /src/app /app
USER appuser
CMD [ "/app" ]

FROM scratch as artifact
COPY --from=build /src/app /app

FROM release

Yukarıdaki Dockerfile'dan, artifactyalnızca dışa aktarmak istediğim dosyaları içeren sahneyi oluşturuyorum. Yeni tanıtılan --outputbayrak, bunları bir görüntü yerine yerel bir dizine yazmama izin veriyor. Bunun 19.03 ile gelen BuildKit motoruyla gerçekleştirilmesi gerekir:

$ DOCKER_BUILDKIT=1 docker build --target artifact --output type=local,dest=. .
[+] Building 43.5s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                                                              0.7s
 => => transferring dockerfile: 572B                                                                                              0.0s
 => [internal] load .dockerignore                                                                                                 0.5s
 => => transferring context: 2B                                                                                                   0.0s
 => [internal] load metadata for docker.io/library/golang:1.12-alpine                                                             0.9s
 => [dev 1/5] FROM docker.io/library/golang:1.12-alpine@sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0  22.5s
 => => resolve docker.io/library/golang:1.12-alpine@sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0       0.0s
 => => sha256:1ec62c064901392a6722bb47a377c01a381f4482b1ce094b6d28682b6b6279fd 155B / 155B                                        0.3s
 => => sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0 1.65kB / 1.65kB                                    0.0s
 => => sha256:2ecd820bec717ec5a8cdc2a1ae04887ed9b46c996f515abc481cac43a12628da 1.36kB / 1.36kB                                    0.0s
 => => sha256:6a17089e5a3afc489e5b6c118cd46eda66b2d5361f309d8d4b0dcac268a47b13 3.81kB / 3.81kB                                    0.0s
 => => sha256:89d9c30c1d48bac627e5c6cb0d1ed1eec28e7dbdfbcc04712e4c79c0f83faf17 2.79MB / 2.79MB                                    0.6s
 => => sha256:8ef94372a977c02d425f12c8cbda5416e372b7a869a6c2b20342c589dba3eae5 301.72kB / 301.72kB                                0.4s
 => => sha256:025f14a3d97f92c07a07446e7ea8933b86068d00da9e252cf3277e9347b6fe69 125.33MB / 125.33MB                               13.7s
 => => sha256:7047deb9704134ff71c99791be3f6474bb45bc3971dde9257ef9186d7cb156db 125B / 125B                                        0.8s
 => => extracting sha256:89d9c30c1d48bac627e5c6cb0d1ed1eec28e7dbdfbcc04712e4c79c0f83faf17                                         0.2s
 => => extracting sha256:8ef94372a977c02d425f12c8cbda5416e372b7a869a6c2b20342c589dba3eae5                                         0.1s
 => => extracting sha256:1ec62c064901392a6722bb47a377c01a381f4482b1ce094b6d28682b6b6279fd                                         0.0s
 => => extracting sha256:025f14a3d97f92c07a07446e7ea8933b86068d00da9e252cf3277e9347b6fe69                                         5.2s
 => => extracting sha256:7047deb9704134ff71c99791be3f6474bb45bc3971dde9257ef9186d7cb156db                                         0.0s
 => [internal] load build context                                                                                                 0.3s
 => => transferring context: 2.11kB                                                                                               0.0s
 => [dev 2/5] RUN apk add --no-cache git ca-certificates                                                                          3.8s
 => [dev 3/5] RUN adduser -D appuser                                                                                              1.7s
 => [dev 4/5] WORKDIR /src                                                                                                        0.5s
 => [dev 5/5] COPY . /src/                                                                                                        0.4s
 => [build 1/1] RUN CGO_ENABLED=0 go build -o app .                                                                              11.6s
 => [artifact 1/1] COPY --from=build /src/app /app                                                                                0.5s
 => exporting to client                                                                                                           0.1s
 => => copying files 10.00MB                                                                                                      0.1s

Derleme tamamlandıktan sonra appikili dosya dışa aktarıldı:

$ ls
Dockerfile  app  go.mod  main.go

$ ./app
Ready to receive requests on port 8080

--outputDocker'ın akış yukarı BuildKit deposunda belgelenen bayrağa başka seçenekleri de var : https://github.com/moby/buildkit#output


çıktı ile derleme için kullanılmayan standart derleme önbellek, kötü
burtsevyg

@burtsevyg Buildkit, farklı bir önbellek ortamı kullanan farklı bir oluşturucudur. Çok daha fazla önbellek verimlidir.
BMitch

teşekkür ederim yapı düğümlerimi geliştireceğim.
burtsevyg

4

Daha genel bir çözüm olarak Jenkins'in Docker konteynerinin içine inşa etmesi için bir CloudBees eklentisi var . Bir Docker kayıt defterinden kullanmak üzere bir görüntü seçebilir veya oluşturmak ve kullanmak için bir Docker dosyası tanımlayabilirsiniz.

Çalışma alanını bir birim (uygun kullanıcıyla) olarak kaba bağlar, çalışma dizininiz olarak ayarlar, istediğiniz komutları yapar (kapsayıcı içinde). Bunu yapmak için image.inside () {} komutuyla docker-iş akışı eklentisini de kullanabilirsiniz (UI yerine kod tercih ederseniz).

Temel olarak tüm bunlar, CI / CD sunucunuza ve sonra bazı pişmiş.


4

Bu komutla PowerShell (Yönetici) kullandım.

docker cp {container id}:{container path}/error.html  C:\\error.html

Misal

docker cp ff3a6608467d:/var/www/app/error.html  C:\\error.html

2

Başka bir iyi seçenek önce kap oluşturmak ve daha sonra bazı commads yürütmek için kabuk yorumlayıcı ile -c bayrağı kullanarak çalıştırmak

docker run --rm -i -v <host_path>:<container_path> <mydockerimage> /bin/sh -c "cp -r /tmp/homework/* <container_path>"

Yukarıdaki komut bunu yapar:

-i = kapsayıcıyı etkileşimli modda çalıştır

--rm = yürütme işleminden sonra kapsayıcı kaldırıldı.

-v = bir klasörü ana makine yolunuzdan kapsayıcı yoluna birim olarak paylaştı.

Son olarak, / bin / sh -c komutu komut olarak parametre olarak girmenizi sağlar ve bu komut ödev dosyalarınızı kapsayıcı yoluna kopyalar.

Umarım bu ek cevap size yardımcı olabilir


1

Ana bilgisayar sisteminde (kapsayıcı dışında) bir veri dizini oluşturun ve bunu kapsayıcı içinden görünen bir dizine bağlayın. Bu, dosyaları ana bilgisayar sisteminde bilinen bir konuma yerleştirir ve ana bilgisayar sistemindeki araçların ve uygulamaların dosyalara erişmesini kolaylaştırır

docker run -d -v /path/to/Local_host_dir:/path/to/docker_dir docker_image:tag

4
Bu, bir dizini ve içeriğini ana bilgisayardan konteynere enjekte etmenizi sağlar. Kapsayıcıdan ana bilgisayara dosya kopyalamanıza izin vermez.
BMitch

Ana bilgisayar klasörü çok geniş izinlere sahipse yapar mı?
giorgiosironi

0

Dosyayı kopyalamak istediğiniz bir yol oluşturun ve şunu kullanın:

docker run -d -v hostpath:dockerimag

0

Bir kapsayıcı için özel depolama alanı oluşturmak bindyerine, volumeyalnızca tek bir klasör takmak yerine kullanabilirsiniz :

  1. Görüntünüzü etiketle oluşturun:

    docker build . -t <image>

  2. Resminizi çalıştırın ve app.py'nin depolandığı geçerli $ (pwd) dizinini bağlayın ve kabınızın içinde / root / example / ile eşleyin.

    docker run --mount type=bind,source="$(pwd)",target=/root/example/ <image> python app.py


0

Bu, örneğin python gibi SDK'da da yapılabilir. Zaten bir kapsayıcı oluşturduysanız, adı console ( docker ps -a) ile arayabilirsiniz.Bir bilim adamı ve bir sıfatın (örneğin "relaxed_pasteur") bir araya gelmesi gibi görünüyor.

Çıkış help(container.get_archive):

Help on method get_archive in module docker.models.containers:

get_archive(path, chunk_size=2097152) method of docker.models.containers.Container instance
    Retrieve a file or folder from the container in the form of a tar
    archive.

    Args:
        path (str): Path to the file or folder to retrieve
        chunk_size (int): The number of bytes returned by each iteration
            of the generator. If ``None``, data will be streamed as it is
            received. Default: 2 MB

    Returns:
        (tuple): First element is a raw tar data stream. Second element is
        a dict containing ``stat`` information on the specified ``path``.

    Raises:
        :py:class:`docker.errors.APIError`
            If the server returns an error.

    Example:

        >>> f = open('./sh_bin.tar', 'wb')
        >>> bits, stat = container.get_archive('/bin/sh')
        >>> print(stat)
        {'name': 'sh', 'size': 1075464, 'mode': 493,
         'mtime': '2018-10-01T15:37:48-07:00', 'linkTarget': ''}
        >>> for chunk in bits:
        ...    f.write(chunk)
        >>> f.close()

Böylece, böyle bir şey kaptaki belirtilen yoldan (/ çıktıdan) ana makinenize çekilir ve katranı paketinden çıkarır.

import docker
import os
import tarfile

# Docker client
client = docker.from_env()
#container object
container = client.containers.get("relaxed_pasteur")
#setup tar to write bits to
f = open(os.path.join(os.getcwd(),"output.tar"),"wb")
#get the bits
bits, stat = container.get_archive('/output')
#write the bits
for chunk in bits:
    f.write(chunk)
f.close()
#unpack
tar = tarfile.open("output.tar")
tar.extractall()
tar.close()
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.