🐳 Что такое слои образа Docker?

by itisgood

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

Но что на самом деле представляет собой слой и чем он отличается от полного образа?

В этой статье вы узнаете, как различать эти два понятия и почему эта разница имеет значение.

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

Что такое образ?

Образ” Docker ведет себя как шаблон, на основе которого могут быть созданы последовательные контейнеры.

Если бы Docker был традиционной виртуальной машиной, образ можно было бы сравнить с ISO, используемым для установки виртуальной машины.

Это не совсем корректное сравнение, поскольку Docker отличается от виртуальных машин как по концепции, так и по реализации, но, тем не менее, это полезная отправная точка.

Образы определяют начальное состояние файловой системы новых контейнеров.

Они собирают исходный код вашего приложения и его зависимости в автономный пакет, готовый к использованию в среде выполнения контейнера.

Внутри образа содержимое файловой системы представлено в виде нескольких независимых слоев.

Что такое слои?

Слои – это результат способа создания образов Docker.

Каждый шаг в Docker-файле создает новый “слой”, который, по сути, представляет собой дифф изменений файловой системы с момента последнего шага.

Инструкции метаданных, такие как LABEL и MAINTAINER, не создают слоев, поскольку они не влияют на файловую систему.

Этот образ имеет две инструкции (COPY и RUN), поэтому он создаст два слоя:

FROM ubuntu:latest
COPY foo.txt /foo.txt
RUN date > /built-on.txt

Первый шаг копирует foo.txt в новый слой, основанный на образе ubuntu:latest.

На втором шаге выполняется команда date и ее вывод передается в файл.

Создается второй слой, основанный на предыдущем.

Создайте файл foo.txt в рабочем каталоге:

$ echo "Hello World" > foo.txt

Теперь соберем образец образа:

$ docker build . -t demo:latest
Sending build context to Docker daemon   2.56kB
Step 1/3 : FROM ubuntu:latest
 ---> df5de72bdb3b
Step 2/3 : COPY foo.txt /foo.txt
 ---> 4932aede6a15
Step 3/3 : RUN date > /built-on.txt
 ---> Running in 91d260fc2e68
Removing intermediate container 91d260fc2e68
 ---> 6f653c6a60fa
Successfully built 6f653c6a60fa
Successfully tagged foo:latest

На каждом этапе сборки передается идентификатор созданного слоя.

Слой последнего шага становится финальным образом, поэтому он получает метку foo:latest.

Эта последовательность показывает, что слои являются действительными образами Docker.

Хотя термин “слой” обычно не используется для обозначения образа с тегом, все образы с тегом технически являются просто слоями с присвоенным идентификатором.

Вы можете запустить контейнер из образа промежуточного слоя:

$ docker run -it 4932aede6a15 sh
# cat /foo.txt
Hello World
# cat /built-on.txt
cat: /built-on.txt: No such file or directory

Этот пример запускает контейнер из слоя, созданного на втором шаге сборки. foo.txt доступен в контейнере, но built-on.txt не существует, поскольку он не добавлен до третьего шага.

Этот файл доступен только в файловых системах последующих слоев.

docker pull php:8.0-apache
8.0-apache: Pulling from library/php
7a6db449b51b: Already exists 
ad2afdb99a9d: Already exists 
dbc5aa907229: Already exists 
82f252ab4ad1: Already exists 
bf5b34fc9894: Already exists 
6161651d3d95: Already exists 
cf2adf296ef1: Already exists 
f0d7c5221e44: Pull complete 
f647198f6316: Pull complete 
c37afe1da4e5: Pull complete 
09c93531cbca: Pull complete 
fef371007dd3: Pull complete 
52043dbb1c06: Pull complete 
Digest: sha256:429889e8f9eac0a806a005b0728a004303b0d49d77b09496d39158707abd6280
Status: Downloaded newer image for php:8.0-apache
docker.io/library/php:8.0-apache

Другие слои уже присутствовали на хосте Docker, поэтому их можно использовать повторно.

Это повышает производительность и позволяет не тратить пропускную способность сети.

Проверка слоев образа

Вы можете просмотреть список слоев в образе, выполнив команду docker image history.

Каждый слой отображает ID созданного образа и инструкцию Dockerfile, вызвавшую изменение.

Вы также можете увидеть общий размер содержимого в слое.

$ docker image history 
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
6f653c6a60fa   4 minutes ago   /bin/sh -c date > /built-on.txt                 29B       
f8420d1a96f3   4 minutes ago   /bin/sh -c #(nop) COPY file:a5630a7506b26a37...   0B        
df5de72bdb3b   4 weeks ago     /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      4 weeks ago     /bin/sh -c #(nop) ADD file:396eeb65c8d737180...   77.8MB    
Последний слой отображается как <missing>, поскольку он относится к слою в базовом образе ubuntu:latest.
Он недоступен локально, поскольку во время сборки сносится только последний слой базового образа (df5de72bdb3b).
Нет необходимости самостоятельно извлекать все промежуточные слои, когда вы хотите использовать определенный образ.

Заключение

Образы и слои Docker – это взаимозаменяемые термины.

Слой – это образ, а образ формируется из одного или нескольких слоев.

Основное различие заключается в тегах: образ будет помечен и предназначен для конечных пользователей, в то время как термин “слой” обычно относится к не помеченным промежуточным образам, созданным в процессе сборки.

Они не видны, пока вы не начнете их искать.

Есть еще одна тема, связанная со слоями: запущенные контейнеры добавляют дополнительный записываемый слой поверх своего образа.

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

Записываемый слой отбрасывается, когда контейнер останавливается или удаляется.

см. также:

 

You may also like

Leave a Comment