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

DockerBeginner
Практиковаться сейчас

Введение

В рамках этого практикума мы изучим образы Docker — основу для создания и запуска контейнеров. Вы научитесь скачивать образы из Docker Hub, запускать контейнеры на базе различных версий, просматривать список установленных образов и удалять ненужные. Мы также разберем концепцию слоев образа, научимся искать образы в реестре и выполнять базовое тегирование. Этот практический опыт даст вам необходимые навыки для эффективной работы с Docker. Не беспокойтесь, если вы новичок — мы сопроводим вас на каждом этапе подробными пояснениями.

Получение образов из Docker Hub

Docker Hub — это публичный репозиторий образов Docker, во многом похожий на GitHub для программного кода. Здесь можно найти готовые образы для большинства популярных приложений и операционных систем. Начнем с получения (скачивания) официального образа Nginx.

Откройте терминал в вашей системе. Вы увидите приглашение командной строки, похожее на это:

labex:project/ $

Теперь скачаем образ Nginx. Введите следующую команду и нажмите Enter:

docker pull nginx

Эта команда приказывает Docker загрузить последнюю версию образа Nginx из Docker Hub. Вы увидите вывод, похожий на этот:

Using default tag: latest
latest: Pulling from library/nginx
5040bd298390: Pull complete
d7a91cdb22f0: Pull complete
9cac4850e5df: Pull complete
Digest: sha256:33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303
Status: Downloaded newer image for nginx:latest

Разберем, что здесь произошло:

  1. "Using default tag: latest" — если вы не указываете конкретную версию, Docker по умолчанию выбирает последнюю доступную версию (latest).
  2. Следующие строки показывают процесс загрузки различных «слоев» образа. Каждый слой представляет собой набор изменений в файловой системе.
  3. "Digest" — это уникальный идентификатор именно этой версии образа.
  4. Последняя строка подтверждает, что образ успешно загружен.

Теперь, когда образ скачан, проверим его наличие в системе. Мы можем сделать это, выведя список всех локальных образов:

docker images

Вы увидите таблицу, похожую на эту:

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    605c77e624dd   2 weeks ago    141MB

Здесь указано:

  • REPOSITORY: Название образа (nginx).
  • TAG: Тег или версия образа (latest).
  • IMAGE ID: Уникальный идентификатор образа.
  • CREATED: Когда была создана эта версия образа.
  • SIZE: Объем дискового пространства, который занимает образ.

Не переживайте, если цифры будут отличаться — главное, чтобы в списке присутствовала запись для nginx.

Если вам интересно, какие еще образы есть в системе, вы можете увидеть записи вроде "jenkins/jenkins" или "gcr.io/k8s-minikube/kicbase". Это предустановленные образы, которые мы не будем использовать в данном уроке.

Запуск различных версий образа

Docker позволяет запускать конкретные версии образа с помощью тегов. Теги работают как псевдонимы для определенных версий. Рассмотрим это на примере образа Python.

Сначала скачаем последнюю версию Python:

docker pull python

Вы увидите процесс загрузки, аналогичный тому, что был с Nginx. Это скачивается самая свежая версия Python.

Теперь скачаем конкретную версию, например, 3.7:

docker pull python:3.7

Обратите внимание, что мы добавили :3.7 после python. Это указывает Docker на необходимость загрузки именно версии 3.7, а не последней.

Выведем список образов Python, чтобы увидеть разные версии:

docker images python

Вывод будет примерно таким:

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
python       3.7       1f1a7b570fbd   2 weeks ago    907MB
python       latest    98ccd1643c71   2 weeks ago    920MB

Теперь у нас есть два образа Python: один с тегом latest (который может быть версией 3.9 или 3.10 в зависимости от текущего момента), и другой с тегом 3.7.

Запустим контейнеры на базе этих версий, чтобы увидеть разницу:

docker run --rm python:latest python --version

Эта команда выполняет несколько действий:

  1. docker run создает и запускает новый контейнер.
  2. --rm приказывает Docker удалить контейнер сразу после его остановки.
  3. python:latest указывает, какой образ использовать.
  4. python --version — это команда, которая выполнится внутри контейнера.

В выводе вы увидите актуальную версию Python.

Теперь проделаем то же самое для Python 3.7:

docker run python:3.7 python --version

