2014-11-01 16 views
11

Tôi cần nội dung của tệp *.zip lớn (5 gb) trong vùng chứa Docker để biên dịch chương trình. Tệp *.zip nằm trên máy cục bộ của tôi. Chiến lược này sẽ là:Cách thêm tệp vào ảnh trong Dockerfile mà không sử dụng chỉ thị ADD hoặc COPY

COPY program.zip /tmp/ 
RUN cd /tmp \ 
&& unzip program.zip \ 
&& make 

Sau khi làm điều này tôi muốn loại bỏ các thư mục giải nén và bản gốc *.zip tập tin bởi vì họ không cần thiết nữa. Vấn đề là COPY (và cũng là chỉ thị ADD) sẽ thêm một lớp vào hình ảnh sẽ chứa tệp program.zip có vấn đề khi hình ảnh có thể có kích thước tối thiểu là 5gb. Có cách nào để thêm tệp vào vùng chứa không sử dụng chỉ thị COPY hoặc ADD không? wget sẽ không hoạt động như tệp *.zip được đề cập trên máy cục bộ của tôi và curl file://localhost/home/user/program.zip -o /tmp/program.zip cũng sẽ không hoạt động.

+0

Bạn không thể đơn giản giải nén trước trên máy cục bộ của mình? Và sau đó thêm những thứ bạn cần? – Nick

+0

Có, nhưng tôi cũng muốn xóa thư mục đã giải nén vì nó vẫn còn trên 5 gb. Nhưng tôi đã tìm ra cách để làm những gì tôi muốn. Câu trả lời là theo cách của nó. –

+0

và tệp make.sh có tạo và xóa tệp không? – Rondo

Trả lời

17

Không đơn giản nhưng có thể thực hiện qua wget hoặc curl với sự hỗ trợ từ python. (Tất cả ba công cụ thường nên có sẵn trên một hệ thống *nix.)

wget sẽ không hoạt động khi không có url được đưa ra và

curl file://localhost/home/user/program.zip -o /tmp/ 

sẽ không làm việc từ bên trong một RUN hướng dẫn Dockerfile 's. Do đó, chúng tôi sẽ cần một máy chủ mà wgetcurl có thể truy cập và tải xuống program.zip từ.

Để làm điều này, chúng tôi thiết lập một máy chủ python nhỏ phục vụ yêu cầu http của chúng tôi. Chúng tôi sẽ sử dụng mô-đun http.server từ python cho điều này. (Bạn có thể sử dụng python hoặc python 3. Nó sẽ hoạt động với cả hai.).

python -m http.server --bind 192.168.178.20 8000 

Máy chủ python sẽ phục vụ tất cả các file trong thư mục nó được bắt đầu từ năm. Vì vậy, bạn nên chắc chắn rằng bạn bắt đầu máy chủ của bạn, hoặc trong thư mục các tập tin bạn muốn tải về trong xây dựng hình ảnh của bạn nằm trong hoặc tạo một thư mục tạm thời chứa chương trình của bạn. Đối với mục đích minh họa chúng ta hãy tạo ra các tập tin foo.txt mà chúng tôi sau này sẽ tải qua wget trong Dockerfile của chúng tôi:

echo "foo bar" > foo.txt 

Khi khởi chạy máy chủ http, điều quan trọng là, rằng chúng tôi chỉ định địa chỉ IP của máy tính cục bộ của chúng tôi trên mạng LAN. Hơn nữa, chúng tôi sẽ mở cổng 8000. Sau khi làm điều này chúng ta sẽ thấy kết quả như sau:

python3 -m http.server --bind 192.168.178.20 8000 
Serving HTTP on 192.168.178.20 port 8000 ... 

Bây giờ chúng ta xây dựng một Dockerfile để minh họa cách làm việc này.(Chúng tôi sẽ giả định rằng tập tin foo.txt nên được tải vào /tmp):

FROM debian:latest 
RUN apt-get update -qq \ 
&& apt-get install -y wget 
RUN cd /tmp \ 
&& wget http://192.168.178.20:8000/foo.txt 

Bây giờ chúng ta bắt đầu xây dựng với

docker build -t test . 

Trong tòa nhà, bạn sẽ thấy kết quả như sau trên máy chủ python của chúng tôi:

