Trích xuất tập tin từ hình ảnh docker?


24

Tôi muốn trích xuất một tập tin từ hình ảnh Docker mà không phải chạy hình ảnh.

Các docker savetùy chọn không phải là currrently một lựa chọn khả thi đối với tôi là nó tiết kiệm quá lớn của một tập tin chỉ để un-tar một tập tin cụ thể.


Bạn đang sử dụng bản phân phối nào?
ryekayo

@ryekayo: Ubuntu 14, docker 1.12.4 (api 1.24)
BlakBat

Câu trả lời:


21

Bạn có thể trích xuất các tập tin từ một hình ảnh bằng các lệnh sau:

docker create $image  # returns container ID
docker cp $container_id:$source_path $destination_path
docker rm $container_id

Theo docker create tài liệu , điều này không chạy container:

Các docker createlệnh tạo ra một lớp chứa có thể ghi lên ảnh cụ thể và chuẩn bị nó cho chạy lệnh chỉ định. ID container sau đó được in ra STDOUT. Điều này tương tự như docker run -dngoại trừ container không bao giờ được bắt đầu. Sau đó, bạn có thể sử dụng docker start <container_id>lệnh để khởi động container tại bất kỳ điểm nào.


Để tham khảo (câu trả lời trước của tôi), một cách ít hiệu quả hơn để trích xuất một tệp từ một hình ảnh là như sau:

docker run some_image cat $file_path > $output_path

3
Bạn có thể muốn đi quá nhiều điểm vào. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Andrew

1
Điều này chạy hình ảnh, đó là cụ thể những gì tôi không muốn làm như đã nêu trong câu hỏi của tôi.
BlakBat

Ah, đó là một điểm tốt. Tôi đồng ý câu trả lời hiện tại của tôi không thỏa đáng.
bbc

1
@BlakBat Câu trả lời cập nhật này có hiệu quả với bạn không? Tôi đoán tôi nên tạo ra một câu trả lời mới nhưng nó đã được thực hiện ngay bây giờ.
bbc

1
@bbc Câu trả lời cập nhật này trong thực tế không bắt đầu một thùng chứa (mấu chốt của câu hỏi) và không yêu cầu phải root.
BlakBat

2

Không ai ở trên làm việc cho tôi. Lệnh làm việc hoàn chỉnh là:

docker run --rm --entrypoint /bin/sh image_name -c "cat /path/filename" > output_filename

Không có dấu ngoặc kép catđược thông qua mà không có tên tệp, vì vậy nó không biết phải hiển thị gì. Ngoài ra, nên xóa container sau khi lệnh kết thúc.


Lệnh bạn đang đề cập sẽ chỉ hoạt động tùy thuộc vào docker và cách ENTRYPOINT / CMD được đặt chính xác trong Dockerfile; điều này không có gì để làm với trích dẫn. Bạn cũng nói để xóa container, nhưng bạn chỉ định --rm. Cuối cùng, khi tôi đã đăng câu hỏi của mình, tôi đã chỉ định "không phải chạy hình ảnh" và không có câu trả lời nào là một giải pháp có tính đến điều này.
BlakBat

1
Bất kể CMD và ENTRYPOINT nào được đặt trong Dockerfile tôi đều ghi đè cả hai, vì vậy nó sẽ luôn hoạt động (tất nhiên là trên Linux). Bạn có ý nghĩa gì bởi "phụ thuộc vào docker"? Cài đặt, phiên bản, env, cái gì? Câu hỏi của bạn không chính xác vì hình ảnh không thể được thực thi, chỉ có container mới có thể. Tôi nghĩ rằng không có câu trả lời chính xác, bạn phải xử lý nhiều tệp hoặc tạo một thùng chứa tạm thời. --rm xóa bộ chứa tạm thời, câu trả lời của người khác để lại một số rác trên đĩa của bạn.
sekrett

1

Nếu tôi không nhầm, tôi tin rằng các container docker lưu trữ các tệp được lưu trong bộ nhớ cache được tạo trong thư mục sau cho Ubuntu:

/var/lib/docker/aufs/diff/<container_id>

Từ đó bạn sẽ có thể truy cập hệ thống tệp và truy xuất (các) tệp của mình.


Không. Thư mục đó chỉ chứa layersizejson, và cũng không thể đọc được người dùng (ngay cả khi người dùng nằm trong nhóm docker). /var/lib/docker/aufs/diffsẽ chứa tệp mà tôi tìm kiếm (nhưng được phân loại không theo id container) và cũng không thể đọc được.
BlakBat

Hãy cho tôi một ít và tôi sẽ tìm kiếm nó. Tôi biết thực tế có một cách để truy xuất các tệp mà không cần nhập vào container hoặc chạy nó.
ryekayo

Bởi không thể đọc, làm thế nào nó hiển thị? Tôi đã tìm thấy một ví dụ nơi bạn có thể kéo các tệp văn bản từ các thùng chứa bằng cách vào thư mục / var / lib / docker / aufs / diff / *
ryekayo

Lỗi của tôi. Người dùng có thể truy cập /var/lib/docker/aufs(nhưng không phải tất cả các thư mục khác trong /var/lib/docker/)
BlakBat

Bạn có thể truy cập như root?
ryekayo

0

Nếu lưu trữ toàn bộ đầu ra docker savekhông phải là một tùy chọn, bạn có thể sử dụng các đường ống để chỉ trích xuất tệp cần thiết từ nó.

Thật không may, vì đầu ra là một "tar of tars", nó có thể là một quá trình lặp đi lặp lại một chút.

Những gì tôi đã làm khi tôi cần giải nén một tập tin là:

1) Xác định phiên bản hình ảnh mà tập tin bạn quan tâm đã thay đổi gần đây nhất (cách bạn thực hiện việc này có thể phụ thuộc vào hình ảnh của bạn) và ngày nó được tạo / lưu

2) Lấy toàn bộ mục lục từ đầu ra của docker savelệnh với:

docker save IMAGE_NAME | tar -tvf -

3) Phạt layer.tar(các) tệp trong đầu ra của lệnh đó khớp với ngày của hình ảnh mà bạn đã xác định trong bước 1. (bạn có thể thêm | grep layer.tarvào để chỉ hiển thị các tệp đó)

4) Trích xuất layer.tartập tin đó ra tiêu chuẩn và lấy mục lục của nó:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -tvf -

5) Xác minh tệp bạn muốn được liệt kê và giải nén nó khi bạn tìm thấy tên:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -xf - PATH/TO/YOUR/FILE

Nếu có nhiều hơn một layer.tartệp khớp với ngày bạn đang tìm kiếm ở bước 2/3, bạn có thể cần lặp lại bước 4 cho mỗi tệp cho đến khi bạn tìm đúng.

Thay thế văn bản bằng chữ in hoa trong các lệnh trên bằng tên hình ảnh, tổng kiểm tra và tên tệp chính xác cho trường hợp của bạn.

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.