На этот раз в выводе должно появиться Python 3.7.x.

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

Просмотр списка и удаление образов

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

Начнем с просмотра всех образов в системе:

docker images

Вы увидите список всех скачанных образов, включая Nginx и Python.

Допустим, мы хотим удалить образ Python 3.7, чтобы освободить место. Для этого используется команда docker rmi (rmi означает "remove image"):

docker rmi python:3.7

Если команда выполнится успешно, вы увидите:

Untagged: python:3.7
Untagged: python@sha256:1f93c63...
Deleted: sha256:1f1a7b57...
Deleted: sha256:8c75ecde...
...

Однако вы можете столкнуться с ошибкой:

Error response from daemon: conflict: unable to remove repository reference "python:3.7" (must force) - container <container_id> is using its referenced image <image_id>

Эта ошибка возникает, если существует контейнер (запущенный или остановленный), созданный на базе этого образа. Docker запрещает удалять используемые образы для сохранения целостности системы.

Чтобы решить эту проблему, сначала нужно удалить все контейнеры, использующие этот образ. Посмотрим список всех контейнеров (включая остановленные):

docker ps -a

Найдите контейнеры, созданные из python:3.7. Если они есть, удалите их командой docker rm:

docker rm <container_id>

Замените <container_id> на реальный ID контейнера.

Теперь попробуйте снова удалить образ:

docker rmi python:3.7

Теперь всё должно пройти успешно.

Проверим, что образ удален, снова просмотрев список образов Python:

docker images python

Образ Python 3.7 должен исчезнуть из списка.

Понимание слоев образа

Образы Docker строятся на основе многослойной файловой системы. Каждый слой представляет собой набор изменений. Такой подход позволяет Docker эффективно использовать дисковое пространство и сетевой трафик. Давайте изучим это подробнее.

Сначала проверим слои образа Nginx, который мы скачали ранее:

docker inspect --format='{{.RootFS.Layers}}' nginx

Вы увидите нечто подобное:

[sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8 sha256:b5357ce95c68acd9c9672ec76e3b2a2ff3f8f62a2bcc1866b8811572f4d409af]

Каждая из этих длинных строк (хеши SHA256) представляет собой слой. Каждый слой соответствует определенной команде в Dockerfile, который использовался для сборки образа.

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

nano Dockerfile

Добавьте в него следующее содержимое:

FROM nginx
RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html

Этот Dockerfile делает две вещи:

  1. Берет за основу образ Nginx (FROM nginx).
  2. Добавляет в образ новый файл (RUN echo...).

Сохраните файл и выйдите (в nano: Ctrl+X, затем Y, затем Enter).

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

docker build -t custom-nginx .

Пример вывода:

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx
 ---> 5ef79149e0ec
Step 2/2 : RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html
 ---> Running in 2fa43e649234
Removing intermediate container 2fa43e649234
 ---> 73b62663b5c3
Successfully built 73b62663b5c3
Successfully tagged custom-nginx:latest

Эта команда создает новый образ на основе нашего Dockerfile и присваивает ему имя custom-nginx. Точка . в конце указывает Docker искать Dockerfile в текущей папке.

Теперь проверим слои нашего нового образа:

docker inspect --format='{{.RootFS.Layers}}' custom-nginx

Вы заметите, что у этого образа на один слой больше, чем у оригинального Nginx. Этот дополнительный слой содержит изменения, внесенные нашей командой RUN.

Понимание слоев важно, потому что:

  1. Слои кэшируются, что ускоряет сборку похожих образов.
  2. Слои разделяются между разными образами, экономя место на диске.
  3. При передаче образов по сети пересылаются только измененные слои.

Поиск образов в Docker Hub

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

Попробуем найти образы, связанные с Nginx:

docker search nginx

Вы получите список репозиториев. Вывод содержит несколько колонок:

  • NAME: Название образа.
  • DESCRIPTION: Краткое описание.
  • STARS: Количество «звезд» (популярность образа).
  • OFFICIAL: Является ли образ официальным (поддерживается командой Docker).
  • AUTOMATED: Собирается ли образ автоматически из репозитория GitHub.

Пример вывода:

NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15763     [OK]
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker c...   2088                 [OK]
...

Официальный образ Nginx обычно находится в самом верху.

