Page cover

#️⃣Docker | Docker Compose

Описание базовых команд Docker и примеры использования Docker Compose

1. Контейнеризация vs виртуализация

Контейнеризация и виртуализация — это технологии, которые используются для изоляции и управления программным обеспечением, но они имеют разные подходы и области применения:

  1. Принцип работы:

    • Виртуализация использует гипервизор для создания и управления виртуальными машинами (VM). Каждая виртуальная машина включает в себя гостевую операционную систему и все необходимые для её работы компоненты (ядро, драйверы и т.д.). Это создает полноценную среду с изолированными операционными системами.

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

  2. Изоляция:

    • В виртуальных машинах изоляция достигается через аппаратную виртуализацию и гипервизор, что предоставляет полную виртуальную машину с отдельной операционной системой.

    • В контейнерах изоляция достигается через механизм именованных пространств (namespaces) и контрольные группы (cgroups), которые предоставляют изоляцию процессов, но делят ядро ОС.

  3. Ресурсы и производительность:

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

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

  4. Управление и масштабирование:

    • Виртуальные машины обычно медленнее запускаются и требуют больше времени на настройку и управление.

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

  5. Применение:

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

    • Контейнеризация чаще используется для разработки и развертывания приложений, особенно для микросервисной архитектуры, поскольку она упрощает CI/CD процессы и автоматическое масштабирование.

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

2. Объекты docker

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

  1. Образы (Images):

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

    • Пример использования: docker pull nginx, docker build -t myapp .

  2. Контейнеры (Containers):

    • Описание: Работающие экземпляры образов. Контейнеры представляют собой изолированные процессы на одном и том же ядре ОС.

    • Пример использования: docker run -d -p 80:80 nginx

  3. Сети (Networks):

    • Описание: Способ для контейнеров общаться друг с другом. Docker поддерживает различные драйверы сетей (bridge, host, overlay и др.).

    • Пример использования: docker network create mynetwork, docker network connect mynetwork mycontainer

  4. Тома (Volumes):

    • Описание: Специализированные директории для постоянного хранения данных контейнеров. Они позволяют сохранять данные независимо от жизненного цикла контейнера.

    • Пример использования: docker volume create myvolume, docker run -v myvolume:/data myapp

  5. Сервисы (Services):

    • Описание: Объекты Docker Swarm, которые позволяют масштабировать контейнеры на нескольких хостах. Они являются основной частью Docker для оркестрации контейнеров.

    • Пример использования: docker service create --name myservice --replicas 3 nginx

  6. Стэки (Stacks):

    • Описание: Набор связанных служб, которые можно развернуть с использованием Docker Compose. Они позволяют управлять многоконтейнерными приложениями.

    • Пример использования: docker stack deploy -c docker-compose.yml mystack

  7. Dockerfile:

    • Описание: Скрипт, содержащий инструкции для создания Docker образа. Используется для автоматизации процесса сборки образов.

    • Пример использования: docker build -t myapp .

3. Базовые команды docker

Чтобы создать docker-контейнер в простейшем виде, необходимо сделать следующее:

Создание контейнера Nginx

Для примера запускаем контейнер с образом nginx версии 1.25:

Создание контейнера Nginx

Если используется Docker Desktop:

Созданный контейнер в Docker Desktop

Результат создания контейнера:

Запущенный Nginx на порте 9000

Вместо Docker Desktop созданный контейнер можно посмотреть через терминал:

Отображение списка контейнеров

Как видно на скриншоте выше, контейнер принимает подключения с любых IP-адресов (0.0.0.0:9000) и перенаправляет подключения на порт 80 внутри контейнера. Автоматически контейнеру присваивается идентификатор (9d10d4ac19fa) и имя (gracious_diffie). Помимо этого, в том терминале, где мы запустили контейнер, мы не может вводить команды на хостовой ОС. Исправим имя контейнера (через указание опции --name) и возможность ввода команд после запуска (через опцию -d). Создаем новый контейнер:

Создание нового контейнера

Вновь проверим созданный контейнер:

Список контейнеров

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

Остановка и удаление контейнера

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

или

Запуск команды cat /etc/passwd внутри контейнера с использованием ID-контейнера
Запуск команды cat /etc/passwd внутри контейнера с использованием имени контейнера

Также можно использовать вместо `docker exec -it`, например, `docker run`, но это создаст новый контейнер!

А как получить shell, чтобы вводить команды свободно, как в обычном терминале? Крайне просто! Нужно просто запустить оболочку:

Запуск оболочки контейнера

4. Создание контейнера с использованием Dockerfile

Теперь создадим свой кастомный Docker-образ с использованием Dockerfile (простой проект на flask). Структура нашего проекта:

Теперь создаем docker-образ:

И запустим контейнер:

Создание собственного 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