172.17.0.21 - - [01/Nov/2014 23:32:37] "GET /foo.txt HTTP/1.1" 200 - 

và kết quả đầu ra của hình ảnh của chúng tôi sẽ là:

Step 2 : RUN cd /tmp && wget http://192.168.178.20:8000/foo.txt 
---> Running in 49c10e0057d5 
--2014-11-01 22:56:15-- http://192.168.178.20:8000/foo.txt 
Connecting to 192.168.178.20:8000... connected. 
HTTP request sent, awaiting response... 200 OK 
Length: 25872 (25K) [text/plain] 
Saving to: `foo.txt' 

    0K .......... .......... .....       100% 129M=0s 

2014-11-01 22:56:15 (129 MB/s) - `foo.txt' saved [25872/25872] 

---> 5228517c8641 
Removing intermediate container 49c10e0057d5 
Successfully built 5228517c8641 

Sau đó bạn có thể kiểm tra nếu nó thực sự làm việc bằng cách bắt đầu và bước vào một container từ biểu tượng bạn muốn xây dựng:

docker run -i -t --rm test bash 

Sau đó bạn có thể tìm trong /tmp cho foo.txt.

Bây giờ, chúng tôi có thể thêm bất kỳ tệp nào vào image mà không tạo lớp mới. Giả sử bạn muốn thêm chương trình khoảng 5 gb như được đề cập trong câu hỏi chúng tôi có thể thực hiện:

FROM debian:latest 
RUN apt-get update -qq \ 
&& apt-get install -y wget 
RUN cd /tmp \ 
&& wget http://conventiont:8000/program.zip \ 
&& unzip program.zip \ 
&& cd program \ 
&& make \ 
&& make install \ 
&& cd /tmp \ 
&& rm -f program.zip \ 
&& rm -rf program 

Bằng cách này, chúng tôi sẽ không còn 10 gb.

+0

Thông minh! Cần phải lưu trữ điều này trên một cái gì đó như aws mặc dù nếu bạn muốn làm một xây dựng đáng tin cậy. – retrohacker

+0

Câu trả lời hay! Cảm ơn. – mkoertgen

+0

Cách tiếp cận này là rất tốt, nhưng nó yêu cầu máy chủ lưu trữ phải có IP ổn định, nếu không bạn cần phải tiếp tục thay đổi địa chỉ IP được sử dụng trong wget trong khách. Sẽ là tốt đẹp để có một giải pháp để giải quyết điều đó quá (tôi đã không có bất kỳ ý tưởng tốt nào được nêu ra!). –

2

Bạn không thể ánh xạ thư mục cục bộ vào vùng chứa khi khởi chạy và sau đó sao chép các tệp bạn cần.

sudo docker run -d -P --name myContainerName -v /localpath/zip_extract:/container/path/ yourContainerID 

https://docs.docker.com/userguide/dockervolumes/

+0

Tôi có lẽ sẽ phải giải nén và biên dịch chương trình mỗi lần container bắt đầu (Hoặc làm ít nhất một lần khi container bắt đầu và sau đó cam kết nó.). Tôi muốn có một giải pháp dựa trên 'Dockerfile'. –

+0

Ah, đã đọc câu trả lời của bạn, bây giờ tôi thấy những gì bạn đang cố gắng làm. Giải pháp tốt. – Emile

+0

ánh xạ khối lượng chỉ có thể được thực hiện trong khi "chạy" không trong quá trình "xây dựng". Khi thêm khối lượng trên xây dựng một số công cụ (bao gồm cả lang thang) tự động thêm/sao chép. Bạn không muốn điều này vì mỗi hướng dẫn bổ sung sẽ được biên dịch thành một lớp deltay trong hình ảnh docker cuối cùng. – mkoertgen

0

Tôi đã đăng một câu trả lời tương tự ở đây: https://stackoverflow.com/a/37542913/909579

Bạn có thể sử dụng docker-squash dẹp lớp mới được tạo ra. Điều đó về cơ bản sẽ loại bỏ các kho lưu trữ từ hình ảnh cuối cùng nếu bạn loại bỏ nó trong hướng dẫn RUN tiếp theo.

Các vấn đề liên quan