Образы 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
Заключение
Образы и слои Docker – это взаимозаменяемые термины.
Слой – это образ, а образ формируется из одного или нескольких слоев.
Основное различие заключается в тегах: образ будет помечен и предназначен для конечных пользователей, в то время как термин “слой” обычно относится к не помеченным промежуточным образам, созданным в процессе сборки.
Они не видны, пока вы не начнете их искать.
Есть еще одна тема, связанная со слоями: запущенные контейнеры добавляют дополнительный записываемый слой поверх своего образа.
Слои, созданные на основе образа контейнера, доступны только для чтения, поэтому модификации файловой системы, производимые контейнером, направлены на его эфемерный записываемый слой.
Записываемый слой отбрасывается, когда контейнер останавливается или удаляется.
- 🐳 Как добавить том к существующему контейнеру Docker
- 🐳 Как обновить образ Docker c новыми изменениями?
- 🐳 Как развернуть стек Portainer внутри кластера Docker Swarm
- 🐳 Как запустить службу Docker при загрузке системы
- 🐳 Как перенести приложение Docker Compose в Kubernetes с помощью Kompose
- 🐳 Как собирать образа контейнеров OCI и Docker с помощью Buildah
- ☸️ Как опубликовать образ Docker в Docker Hub с помощью Podman
- 🐳 Как обновить / добавить файл в Docker образ
- 🐳 Как изменить расположение файла Docker sock?
- 🐳 Топ самых важных команд Docker
- 🐳 Как экспортировать и импортировать образы / контейнеры Docker
- Как работать с контейнерами Docker