Несколько FROM - что это значит

113

Я хочу создать образ докера для проекта Linkurious на github, для работы которого требуется как база данных Neo4j, так и Node.js.

Моим первым подходом было объявить базовое изображение для моего изображения, содержащее Neo4j. Справочные документы не определяют «базовое изображение» каким-либо полезным образом:

Базовое изображение: изображение, не имеющее родителя, является базовым.

из которого я прочитал, что у меня может быть только базовое изображение, если у этого изображения нет самого базового изображения.

а что такое базовый образ? Означает ли это, что если я объявлю neo4j / neo4j в директиве FROM, то при запуске моего образа база данных neo будет автоматически запускаться и будет доступна в контейнере на порту 7474?

читая ссылку на Docker (см .: https://docs.docker.com/reference/builder/#from ), я вижу:

FROM может появляться несколько раз в одном Dockerfile для создания нескольких образов. Просто запишите последний идентификатор изображения, выводимый коммитом перед каждой новой командой FROM.

я хочу создать несколько изображений? Казалось бы, я хочу иметь одно изображение, которое содержит содержимое других изображений, например neo4j и node.js

Я не нашел в справочном руководстве директивы для объявления зависимостей. Нет ли зависимостей, как в RPM, где для запуска моего изображения вызывающий контекст должен сначала установить нужные ему изображения?

Я запутался...

Эккис
источник
Примечание: май 2017 г., теперь у вас есть несколько FROMфайлов Dockerfile. См. Мой отредактированный ответ ниже.
VonC
Посмотри, найдешь ли ты мой ответ чище И если да, подумайте о том, чтобы принять это.
Эван Кэрролл,

Ответы:

113

что такое базовое изображение?

Набор файлов, плюс EXPOSEd-порты ENTRYPOINTи CMD.
Вы можете добавлять файлы и создавать новый образ на основе этого базового образа с новым, Dockerfileначинающимся с FROMдирективы: изображение, упомянутое после, FROMявляется «базовым изображением» для вашего нового образа.

Означает ли это, что если я объявлю neo4j/neo4jв FROMдирективе, что при запуске моего образа база данных neo будет автоматически запускаться и будет доступна в контейнере на порту 7474?

Только если не перезаписывать CMDи ENTRYPOINT.
Но самого изображения достаточно: вы бы использовали, FROM neo4j/neo4jесли бы вам нужно было добавить файлы, относящиеся к neo4jвашему конкретному использованию neo4j.

FROM может появляться несколько раз в одном Dockerfile

Не надо: есть предложение все равно убрать эту "фичу" ( issue 13026 )

В выпуске 14412 упоминается:

Использование нескольких FROM- это не совсем функция, а ошибка (ну да ладно, ограничение жесткое, и FROMв Dockerfile есть несколько вариантов использования нескольких ).


Обновление май 2017 г. (18 месяцев спустя) с докером (моби) 17.05-ce .

Многократное FROM может использоваться в одном Dockerfile.
См. « Шаблон построителя против многоэтапных сборок в Docker » ( Алекс Эллис ) и PR 31257, автор Тынис Тийги .

Перед:

Шаблон компоновщика включает использование двух образов Docker - одного для выполнения сборки, а другого для отправки результатов первой сборки без ущерба для цепочки сборки и инструментов в первом образе.

После:

Общий синтаксис включает в себя добавление FROMдополнительных значений времени в вашем Dockerfile - последний из FROMоператоров является окончательным базовым образом. Для копирования артефактов и выходов из промежуточных изображений используйте COPY --from=<base_image_number>.

Первая часть 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 .

Вторая часть того же (!) 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"]  

В результате будут два изображения, одно для построения, другое только с конечным приложением ( намного меньше).

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  
VonC
источник
2
Жалко об удалении нескольких ОТ. мне это кажется наиболее полезным, особенно в отсутствие механизма зависимости. с помощью RPM, например, я могу заявить, что моему пакету нужен другой пакет для запуска, поэтому во время установки все настраивается для меня. реальность такова, что почти все потребует множественных зависимостей, поэтому в отсутствие множества FROM как это должно работать?
ekkis
3
@ekkis, как я уже упоминал в своем предыдущем ответе ( stackoverflow.com/a/33295292/6309 ), вы запускаете свою систему, организуя несколько контейнеров, каждый из которых предоставляет определенную службу, и взаимодействует через --link ( docs.docker.com/ руководство пользователя / dockerlinks /… ).
VonC,
2
@VonC Конечно, в идеальном мире, с новым приложением и понятными шаблонами. Между тем, я ожидаю, что будет больше случаев, когда люди пытаются перенести свои решения в Docker и имеют потребности, которые не решаются сетью, такие как зависимости программного обеспечения, все с использованием совместимой базы, но ИЗ нескольких файлов Docker. Вместо этого лучшее, что я могу выяснить до сих пор, - это разбирать их файлы Docker для создания своих собственных.
ранабба
@rainabba Согласен. Устаревшие монолиты нелегко перенести. Интересные материалы: martinfowler.com/articles/… , treedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC
2

Первый ответ, на мой взгляд, слишком сложен, историчен и малоинформативен.


На самом деле это довольно просто. Docker предоставляет функциональность, называемую многоэтапными сборками, основная идея здесь состоит в том, чтобы:

  • Освободите вас от необходимости вручную удалять то, что вы не хотите, заставив вас занести в белый список то, что вы действительно хотите,
  • Бесплатные ресурсы, которые в противном случае были бы заняты из-за реализации Docker.

Начнем с первого. Очень часто с чем-то вроде Debian вы увидите.

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

Мы можем объяснить все это в терминах вышеизложенного. Вышеупомянутая команда связана вместе, поэтому она представляет собой одно изменение без промежуточных изображений. Если бы это было написано так,

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

Это приведет к появлению еще 3 временных промежуточных изображений. После сокращения до одного образа остается одна проблема: apt-get cleanне очищаются артефакты, использованные при установке. Если сопровождающий Debian включает в свою установку сценарий, который изменяет систему, эта модификация также будет присутствовать в окончательном решении (см. pepperflashplugin-nonfreeЧто- то подобное для примера).

Используя многоступенчатую сборку, вы получаете все преимущества одного измененного действия, но для этого потребуется вручную внести в белый список и скопировать файлы, которые были добавлены во временный образ, с использованием COPY --fromсинтаксиса, описанного здесь. Более того, это отличное решение там, где нет альтернативы (например apt-get clean), и в противном случае у вас будет много ненужных файлов в вашем конечном изображении.

Смотрите также

Эван Кэрролл
источник
спасибо, но я не понимаю, как вы решаете мою проблему. Для меня FROM - это механизм наследования, а наличие нескольких директив означает, что я могу наследовать от нескольких родителей. в своем ответе вы не упоминаете FROM или идею использования упаковки программного обеспечения другими лицами
Эккис
1
Возможно, это путаница. FROMв основном это объявление пространства имен. Квалификатор здесь больше похож на расширение, чем на наследование. Вы можете объявить несколько пространств имен. И каждое из этих пространств имен может расширять одно другое пространство имен. @ekkis Если вам подходит другой ответ, то обязательно придерживайтесь его.
Эван Кэрролл,