Теперь попробуем найти конкретную версию Python:

docker search python:3.8

Вы заметите, что поиск работает не совсем так, как ожидалось. docker search не поддерживает поиск по тегам (например, 3.8). Вместо этого он ищет строку "python:3.8" в названии или описании.

Чтобы найти конкретные версии, лучше:

  1. Искать общее имя образа (например, docker search python).
  2. Зайти на сайт Docker Hub для получения подробной информации о тегах.
  3. Скачать образ через docker pull и изучить его локально.

Помните, что docker search — это быстрый способ найти нужный софт, но для выбора конкретной версии удобнее использовать веб-интерфейс Docker Hub.

Сохранение и загрузка образов

Docker позволяет сохранять образы в виде tar-архивов и загружать их позже. Это полезно для переноса образов между системами без использования реестра или для создания резервных копий.

Сохраним образ Nginx в файл:

docker save nginx > nginx.tar

Эта команда сохраняет образ Nginx в файл nginx.tar в текущем каталоге. Символ > используется для перенаправления вывода команды в файл.

Проверьте создание файла, просмотрев содержимое каталога:

ls -lh nginx.tar

Вы увидите файл nginx.tar и его размер (обычно более 100 МБ).

Теперь удалим образ Nginx из системы, чтобы имитировать перенос на другой компьютер:

docker rmi nginx

Убедитесь, что образа больше нет:

docker images nginx

Список должен быть пустым.

Теперь загрузим образ обратно из tar-файла:

docker load < nginx.tar

Символ < используется для передачи содержимого файла nginx.tar на вход команде docker load.

После завершения проверьте наличие образа:

docker images nginx

Образ Nginx снова появится в списке, в том же виде, что и до удаления.

Этот процесс незаменим, когда нужно:

  • Перенести образы на сервер без доступа к интернету.
  • Сделать бэкап конкретной версии образа.
  • Передать кастомный образ коллеге напрямую.

Основы тегирования образов

Тегирование — это способ создания псевдонимов для ваших образов Docker. Оно часто используется для версионирования и организации структуры образов.

Создадим новый тег для нашего образа Nginx:

docker tag nginx:latest my-nginx:v1

Эта команда создает новый тег my-nginx:v1, который указывает на тот же самый образ, что и nginx:latest. Разберем части команды:

  • nginx:latest — исходный образ и его тег.
  • my-nginx — новое имя образа, которое мы создаем.
  • v1 — новый тег, который мы присваиваем.

Теперь посмотрите список образов:

docker images

Вы увидите и nginx:latest, и my-nginx:v1. Обратите внимание, что у них одинаковый Image ID — это подтверждает, что физически это один и тот же образ, просто под разными именами.

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

docker run -d --name my-nginx-container my-nginx:v1

Разбор параметров:

  • -d запускает контейнер в фоновом режиме (detached mode).
  • --name my-nginx-container задает имя нашему новому контейнеру.
  • my-nginx:v1 — образ и тег, используемые для запуска.

Проверьте, что контейнер запущен:

docker ps

Вы увидите его в списке активных контейнеров.

Тегирование полезно по нескольким причинам:

  1. Контроль версий: можно помечать образы номерами версий (v1, v2 и т.д.).
  2. Разделение сред: можно тегировать образы для разных окружений (dev, staging, prod).
  3. Читаемость: кастомные теги помогают понять назначение образа.

Помните: теги — это просто ссылки. Они не создают копию данных образа, а лишь добавляют новое имя, указывающее на существующие данные.

Резюме

В ходе этого практикума мы изучили различные аспекты работы с образами Docker. Мы научились:

  1. Скачивать образы из Docker Hub.
  2. Запускать контейнеры на базе различных версий.
  3. Просматривать список и удалять образы.
  4. Понимать структуру слоев образа.
  5. Искать образы в Docker Hub через терминал.
  6. Сохранять и загружать образы из файлов.
  7. Выполнять базовое тегирование.

Эти навыки являются фундаментом для эффективного управления Docker-инфраструктурой в ваших проектах. По мере погружения в мир Docker эти операции станут для вас повседневными при сборке и развертывании контейнеризированных приложений.

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

Продолжайте практиковаться и изучать новые образы. Чем больше вы работаете с Docker, тем увереннее будете себя чувствовать. Удачи в обучении!