Nhiều TỪ - nghĩa là gì


112

Tôi muốn xây dựng hình ảnh docker cho dự án Linkurious trên github, dự án này yêu cầu cả cơ sở dữ liệu Neo4j và Node.js để chạy.

cách tiếp cận đầu tiên của tôi là khai báo một hình ảnh cơ sở cho hình ảnh của tôi, chứa Neo4j. Các tài liệu tham khảo không xác định "hình ảnh cơ sở" theo bất kỳ cách hữu ích nào:

Hình ảnh cơ sở: Hình ảnh không có cha là hình ảnh cơ sở

từ đó tôi đọc rằng tôi có thể chỉ có một hình ảnh cơ sở nếu hình ảnh đó không có hình ảnh cơ sở.

nhưng hình ảnh cơ sở là gì? có nghĩa là nếu tôi khai báo neo4j / neo4j trong chỉ thị FROM, thì khi hình ảnh của tôi được chạy, cơ sở dữ liệu neo sẽ tự động chạy và có sẵn trong vùng chứa trên cổng 7474?

đọc tham chiếu Docker (xem: https://docs.docker.com/reference/builder/#from ), tôi thấy:

FROM có thể xuất hiện nhiều lần trong một Dockerfile để tạo nhiều hình ảnh. Đơn giản chỉ cần ghi chú về đầu ra ID hình ảnh cuối cùng bằng cam kết trước mỗi lệnh FROM mới.

tôi có muốn tạo nhiều hình ảnh không? Có vẻ như những gì tôi muốn là có một hình ảnh duy nhất chứa nội dung của các hình ảnh khác, ví dụ như neo4j và node.js

Tôi không tìm thấy chỉ thị nào để khai báo các phụ thuộc trong hướng dẫn tham khảo. không có sự phụ thuộc nào như trong RPM, nơi để chạy hình ảnh của tôi, ngữ cảnh gọi trước tiên phải cài đặt hình ảnh mà nó cần?

Tôi bối rối...


Lưu ý: Tháng 5 năm 2017, bạn hiện có nhiều FROMtrong a Dockerfile. Xem câu trả lời đã chỉnh sửa của tôi bên dưới.
VonC

Hãy xem bạn có thấy câu trả lời của tôi rõ ràng hơn không. Và nếu vậy, hãy cân nhắc việc chấp nhận nó.
Evan Carroll

Câu trả lời:


113

hình ảnh cơ sở là gì?

Một tập hợp các tệp, cùng với EXPOSE'd cổng, ENTRYPOINTCMD.
Bạn có thể thêm tệp và xây dựng hình ảnh mới dựa trên hình ảnh cơ sở đó, với một Dockerfilekhởi đầu mới bằng FROMchỉ thị: hình ảnh được đề cập sau FROMlà "hình ảnh cơ sở" cho hình ảnh mới của bạn.

có nghĩa là nếu tôi khai báo neo4j/neo4jtrong một FROMchỉ thị, rằng khi hình ảnh của tôi được chạy, cơ sở dữ liệu neo sẽ tự động chạy và có sẵn trong vùng chứa trên cổng 7474?

Chỉ khi bạn không ghi đè CMDENTRYPOINT.
Nhưng hình ảnh tự nó là đủ: bạn sẽ sử dụng một FROM neo4j/neo4jnếu bạn phải thêm các tệp liên quan đến neo4jcho việc sử dụng cụ thể của bạn neo4j.

FROM có thể xuất hiện nhiều lần trong một Dockerfile duy nhất

Đừng: vẫn có đề xuất xóa "tính năng" đó ( vấn đề 13026 )

Vấn đề 14412 đề cập:

Sử dụng nhiều FROMkhông thực sự là một tính năng mà là một lỗi (ồ, giới hạn rất chặt chẽ và có rất ít trường hợp sử dụng cho nhiều FROMtrong một Dockerfile).


Cập nhật tháng 5 năm 2017 (18 tháng sau), với docker (moby) 17.05-ce .

Nhiều FROM có thể được sử dụng trong một Dockerfile.
Xem " Mẫu xây dựng so với các bản dựng nhiều giai đoạn trong Docker " (bởi Alex Ellis ) và PR 31257 của Tõnis Tiigi .

Trước:

Mẫu xây dựng liên quan đến việc sử dụng hai hình ảnh Docker - một hình ảnh để thực hiện xây dựng và một hình ảnh khác để gửi kết quả của lần xây dựng đầu tiên mà không bị phạt chuỗi xây dựng và công cụ trong hình ảnh đầu tiên.

Sau:

Cú pháp chung liên quan đến việc thêm FROMthời gian bổ sung trong Dockerfile của bạn - bất kỳ FROMcâu lệnh nào cuối cùng là hình ảnh cơ sở cuối cùng. Để sao chép tạo tác và kết quả đầu ra từ hình ảnh trung gian, sử dụng COPY --from=<base_image_number>.

Phần đầu tiên của Dockerfile:

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

Phần thứ hai của cùng (!) Dockerfile:

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app    .
CMD ["./app"]  

Kết quả sẽ là hai hình ảnh, một hình ảnh để xây dựng, một hình ảnh chỉ chứa ứng dụng kết quả ( nhỏ hơn nhiều )

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  

2
tiếc về việc loại bỏ nhiều FROM. đối với tôi nó dường như hữu ích nhất, đặc biệt là trong trường hợp không có cơ chế phụ thuộc. với RPM, chẳng hạn, tôi có thể tuyên bố rằng gói của tôi cần một gói khác để chạy nên tại thời điểm cài đặt, mọi thứ sẽ được thiết lập cho tôi. thực tế là hầu hết mọi thứ sẽ yêu cầu nhiều phụ thuộc vì vậy trong trường hợp không có nhiều TỪ, điều đó sẽ hoạt động như thế nào?
ekkis

3
@ekkis như tôi đã đề cập trong câu trả lời trước của mình ( stackoverflow.com/a/33295292/6309 ), bạn chạy hệ thống của mình bằng cách sắp xếp nhiều vùng chứa, mỗi vùng chứa cung cấp một dịch vụ cụ thể và giao tiếp thông qua --link ( docs.docker.com/ userguide / dockerlinks /… ).
VonC

2
@VonC Chắc chắn rồi, trong một thế giới lý tưởng, với một ứng dụng mới và tất cả các mẫu đều được hiểu. Trong thời gian chờ đợi, tôi hy vọng sẽ có nhiều trường hợp hơn về những người cố gắng di chuyển các giải pháp của họ vào docker và có những nhu cầu không được giải quyết bằng mạng, chẳng hạn như phụ thuộc phần mềm, tất cả đều sử dụng một cơ sở tương thích, nhưng TỪ nhiều Dockerfiles. Thay vào đó, điều tốt nhất tôi có thể tìm ra cho đến nay là bẻ khóa các tệp Dockerfiles của họ để tạo tệp của riêng tôi.
rainabba

@rainabba Đồng ý. Những tảng đá nguyên khối kế thừa sẽ không được di chuyển dễ dàng. Các bài đọc thú vị: martinfowler.com/articles/… , threedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC

2

Câu trả lời đầu tiên là quá phức tạp, mang tính lịch sử và không phù hợp với sở thích của tôi.


Nó thực sự khá đơn giản. Docker cung cấp cho một chức năng được gọi là xây dựng nhiều giai đoạn , ý tưởng cơ bản ở đây là,

  • Giải phóng bạn khỏi việc phải xóa những thứ bạn không muốn theo cách thủ công, bằng cách buộc bạn phải đưa những gì bạn muốn vào danh sách trắng,
  • Các tài nguyên miễn phí sẽ được sử dụng do việc triển khai Docker.

Hãy bắt đầu với cái đầu tiên. Bạn sẽ thấy rất thường xuyên với thứ gì đó giống như Debian.

RUN apt-get update \ 
  && apt-get dist-upgrade \
  && apt-get install <whatever> \
  && apt-get clean

Chúng tôi có thể giải thích tất cả điều này theo những điều trên. Lệnh trên được liên kết với nhau để nó đại diện cho một thay đổi duy nhất mà không cần Hình ảnh trung gian. Nếu nó được viết như thế này,

RUN apt-get update ;
RUN apt-get dist-upgrade;
RUN apt-get install <whatever>;
RUN apt-get clean;

Nó sẽ dẫn đến 3 Hình ảnh trung gian tạm thời hơn. Khi nó được giảm xuống một hình ảnh, có một vấn đề còn lại: apt-get cleankhông xóa các phần mềm tạo tác được sử dụng trong cài đặt. Nếu người bảo trì Debian đưa vào bản cài đặt của mình một tập lệnh sửa đổi hệ thống thì sửa đổi đó cũng sẽ có mặt trong giải pháp cuối cùng (xem pepperflashplugin-nonfreeví dụ như thế này).

Bằng cách sử dụng bản dựng nhiều giai đoạn, bạn nhận được tất cả lợi ích của một hành động được thay đổi duy nhất, nhưng nó sẽ yêu cầu bạn lập danh sách trắng và sao chép theo cách thủ công các tệp đã được giới thiệu trong hình ảnh tạm thời bằng COPY --fromcú pháp được ghi ở đây. Hơn nữa, đó là một giải pháp tuyệt vời mà không có giải pháp thay thế (như một apt-get clean), và nếu không, bạn sẽ có rất nhiều tệp không cần thiết trong hình ảnh cuối cùng của mình.

Xem thêm


cảm ơn nhưng tôi không biết bạn đang giải quyết vấn đề của tôi như thế nào. đối với tôi, FROM là một cơ chế kế thừa và có nhiều chỉ thị có nghĩa là tôi có thể thừa kế từ nhiều bậc cha mẹ. trong câu trả lời của bạn, bạn không đề cập đến FROM hoặc khái niệm lợi dụng việc đóng gói phần mềm của người khác
ekkis

1
Có lẽ đó là sự nhầm lẫn. FROMvề cơ bản là một khai báo không gian tên. Vòng loại ở đó giống như một phần mở rộng hơn là kế thừa. Bạn có thể khai báo nhiều không gian tên. Và mỗi không gian tên đó có thể mở rộng một không gian tên khác. @ekkis Nếu câu trả lời khác phù hợp với bạn, thì hãy kiên trì với nó.
Evan Carroll
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.