Вони мають найбільш сенс для мене прикладом ...
Вивчення шарів власної збірки за допомогою 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 МБ файлу, який ви бачите на остаточному зображенні.