#️⃣Docker | Docker Compose
Описание базовых команд Docker и примеры использования Docker Compose
1. Контейнеризация vs виртуализация
Контейнеризация и виртуализация — это технологии, которые используются для изоляции и управления программным обеспечением, но они имеют разные подходы и области применения:
Принцип работы:
Виртуализация использует гипервизор для создания и управления виртуальными машинами (VM). Каждая виртуальная машина включает в себя гостевую операционную систему и все необходимые для её работы компоненты (ядро, драйверы и т.д.). Это создает полноценную среду с изолированными операционными системами.
Контейнеризация использует ядро операционной системы хоста и изолирует приложения друг от друга через контейнеры. Контейнеры делят общее ядро, но имеют собственные библиотеки и окружение выполнения, что делает их легковеснее по сравнению с виртуальными машинами.
Изоляция:
В виртуальных машинах изоляция достигается через аппаратную виртуализацию и гипервизор, что предоставляет полную виртуальную машину с отдельной операционной системой.
В контейнерах изоляция достигается через механизм именованных пространств (namespaces) и контрольные группы (cgroups), которые предоставляют изоляцию процессов, но делят ядро ОС.
Ресурсы и производительность:
Виртуальные машины требуют больше ресурсов, так как каждая VM включает полную копию операционной системы.
Контейнеры используют меньше ресурсов, так как они не требуют отдельной операционной системы и работают на том же ядре, что и хостовая ОС.
Управление и масштабирование:
Виртуальные машины обычно медленнее запускаются и требуют больше времени на настройку и управление.
Контейнеры запускаются значительно быстрее, что делает их более удобными для масштабирования и разработки микросервисов.
Применение:
Виртуализация часто используется для создания изолированных сред для разработки, тестирования, и развертывания серверных приложений.
Контейнеризация чаще используется для разработки и развертывания приложений, особенно для микросервисной архитектуры, поскольку она упрощает CI/CD процессы и автоматическое масштабирование.
В итоге, выбор между контейнеризацией и виртуализацией зависит от конкретных требований к производительности, изоляции и управлению приложениями.
2. Объекты docker
Docker использует несколько типов объектов для управления контейнерами и приложениями. Основные объекты Docker включают:
Образы (Images):
Описание: Шаблоны только для чтения, из которых создаются контейнеры. Они включают в себя все необходимое для работы приложения: код, среды выполнения, библиотеки и зависимости.
Пример использования:
docker pull nginx
,docker build -t myapp .
Контейнеры (Containers):
Описание: Работающие экземпляры образов. Контейнеры представляют собой изолированные процессы на одном и том же ядре ОС.
Пример использования:
docker run -d -p 80:80 nginx
Сети (Networks):
Описание: Способ для контейнеров общаться друг с другом. Docker поддерживает различные драйверы сетей (bridge, host, overlay и др.).
Пример использования:
docker network create mynetwork
,docker network connect mynetwork mycontainer
Тома (Volumes):
Описание: Специализированные директории для постоянного хранения данных контейнеров. Они позволяют сохранять данные независимо от жизненного цикла контейнера.
Пример использования:
docker volume create myvolume
,docker run -v myvolume:/data myapp
Сервисы (Services):
Описание: Объекты Docker Swarm, которые позволяют масштабировать контейнеры на нескольких хостах. Они являются основной частью Docker для оркестрации контейнеров.
Пример использования:
docker service create --name myservice --replicas 3 nginx
Стэки (Stacks):
Описание: Набор связанных служб, которые можно развернуть с использованием Docker Compose. Они позволяют управлять многоконтейнерными приложениями.
Пример использования:
docker stack deploy -c docker-compose.yml mystack
Dockerfile:
Описание: Скрипт, содержащий инструкции для создания Docker образа. Используется для автоматизации процесса сборки образов.
Пример использования:
docker build -t myapp .
3. Базовые команды docker
Чтобы создать docker-контейнер в простейшем виде, необходимо сделать следующее:
Для примера запускаем контейнер с образом nginx версии 1.25:
Если используется Docker Desktop:
Результат создания контейнера:
Вместо Docker Desktop созданный контейнер можно посмотреть через терминал:
Как видно на скриншоте выше, контейнер принимает подключения с любых IP-адресов (0.0.0.0:9000) и перенаправляет подключения на порт 80 внутри контейнера. Автоматически контейнеру присваивается идентификатор (9d10d4ac19fa) и имя (gracious_diffie). Помимо этого, в том терминале, где мы запустили контейнер, мы не может вводить команды на хостовой ОС. Исправим имя контейнера (через указание опции --name) и возможность ввода команд после запуска (через опцию -d). Создаем новый контейнер:
Вновь проверим созданный контейнер:
Теперь остановим работу первого контейнера и удалим его:
Теперь попробуем запустить команду внутри контейнера:
или
Также можно использовать вместо `docker exec -it`, например, `docker run`, но это создаст новый контейнер!
А как получить shell, чтобы вводить команды свободно, как в обычном терминале? Крайне просто! Нужно просто запустить оболочку:
4. Создание контейнера с использованием Dockerfile
Теперь создадим свой кастомный Docker-образ с использованием Dockerfile (простой проект на flask). Структура нашего проекта:
Теперь создаем docker-образ:
И запустим контейнер:
Таким образом, наш мини-проект будет запускаться в изолированной среде, собираться сам, подтягивая все необходимые зависимости из `requirements.txt`
5. Развертывание образов с использованием docker-compose, добавление БД к проекту
Теперь реализуем развертывание контейнера с использованием docker-compose. Переделаем структуру проекта:
docker-compose.yaml выглядит следующим образом:
Производим запуск следующей командой, благодаря которой docker сам создаст все образы и запустит контейнеры (запуск из директории flask_docker_project):
Контейнеры:
Образы:
Тома:
Из интересного - порты:
Доступ к созданному нами веб-серверу можно получить двумя способами:
Локально (127.0.0.1 или localhost) на порте 5000
Отовсюду (0.0.0.0) на порте 5001
В примере созданы два порта, но можно оставить один из двух вариантов в зависимости от ситуации
Теперь добавим к нашему проекту подключение к БД. Для начала обновим requirements.txt:
Обновим исходный код:
Сделаем ребилд с помощью следующей команды:
И вновь запустим проект:
Проверяем, могут ли обменяться информацией два созданный контейнера:
Как видим, запрос на версию БД успешно реализован. Хочется отметить один момент в исходном коде веб-сервера:
Обращаем внимание на `@db`. Это указание на имя контейнера. Почему это работает? В концепции Docker, при использовании Docker Compose, сервисы могут взаимодействовать друг с другом по именам сервисов, указанным в docker-compose.yaml
. Это возможно благодаря встроенной сети Docker Compose, которая создает виртуальную сеть и DNS для всех сервисов, указанных в файле конфигурации.
Также можно обратить внимание на то, что логин и пароль указаны в явном виде, но мы можем поменять файл docker-compose.yaml, чтобы получить логин и пароль из переменных окружений.
Заменим переменные окружения:
Также изменим немного исходный код веб-сервера:
Вновь сделаем ребилд и запустим контейнеры:
Как итог, все также работает:
Кстати, чтобы зайти в БД, можно выполнить команду:
6. Другие полезные команды
Last updated