Docker - làm cách nào tôi có thể sao chép tệp từ hình ảnh sang máy chủ lưu trữ?


117

Câu hỏi của tôi liên quan đến câu hỏi này về việc sao chép tệp từ vùng chứa sang máy chủ; Tôi có một Dockerfile tìm nạp các phụ thuộc, biên dịch một cấu phần xây dựng từ nguồn và chạy một tệp thực thi. Tôi cũng muốn sao chép tạo tác xây dựng (trong trường hợp của tôi, đó là .ziptạo tác được sản xuất bởi sbt distin '../ target / `, nhưng tôi nghĩ câu hỏi này cũng áp dụng cho các lọ, tệp nhị phân, v.v.

docker cphoạt động trên vùng chứa, không phải hình ảnh; tôi có cần khởi động vùng chứa chỉ để lấy tệp ra khỏi nó không? Trong một tập lệnh, tôi đã thử chạy /bin/bashở chế độ tương tác trong nền, sao chép tệp ra ngoài và sau đó giết vùng chứa, nhưng điều này có vẻ khó hiểu. Có cách nào tốt hơn?

Mặt khác, tôi muốn tránh giải nén một .tartệp sau khi chạy docker save $IMAGENAMEchỉ để lấy một tệp ra (nhưng đó có vẻ là tùy chọn đơn giản nhất, nếu chậm nhất, ngay bây giờ).

Tôi sẽ sử dụng khối lượng docker, ví dụ:

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

nhưng tôi đang chạy boot2dockertrong OSX và tôi không biết cách ghi trực tiếp vào hệ thống tệp máy chủ lưu trữ mac của mình (khối lượng đọc-ghi đang gắn bên trong máy ảo boot2docker của tôi, có nghĩa là tôi không thể dễ dàng chia sẻ tập lệnh để trích xuất blah.ziptừ một hình ảnh những người khác.

Câu trả lời:


172

Để sao chép tệp từ một hình ảnh, hãy tạo một vùng chứa tạm thời, sao chép tệp từ đó và sau đó xóa nó:

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

Phiên bản nào của Docker là createlệnh thêm / gỡ bỏ (nó không có mặt trong 1,01)
ThorSummoner

2
@ThorSummoner docker createđã được giới thiệu trong docker
Igor Bukanov

1
Tôi không biết tại sao đây không được chọn là câu trả lời chính xác.
CentAu

1
Chắc chắn là câu trả lời đúng !!! Không dựa vào bất cứ thứ gì bên trong hộp đựng ... Đối với hình ảnh vết xước Golang, đây là cách duy nhất có thể!
Marcello de Sales

2
bất kỳ lý do nào để sao chép vào stdout và sau đó chuyển trực tiếp nó vào một tệp cục bộ? khi tôi làm điều này, nó đã đổ một loạt các ký tự điều khiển trước và sau nội dung của tệp. chạy nó trực tiếp như docker cp $id:path > local-tar-fileđã hoạt động hoàn hảo.
Yonatan

62

Thật không may, dường như không có cách nào để sao chép tệp trực tiếp từ hình ảnh Docker. Trước tiên, bạn cần tạo một vùng chứa và sau đó sao chép tệp từ vùng chứa.

Tuy nhiên, nếu hình ảnh của bạn chứa một catlệnh (và nó sẽ thực hiện trong nhiều trường hợp), bạn có thể thực hiện điều đó bằng một lệnh duy nhất:

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

Nếu hình ảnh của bạn không chứa cat, chỉ cần tạo một vùng chứa và sử dụng docker cplệnh như được đề xuất trong câu trả lời của Igor.


1
Giải pháp tuyệt vời. Không thể truy cập vùng chứa của tôi vì nó bị lỗi một giây sau khi khởi chạy, nhưng cần lấy một tệp trong đó. Điều này đã hoạt động hoàn hảo.
Mirodinho

23

Một tùy chọn nhanh hơn nhiều là sao chép tệp từ vùng chứa đang chạy sang ổ đĩa được gắn kết:

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

thực 0m0.446s

** VS **

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

thực 0m9.014s


Điều này có thể liên quan nhiều hơn đến việc hệ thống tệp bên dưới thực hiện sao chép tệp chậm / nông (nghĩ là copy-on-write) trong ví dụ đầu tiên, so với việc thực sự sao chép các byte của tệp trong ví dụ thứ hai. Một bài kiểm tra hữu ích sẽ là xem liệu cat a >bvs cp a bcó thời gian tương tự như được hiển thị ở đây hay không. Ngoài ra, nếu đường dẫn nguồn và đường dẫn đích nằm trên các hệ thống tệp khác nhau, thì cả hai ví dụ sẽ dẫn đến bản sao byte-for-byte đầy đủ.
KevinOrr

14

Nhận xét của phụ huynh đã chỉ ra cách sử dụng mèo . Bạn cũng có thể sử dụng tar theo cách tương tự:

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

1
Câu trả lời này là sao chép các thư mục thay vì các tệp như câu hỏi ban đầu yêu cầu. Tuy nhiên, +1 vì nó cũng hoạt động với các tệp và đi kèm với một tính năng bổ sung: quyền và bảo quản chủ sở hữu. Tuyệt quá!
caligari

5
Trên thực tế, tôi sử dụngdocker run --rm --entrypoint tar _image_ cC _img_directory_ . | tar xvC _host_directory_
Caligari

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

muốn cung cấp một giải pháp một dòng

chỉnh sửa: vùng chứa thậm chí không cần phải chạy trong giải pháp này


1

Một câu trả lời (ngắn) khác cho vấn đề này:

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

0

Tôi đang sử dụng boot2docker trên MacOS. Tôi có thể đảm bảo với bạn rằng các tập lệnh dựa trên "docker cp" là có thể di động. Bởi vì bất kỳ lệnh nào được chuyển tiếp bên trong boot2docker nhưng sau đó luồng nhị phân được chuyển tiếp trở lại máy khách dòng lệnh docker đang chạy trên máy mac của bạn. Vì vậy, các hoạt động ghi từ máy khách docker được thực thi bên trong máy chủ và được ghi trở lại phiên bản máy khách đang thực thi!

Tôi đang chia sẻ tập lệnh sao lưu cho khối lượng docker với bất kỳ vùng chứa docker nào mà tôi cung cấp và các tập lệnh sao lưu của tôi được thử nghiệm cả trên linux và MacOS với boot2docker. Các bản sao lưu có thể dễ dàng trao đổi giữa các nền tảng. Về cơ bản, tôi đang thực hiện lệnh sau bên trong tập lệnh của mình:

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

Chạy một vùng chứa busybox mới và gắn dung lượng của vùng chứa jenkins của tôi với tên jenkins_jenkins_1. Toàn bộ tập được ghi vào bản sao lưu tệp / JenkinsBackup-2015-07-09-14-26-15.tar

Tôi đã chuyển các tệp lưu trữ giữa vùng chứa linux và vùng chứa mac của mình mà không có bất kỳ điều chỉnh nào đối với tập lệnh sao lưu hoặc khôi phục. Nếu đây là những gì bạn muốn, bạn hãy tìm toàn bộ tập lệnh, một hướng dẫn ở đây: blacklabelops / jenkins


0

Bạn có thể liên kết một đường dẫn cục bộ trên máy chủ lưu trữ với một đường dẫn trên vùng chứa, rồi cpđến (các) tệp mong muốn với đường dẫn đó ở cuối tập lệnh của bạn.

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

Sau đó không cần phải sao chép sau đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.