Документация

Работа с образами в Docker

Образы в Docker

Docker предоставляет средства для запуска приложений в изолированных окружениях, контейнерах. Изоляция происходит на уровне файловой системы, взаимодействия запущенных процессов и сетевого взаимодействия. Контейнеры создаются из образов.

Образы в Docker составлены из слоёв файловых систем находящихся один над другим. В основе слоёв находится файловая система для загрузки bootfs. Она используется на начальных этапах запуска контейнера, после чего заменяется содержимым изначального образа initrd. Это очень схоже с обычным процессом загрузки ядра ОС.

После загрузки из корневой файловой системы следующие слои подключаются с использованием подхода union mount. Все подключение файловые системы подключаются в режиме только для чтения. То есть контейнер не может внести в них никакие изменения.

С точки зрения пользователя файловая система является единой, он не видит «склеек», которые возникают в результате подключения слоёв. Однако пользователю доступны данные из всех слоёв.

В терминологии Docker каждый такой слой называется образом. Образы могут находиться один над другим. Образ, который находится ниже, называется родительским образом. Можно продвигаться «вниз» по стеку из слоёв, чтобы достигнуть его начала. Базовым образом называется образ, который находится в основании данного стека.

При запуске контейнера поверх всех слоёв в формате «только для чтения» Docker создаёт отдельный слой для контейнера в режиме чтения-записи. Любые действия с файловой системой, которые выполняются внутри контейнера, сохраняются в данном созданном слое. Собственно он и составляет содержимое контейнера, построенного на базе образа.

Краткий обзор команд по работе с образами

  • docker image build, docker build — создать новый образ с использованием файла-описания Dockerfile.
  • docker image history — посмотреть историю создания образа, отобразить действия по созданию слоёв
  • docker image import, docker import — создать новый базовый образ из файлового архива
  • docker image inspect, docker inspect — получить детальную информацию об одном или нескольких образах
  • docker image load, docker load — загрузить образ из стандартного потока ввода
  • docker image ls, docker images — отобразить информацию о доступных для работы образов
  • docker image prune — удалить ненужные или неиспользуемые сейчас образ
  • docker image pull, docker pull — скачать образы из удалённого реестр в локальное хранилище
  • docker image push, docker push — загрузить образы из локального хранилища в удалённый реестр
  • docker image rm, docker rmi — удалить один или несколько образов
  • docker image save, docker save — выгрузить образы в виде tar-архива или на стандартный поток вывода
  • docker image tag, docker tag — создать новое название (или присвоить тег) существующему образу

Как можно легко увидеть, большинство команд docker image также доступны как команды верхнего уровня. Это связано с тем, что в рамках Docker уделяется серьёзное внимание работе с образами, одна из ключевых задач данного инструментария.

Работа с реестром Docker Hub

В любой момент времени мы можем посмотреть на список локально доступных образов с помощью команды docker image ls:

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian              buster              0d587dfbc4f4        3 weeks ago         114MB

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

Рассмотрим следующий пример:

$ docker container run --rm -it alpine sh
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
540db60ca938: Pull complete
Digest: sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f
Status: Downloaded newer image for alpine:latest
/ # exit
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              latest              6dbb9cc54074        2 weeks ago         5.61MB
debian              buster              0d587dfbc4f4        3 weeks ago         114MB

Мы попытались запустить контейнер на базе alpine:latest. Данный образ локально не был доступен, поэтому он был скачан с Docker Hub и теперь доступен среди локальных образов.

Создание образов с помощью docker container commit

Создадим новый образ на основании debian:buster, который включает в себя приложение ncdu:

$ docker container run -it debian:buster bash
root@d1bdfc83b9d2:/# ncdu
bash: ncdu: command not found
root@d1bdfc83b9d2:/# apt update && apt install ncdu && apt-get clean
…
Setting up ncdu (1.13-1+b1) ...
root@d1bdfc83b9d2:/# exit
exit

Теперь в списке контейнеров есть новый stupefied_feistel:

$ docker container ls --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
d1bdfc83b9d2        debian:buster       "bash"              2 minutes ago       Exited (0) About a minute ago                       stupefied_feistel

Создадим новый образ на основе данного контейнера с помощью команды docker container commit:

$ docker container commit stupefied_feistel debian-ncdu:latest
sha256:bc2602abd3e6e0de8b7f2bd3bcc80457188bc76b2b91437f333498e9f3fd1b9c
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian-ncdu         latest              bc2602abd3e6        21 seconds ago      133MB
alpine              latest              6dbb9cc54074        2 weeks ago         5.61MB
debian              buster              0d587dfbc4f4        3 weeks ago         114MB

