Що таке "шари" зображення Докера?


165

Я абсолютно новий для Докера і намагаюся зрозуміти, що таке зображення Докера . Кожне окреме визначення зображення Докера використовує термін "шар", але, схоже, не визначає, що означає " шар" .

З офіційних документів Docker :

Ми вже бачили, що зображення Docker - це шаблони лише для читання, з яких запускаються контейнери Docker. Кожне зображення складається з серії шарів. Docker використовує файлові системи об'єднання для об'єднання цих шарів в єдине зображення. Файлові системи Союзу дозволяють прозоро накладати файли та каталоги окремих файлових систем, відомих як гілки, утворюючи єдину цілісну файлову систему.

Тому я запитую, що таке шар (саме); хтось може навести кілька конкретних прикладів з них? І як ці шари «стискаються разом», щоб сформувати зображення?

Відповіді:


133

Я можу запізнитися, але ось мої 10 копійок (доповнюючи відповідь Ашишджайна):

В основному шар або шар зображення - це зміна зображення або проміжне зображення . Кожна команда вказується ( FROM, RUN, COPYі т.д.) в вашому Dockerfile викликає попереднє зображення зміни, створюючи тим самим новий шар. Ви можете вважати це зміною поетапно, коли ви використовуєте git: Ви додаєте зміни файлу, потім ще одну, потім ще одну ...

Розглянемо наступний Dockerfile:

FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]

Спочатку ми вибираємо початкове зображення:, rails:onbuildяке в свою чергу має багато шарів . Додамо ще один шар поверх нашого вихідного зображення, встановивши змінну оточення RAILS_ENVз ENVкомандою. Потім, ми кажемо докер запустити bundle exec puma(який завантажує сервер рейки). Це ще один шар.

Поняття про шари стане в нагоді під час побудови зображень. Оскільки шари є проміжними зображеннями, якщо ви внесете зміни у свій Dockerfile, docker створить лише той шар, який був змінений, та ті, що були після цього. Це називається кешування шарів.

Більше про це можна прочитати тут .


13
Якщо ви зміните або додасте шар, Docker також створить будь-які шари, які з’являться згодом, оскільки на них можуть вплинути зміни.
Адам

Дякуємо, що пояснили причину концепції шарів, якої немає в інших відповідях.
Seeta Somagani

@David, у наведеному вище прикладі, скільки шарів буде додано? 2? або 1?
Гурав Сінгла

1
@GouravSingla Це повинно бути 2. Зміна ENV також є зміною. Схоже, шар є фіксацією git.
PokerFace

