Кілька ВІД - що це означає


112

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

мій перший підхід - оголосити базове зображення для мого зображення, що містить Neo4j. Довідкові документи жодним чином не визначають "базове зображення":

Базове зображення: зображення, яке не має батьків, є базовим зображенням

з якого я читаю, що базове зображення у мене може бути тільки в тому випадку, якщо воно не має базового зображення.

але що таке базове зображення? чи означає це, що якщо я оголошу neo4j / neo4j в директиві FROM, то, коли моє зображення запущено, база даних neo автоматично запускається і буде доступною в контейнері на порт 7474?

читаючи посилання на Докер (див. https://docs.docker.com/reference/builder/#from ), я бачу:

FROM може з'являтися кілька разів у межах одного Dockerfile, щоб створити кілька зображень. Просто занотуйте останній вихідний ідентифікатор зображення, виконуючи команду перед кожною новою командою FROM.

я хочу створити кілька зображень? Здавалося б, я хочу, щоб було єдине зображення, яке містить вміст інших зображень, наприклад, neo4j та node.js

У довідковому посібнику я не знайшов директиви щодо декларації залежностей. чи немає таких залежностей, як у RPM, де для запуску мого зображення контекст виклику повинен спочатку встановити потрібні йому зображення?

Я збентежений...


Примітка. У травні 2017 року у вас є декілька FROMв Dockerfile. Дивіться мою відредаговану відповідь нижче.
VonC

Подивіться, чи знайдете ви мою відповідь чистішою. І якщо так, подумайте про її прийняття.
Еван Керролл

Відповіді:


113

що таке базове зображення?

Набір файлів, плюс EXPOSE'd порти ENTRYPOINTта CMD.
Ви можете додавати файли і створювати нове зображення на основі цього базового зображення, з нового, Dockerfileпочинаючи з FROMдирективи: зображення, згадане після, FROMє "базовим зображенням" для нового зображення.

чи означає це, що якщо я декларую neo4j/neo4jв FROMдирективі, що, коли моє зображення запущено, база даних neo автоматично запуститься і буде доступна в контейнері на порт 7474?

Тільки якщо ви не перезаписуєте CMDта ENTRYPOINT.
Але самого зображення достатньо: ви б використовували a, FROM neo4j/neo4jякби вам додавалося додавати файли, пов'язані neo4jдля вашого конкретного використання neo4j.

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

Не варто: є пропозиція видалити цю "функцію" все одно ( випуск 13026 )

Випуск 14412 згадує:

Використання декількох FROMнасправді не є функцією, але помилка (ну добре, обмеження обмежене, і FROMв Dockerfile мало випадків використання для кількох ).


Оновлення травня 2017 року (18 місяців пізніше), з docker (moby) 17.05-ce .

Кілька ВІД можна використовувати в одному Dockerfile.
Дивіться « Builder шаблон проти багатоступінчастого будує в Докер » (автор Alex Ellis ) і PR 31257 по Тиніс Тійгі .

Перед:

Шаблон конструктора передбачає використання двох зображень Докера - один для виконання збірки, а інший для передачі результатів першого складання без штрафу ланцюга збірки та інструментарію на першому зображенні.

Після:

Загальний синтаксис включає додавання 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 .

Друга частина того ж (!) Докерфайлу:

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  

2
шкода про видалення декількох FROM. мені здається найбільш корисним, особливо за відсутності механізму залежності. Наприклад, з RPM, я можу заявити, що мій пакет потребує іншого пакету для запуску, тому в час установки все налаштовується для мене. реальність полягає в тому, що більшість всього потребуватиме декількох залежностей, тому за відсутності декількох ВІД, як це має працювати?
ekkis

3
@ekkis, як я вже згадував у своїй попередній відповіді ( stackoverflow.com/a/33295292/6309 ), ви запускаєте свою систему, упорядковуючи кілька контейнерів, кожен з яких надає певну послугу, і спілкуєтесь через --link ( docs.docker.com/ userguide / dockerlinks /… ).
VonC

2
@VonC Звичайно, в ідеальному світі, з новим додатком та всіма зрозумілими зразками. Тим часом, я думаю, що існує більше випадків, коли люди намагаються перенести свої рішення в докер і мають потреби, які не вирішуються мережами, такими як програмні залежності, всі використовують сумісну базу, але ВІД декількох Dockerfiles. Натомість найкраще, на що я можу розібратися, - це зламати їх Dockerfiles, щоб створити свою власну.
rainabba

@rainabba Погодився. Спадкові моноліти неможливо легко перенести. Цікаво читає: martinfowler.com/articles/… , threedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC

2

Перша відповідь занадто складна, історична та малоінформативна на мій смак.


Насправді це досить просто. 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;

Це призведе до ще трьох тимчасових проміжних зображень. Зменшивши її до одного зображення, існує одна проблема: apt-get cleanне очищає артефакти, які використовуються при встановленні. Якщо технічний сервіс Debian включить у свій інсталятор скрипт, який модифікує систему, модифікація також буде присутній у остаточному рішенні (див. Щось на зразок pepperflashplugin-nonfreeприкладу цього).

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

Дивитися також


дякую, але я не бачу, як ти вирішуєш мою проблему. для мене FROM - це механізм успадкування, а наявність декількох директив означає, що я можу успадкувати від декількох батьків. у своїй відповіді ви не згадуєте ВІД і концепцію скористатися упаковкою програмного забезпечення іншими
ekkis

1
Можливо, це плутанина. FROMв основному є оголошенням простору імен. Кваліфікатор там більше схожий на розширення, ніж на спадщину. Ви можете оголосити кілька просторів імен. І кожен з цих просторів імен може розширювати ще один простір імен. @ekkis Якщо інша відповідь працює для вас, то, безумовно, дотримуйтесь її.
Еван Керролл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.