Теперь в списке локально доступных образов появился debian-ncdu:latest. Можно создать контейнер на основе данного образа и запустить приложение:

$ docker container run -it --rm debian-ncdu ncdu
…
$ echo $?
0

Теперь на основании образа debian-ncdu:latest можно запустить множество контейнеров.

После создания образа контейнер stupefied_feistel можно удалить, так как он более не нужен:

$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
d1bdfc83b9d2b79a84f90b943fab6621ccbf28cc4c7a111bf0ef7af49308c892

Total reclaimed space: 18.6MB

Задания

Задача № 1: Работа с локальными образами

  1. Отобразите список локально доступных образов. Сохраните данный вывод, чтобы он был доступен позднее.
  2. Запустите контейнер с интерактивным командным интерпретатором bash на основании доступного локально образа debian:buster. Настройте контейнер на автоматическое удаление после завершения работы. Обратите внимание: было ли произведено скачивание нового образа или нет.
  3. Завершите работу интерактивной оболочки.
  4. Запустите контейнер с интерактивным командным интерпретатором sh на основании образа alpine:latest. Настройте контейнер на автоматическое удаление после завершения работы. Обратите внимание: было ли произведено скачивание нового образа или нет.
  5. Завершите работу интерактивной оболочки.
  6. Отобразите список локально доступных образов. Сравните с выводом команды в пункте № 1.

Задача № 2: Получение образов с Hub Docker

  1. Отобразите список локально доступных образов.
  2. Получите образ ubuntu:21.04 с помощью команды docker image pull.
  3. Отобразите список локально доступных образов.
  4. Запустите контейнер с интерактивной оболочной bash. Настройте контейнер на автоматическое удаление после завершения работы.
  5. Удостоверьтесь, что контейнер запущен на основе образа Ubuntu 21.04.
  6. Завершите работу интерактивной оболочки.

Задача № 3: Удаление локальных образов

  1. Отобразите список локально доступных образов, включая «висячие».
  2. Удалите все образы, которые не имеют тегов с помощью docker image prune.
  3. Отобразите список локально доступных образов. Какие из них были удалены?
  4. Удалите образ ubuntu:21.04, который был скачан на предыдущем шаге. Выполните это с помощью команды docker image rm.
  5. Отобразите список локально доступных образов. Был ли удалён данный образ?

Задача № 4: Управление локальными образами

  1. Отобразите размер хранилища данных Docker: /var/lib/docker.
  2. Загрузите образ fedora:latest с Docker Hub.
  3. Отобразите размер хранилища данных Docker.
  4. Запустите интерактивный контейнер с bash на основе образа Docker Hub. Не настраивайте контейнер на автоматическое удаление.
  5. Отобразите размер хранилища данных Docker.
  6. Установите в контейнер приложения nginx и tmux: dnf install nginx tmux.
  7. Завершите работу интерактивного интерпретатора.
  8. Отобразите размер хранилища данных Docker.
  9. Удалите контейнер, в котором производилась установка приложений.
  10. Отобразите размер хранилища данных Docker.
  11. Удалите образ fedora:latest.
  12. Отобразите размер хранилища данных Docker.

Задача № 5: Просмотр истории образов

  1. Посмотрите на историю создания образов debian:buster и alpine:latest с помощью команд docker image history и docker image inspect.
  2. Какую информацию можно получить из работы данных команд? Какая из них «лучше»?

Задача № 6: Создание собственных образов

  1. Следуя шагам из документации создайте собственный образ на основании debian:buster, который будет включать в себя интерпретатор языка Ruby. Установку интерпретатора следует выполнить из репозитория.
  2. Отобразите список доступных образов.
  3. Сравните размер базового образа и нового образа.
  4. Отобразите историю и детальную информацию о новом образе. Сравните историю с историей базовых образов.
  5. Удостоверьтесь, что контейнер для сборки образа был удалён.

Задача № 7: Создание нового тега для образа

  1. Отобразите список локально доступных образов.
  2. Посмотрите на размер хранилища данных Docker: /var/lib/docker
  3. Выдайте новый тег debian-ruby:test-tag-001 к образу, созданному на предыдущем шаге.
  4. Отобразите список локально доступных образов.
  5. Посмотрите на историю и детали образа debian-ruby:test-tag-001, сравните их с оригинальным образом.
  6. Посмотрите на размер хранилища данных Docker: изменился ли он?