Останнє веб-посилання ( https://labs.ctl.io/caching-docker-images/) порушено. Хтось отримав пропозиції щодо заміни?
Джонні Юта

72

Зображення контейнера докер створюється за допомогою dockerfile . Кожен рядок в dockerfile створить шар. Розглянемо наступний фіктивний приклад:

FROM ubuntu             #This has its own number of layers say "X"
MAINTAINER FOO          #This is one layer 
RUN mkdir /tmp/foo      #This is one layer 
RUN apt-get install vim #This is one layer 

Це створить остаточне зображення, де загальна кількість шарів буде X + 3


32
Поки я не сказав, я вважаю, що це пояснює, як створювати шари, але жодним чином не відповідає на питання про те, що таке шар.
Лассе В. Карлсен

2
Я згоден з @ LasseV.Karlsen, ashishjain. Я не порушував вас і насправді виступаю за те, що ви намагаєтесь допомогти мені (так +1), але для того, щоб я міг дати вам зелений чек, мені потрібно зрозуміти, що таке шар насправді! Ще раз дякую, продовжуйте!
smeeb

3
найкраща відповідь imo. для багатьох з нас, хто переходить на "використання докера", це дає нам суть того, як працюють шари.
dtc

6
"Кожен рядок в dockerfile створить шар" - це мені дуже допомогло знати
akirekadu

2
@akirekadu Це ще не повна історія. Більшість рядків створить шар, але лише інструкції ADD, COPY або RUN створять шари, які збільшують розмір отриманого зображення контейнера. Я сказала більшість рядків, тому що якщо з’єднати команди або уникнути нових рядків із зворотною косою рисою, послідовність ланцюгових команд / біг нових рядків утворюватиме одну команду.
Скотт Сімонтіс

41

Вони мають найбільш сенс для мене прикладом ...

Вивчення шарів власної збірки за допомогою docker diff

Давайте візьмемо надуманий приклад Dockerfile:

FROM busybox

RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one 
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two 
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one 

CMD ls -alh /data

Кожна з цих ddкоманд виводить на диск 1М файл. Дозволяє будувати зображення за допомогою додаткового прапора для збереження тимчасових контейнерів:

docker image build --rm=false .

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

...
Step 2/7 : RUN mkdir /data
 ---> Running in 04c5fa1360b0
 ---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
 ---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
 ---> ea2506fc6e11

Якщо ви запустите а docker diffна кожному з цих ідентифікаторів контейнера, ви побачите, які файли створені в цих контейнерах:

$ docker diff 04c5fa1360b0  # mkdir /data
A /data
$ docker diff f1b72db3bfaa  # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d  # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b  # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea  # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637  # rm /data/one
C /data
D /data/one

Кожен рядок із префіксом а Aдодає файл, Cвказує на зміну існуючого файлу та Dвказує на видалення.

Ось частина TL; DR

Кожна з цих файлових систем контейнерів, що відрізняється вище, переходить в один "шар", який збирається при запуску зображення у вигляді контейнера. Весь файл знаходиться у кожному шарі, коли є додавання чи зміна, тому кожна з цих chmodкоманд, незважаючи на лише зміну біта дозволу, призводить до того, що весь файл буде скопійований у наступний шар. Видалений / дані / один файл все ще знаходиться в попередніх шарах, фактично 3 рази, і буде скопійовано через мережу та збережено на диску, коли ви витягнете зображення.

Розгляд наявних зображень

Ви можете бачити команди, які входять у створення шарів існуючого зображення за допомогою docker historyкоманди. Ви також можете запустити docker image inspectна зображенні та переглянути список шарів у розділі RootFS.

Ось історія наведеного зображення:

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a81cfb93008c        4 seconds ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ls -…   0B
f36265598aef        5 seconds ago       /bin/sh -c rm /data/one                         0B
c79aff033b1c        7 seconds ago       /bin/sh -c chmod -R 0777 /data                  2.1MB
b821dfe9ea38        10 seconds ago      /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
a5602b8e8c69        13 seconds ago      /bin/sh -c chmod -R 0777 /data                  1.05MB
08ec3c707b11        15 seconds ago      /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
ed27832cb6c7        18 seconds ago      /bin/sh -c mkdir /data                          0B
22c2dd5ee85d        2 weeks ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f…   1.16MB

Найновіші шари вказані вгорі. Зауважимо, внизу є два шари, які досить старі. Вони походять із самого зображення зайнятої скриньки. Створюючи одне зображення, ви успадковуєте всі шари зображення, які ви вказали у FROMрядку. Також додаються шари для зміни метаданих зображень, як-от CMDрядок. Вони ледь не займають місця і більше допомагають зберігати записи, які налаштування застосовуються до зображення, яке ви працюєте.

Чому шари?

У шарів є кілька переваг. По-перше, вони незмінні. Після створення цього шару, ідентифікованого хешем sha256, ніколи не зміниться. Ця незмінність дозволяє зображенням безпечно створювати та розщеплювати один одного. Якщо два докерфайли мають однаковий початковий набір ліній і побудовані на одному сервері, вони матимуть однаковий набір початкових шарів, економлячи місце на диску. Це також означає, що якщо ви відновлюєте зображення, лише за останні кілька рядків Dockerfile відбулися зміни, лише ті шари потрібно перебудовувати, а решта можна використовувати повторно з кеша шарів. Це може дуже швидко відновити зображення докера.

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

Зменшення набряку шару

Однією з недоліків шарів є створення зображень, які копіюють файли або передають файли, які видаляються в пізнішому шарі. Рішенням часто є об'єднання декількох команд в одну RUNкоманду. Зокрема, коли ви змінюєте існуючі файли або видаляєте файли, ви хочете, щоб ці дії виконувалися в тій же команді, де вони були створені вперше. Перезапис вищевказаного Dockerfile виглядатиме так:

FROM busybox

RUN mkdir /data \
 && dd if=/dev/zero bs=1024 count=1024 of=/data/one \
 && chmod -R 0777 /data \
 && dd if=/dev/zero bs=1024 count=1024 of=/data/two \
 && chmod -R 0777 /data \
 && rm /data/one

CMD ls -alh /data

А якщо порівнювати отримані зображення:

  • зайнятий: ~ 1 Мб
  • перше зображення: ~ 6 Мб
  • друге зображення: ~ 2 Мб

Просто об’єднавши деякі рядки у надуманому прикладі, ми отримали однаковий вміст у нашому зображенні та зменшили наше зображення з 5 МБ до лише 1 МБ файлу, який ви бачите на остаточному зображенні.


Проходження шарів під час читання файлів тягне за собою накладні витрати, правда? Щоб зберегти цей наклад, чи є сенс поєднувати кілька команд (які потрібно виконувати разом будь-коли) в одному RUN?
СергійКолесніков

@SergiyKolesnikov залежить від того, скільки часу ви хочете передчасно витратити на оптимізацію. Ризик - це витратити години розробника, концерти доданої пропускної здатності та пам’яті, щоб заощадити мілісекунди часу виконання. Як і у багатьох справах, пов'язаних із ефективністю роботи, існують крайнощі, і існує потреба в вимірюванні проблеми, перш ніж докладати зусиль для її вирішення.
BMitch

19

З моменту введення Docker v1.10 із впровадженням вмісту, адресованого вмістом, поняття «шар» стало зовсім іншим. Шари не мають поняття ні про зображення, ні про приналежність до зображення, вони стають лише колекціями файлів і каталогів, якими можна поділитися між зображеннями. Шари та зображення стали відокремленими.

Наприклад, на місцевому рівні , побудоване зображення з базового зображення, скажімо, ubuntu:14.04, то docker historyкоманда дає ланцюжок зображення, але деякі з ідентифікаторів зображень , будуть показані як «не вистачає» , тому що історія збірки більше не завантажуються. І шари, які складають ці зображення, можна знайти через

docker inspect <image_id> | jq -r '.[].RootFS'

Вміст шару зберігається, /var/lib/docker/aufs/diffякщо вибрано драйвер зберігання aufs. Але шари названі випадковим чином генерованим ідентифікатором кешу, схоже, зв’язок між шаром та його ідентифікатором кеша відомий лише Docker Engine лише з міркувань безпеки. Я досі шукаю спосіб дізнатися

  1. Відповідне співвідношення між зображенням та його композиційним шаром
  2. Фактичне розташування та розмір шару на диску

Цей блог дав багато розуміння.


У цьому записі ТА я розмістив досить наївний спосіб відповісти на два запитання, які я розмістив.
Ruifeng Ma

13

Специфікація зображення Per Docker за допомогою проекту Moby :

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

Отже, по суті, шар - це лише набір змін, внесених у файлову систему.


На це мені знадобилося лише пару годин, але з цієї елегантно-простої відповіді я нарешті розумію, що таке шар: "Each [Docker] layer is a set of filesystem changes."(якщо припустити, що це правда.) Я чомусь не зрозумів цього фундаментального моменту, читаючи численні інші документи / блоги / Q + A / тощо, і я підозрюю, що обмеження було їхнім, а не моїм. Незважаючи на це, браво Адітя за те, щоб дістатися до суті справи.
Джонні Юта

12

Я думаю, що офіційний документ дає досить детальне пояснення: https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/ .


(джерело: docker.com )

Зображення складається з багатьох шарів, які зазвичай генеруються з Dockerfile, кожен рядок у Dockerfile створить новий шар, а результат - зображення, яке позначається такою формою repo:tag, як ubuntu:15.04.

Для отримання додаткової інформації, зверніть увагу на читання офіційних документів вище.


2

Дякую @David Castillo за корисну інформацію . Я думаю, що шар - це якась двійкова зміна чи інструкція зображення, яку можна легко виконати або скасувати. Вони робляться поетапно, це те саме, що шар на шарі, тому ми називали "шар".

Для отримання додаткової інформації ви можете побачити "історію докера" так:

docker зображення - дерево
Попередження: '--tree' застаріло, воно буде видалено незабаром. Дивіться використання.
└─511136ea3c5a Віртуальний розмір: 0 B Теги: подряпина: останнє
  └─59e359cb35ef Віртуальний розмір: 85,18 Мб
    └─e8d37d9e3476 Віртуальний розмір: 85,18 MB Теги: debian: wheezy
      └─c58b36b8f285 Віртуальний розмір: 85,18 Мб
        └─90ea6e05b074 Віртуальний розмір: 118,6 Мб
          └─5dc74cffc471 Віртуальний розмір: 118,6 Мб Теги: vim: останнє


5
знайшов нову інформацію про шари : Коли Docker монтує рутові файли, він запускається лише для читання, як у традиційному завантаженні Linux, але тоді, замість зміни файлової системи в режимі читання-запису, він використовує перевагу об'єднання, щоб додати файлова система читання-запису над файловою системою, доступною лише для читання. Насправді може бути декілька файлових систем, доступних лише для читання, складених один над одним. Ми вважаємо кожну з цих файлових систем шаром .
hiproz

1

Моє особисте розуміння полягає в тому, що ми можемо порівняти шар докера з фіксацією github. Для базового зображення (вашої свіжої master repo) ви вносите кілька комітетів, кожна фіксація змінює ваш статус головного, це однаково в докері, кожен шар виконує певну операцію на основі попереднього проміжного шару. А потім цей шар стає новим проміжним шаром до наступного шару.


0

Раніше я думав , що вони схожі файлами зміни на попередніх шарах. Прочитавши тут деякі відповіді, я не був так впевнений; вони описуються як набори змін у файловій системі . Я написав кілька Dockerfiles, щоб показати, що вони більше схожі на розходження, тобто вони дійсно залежать від попередніх шарів.

Враховуючи ці два докерфіли

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three

і

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one

можна було б очікувати того ж набору шарів, якби вони просто стосувалися змін у файловій системі, але це не так:

$ docker history img_1
IMAGE               CREATED             CREATED BY                                      SIZE
30daa166a9c5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
4467d16e79f5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
c299561fd031        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

і

$ docker history img_2
IMAGE               CREATED             CREATED BY                                      SIZE
f55c91305f8c        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
29b3b627c76f        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
18360be603aa        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

Ви можете бачити, як, навіть якщо зміни у файловій системі однакові в обох випадках, порядок має значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.