Docker для начинающих: попрощайтесь с кошмарами развертывания!

Docker для начинающих: попрощайтесь с кошмарами развертывания!

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

Docker, написанный на Go и опубликованный с открытым исходным кодом под лицензией Apache 2.0, представляет собой контейнерный движок для приложений. Эта технология контейнеризации позволяет разработчикам упаковывать свои приложения и зависимости в легковесные, переносимые контейнеры. Такие контейнеры можно развернуть на любой популярной Linux-машине, не беспокоясь о различиях в окружении.

Docker в сравнении с виртуальными машинами (VM)

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

Для начала рассмотрим типичную архитектуру виртуальной машины. Над инфраструктурой (аппаратное обеспечение) располагается гипервизор. Выступая посредником между физическим сервером и операционными системами, он позволяет нескольким ОС и приложениям совместно использовать аппаратные ресурсы. Виртуальные машины запускают несколько разных операционных систем поверх хостовой ОС и используют гипервизор для доступа к оборудованию. Если вам нужно запустить три изолированных приложения, вы создадите три виртуальные машины. Это означает, что поверх гипервизора будут работать три операционные системы, что приводит к значительным накладным расходам ресурсов.

Типичная архитектура виртуальной машины

(Примечание: на схеме должна быть показана хостовая операционная система над гипервизором)

Docker, напротив, невероятно легковесен. Его демон (Docker Daemon) заменяет гипервизор и работает непосредственно в операционной системе. Исходный код приложения и его зависимости упаковываются в образ Docker. Затем движок Docker использует этот образ для создания контейнера. Разные приложения выполняются в изолированных контейнерах.

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

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

Как использовать Docker

Установка Docker (пример для CentOS 7)

  1. Установите необходимые системные инструменты:
yum install -y yum-utils device-mapper-persistent-data lvm2 
  1. Обновите ядро системы и кеш yum:
yum update
yum makecache fast
  1. Установите Docker и запустите его:
yum -y install docker-ce
systemctl start docker 
  1. Проверьте успешность установки Docker:
docker run hello-world 

Если на экране появилось “Hello from Docker”, поздравляю — установка завершена.

Основные понятия

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

  1. Образы Docker: Образ Docker — это шаблон для создания контейнеров Docker.
  2. Контейнер Docker: Docker создает контейнеры из образов для запуска набора независимых приложений.
  3. Реестр Docker: Хранилище кода для сохранения образов.

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

Примеры

Свяжем эти понятия на двух распространенных примерах, демонстрирующих использование Docker.

Установка Python с помощью Docker

Как упоминалось, первый шаг при использовании контейнера Docker — загрузить соответствующий образ из реестра. Это подводит нас к первой команде в нашем руководстве:

  • Назначение: Поиск определенного образа в реестре образов.
  • Синтаксис: docker search [OPTIONS] TERM
  • Пример: docker search python
  • Пояснение: Поиск образов, связанных с Python, в реестре.
[root@novita ~]# docker search pythonINDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/python                           Python is an interpreted, interactive, obj...   4356      [OK]
docker.io   docker.io/django                           Django is a free web application framework...   856       [OK]
docker.io   docker.io/pypy                             PyPy is a fast, compliant alternative impl...   196       [OK]
docker.io   docker.io/kaggle/python                    Docker image for Python scripts run on Kaggle   125                  [OK]
docker.io   docker.io/arm32v7/python                   Python is an interpreted, interactive, obj...   38
docker.io   docker.io/centos/python-35-centos7         Platform for building and running Python 3...   36

Выберем официальный образ с тегом (версией) 3.7.

docker pull

  • Назначение: Загрузить или обновить указанный образ из реестра.
  • Синтаксис: docker pull [OPTIONS] NAME:TAG
  • Пример: docker pull python:3.7
  • Пояснение: Загрузить образ Python с тегом 3.7 из реестра.
[root@novita ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============>                                     ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================>      ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==>                                                ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7

Docker загрузил указанный образ. Чтобы просмотреть существующие образы Docker:

docker images

  • Назначение: Вывести список локальных образов.
  • Синтаксис: docker images [OPTIONS] [REPOSITORY[:TAG]]
  • Пример: docker images
  • Пояснение: Просмотреть все локальные образы Docker.
[root@novita ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/python        3.7                 42d620af35be        6 days ago          918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        7 days ago          179 MB
docker.io/golang        latest              f50db16df5da        9 days ago          774 MB

Образ python3.7 присутствует. Давайте создадим контейнер на его основе.

docker run

Прежде чем создавать контейнер, кратко упомянем идентификаторы. В Docker ID однозначно идентифицируют образы или контейнеры. Мы взаимодействуем с ними с помощью “команды + ID”. Например, в предыдущем коде ID образа python3.7 — 42d620af35be.

  • Назначение: Создать новый контейнер.
  • Синтаксис: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Чтобы проверить среду Python, создадим локальный файл hello.py:

#!/usr/bin/python 
import sys 

print("Hello, Docker!") 
print(sys.version)  # Вывод номера версии Python 

Предположим, этот код сохранен в /root/code/python:

[root@novita python]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python hello.py 
Hello, Docker! 
3.7.4 (default, Jul 13 2019, 14:04:11) [GCC 8.3.0] 

Разберем эту команду:

  • docker run: Создает контейнер.
  • -v $PWD:/usr/src/code: Монтирует локальную директорию в контейнер Docker. В данном случае монтируется каталог, из которого выполняется команда, в /usr/src/code внутри контейнера. Двоеточие разделяет локальный путь и путь в контейнере. Вместо $PWD можно использовать абсолютные пути.
  • -w /usr/src/code: Устанавливает рабочую директорию контейнера. Поскольку каталог с кодом Python смонтирован в /usr/src/code, мы назначаем его рабочей директорией.
  • python:3.7: Указывает образ. Можно использовать ID образа.
  • python hello.py: Выполняет эту команду внутри контейнера.

Вопрос для размышления: Если у вас есть файл hello.go в /root/data/ и вы хотите запустить его с помощью контейнера Golang с ID образа f50db16df5da, какой будет команда? (Подсказка: команда для запуска Go-кода — go run FILENAME)

Установка MariaDB с помощью Docker

Предположим, вы уже умеете искать и загружать образ MariaDB. Сосредоточимся на его запуске. Таким сервисам, как базы данных, требуются соответствующие порты, открытые на хосте. Как это сделать с помощью Docker? Мы используем проброс портов, аналогично монтированию директорий.

[root@novita python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456  --restart unless-stopped 3a2ef06682ac 
  • -d: Запустить контейнер в фоновом режиме.
  • -p 3306:3306: Пробросить порт 3306 контейнера на порт 3306 хоста.
  • -e MYSQL_ROOT_PASSWORD=123456: Устанавливает пароль root для MariaDB равным 123456.
  • --restart unless-stopped: Автоматически перезапускать контейнер при неожиданной остановке.
  • 3a2ef06682ac: ID образа для создания контейнера.

Теперь проверим, запущен ли сервис базы данных: docker ps

  • Назначение: Вывести список контейнеров.
  • Синтаксис: docker ps [OPTIONS]
[root@novita ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
107b52416c13        3a2ef06682ac        "docker-entrypoint..."   5 minutes ago       Up 5 minutes        0.0.0.0:3306->3306/tcp                                                                       quizzical_mcnulty 

Далее войдем во внутреннюю среду контейнера. docker exec

  • Назначение: Выполнить команду в работающем контейнере.
  • Синтаксис: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
  • Пример: docker exec -it 107b52416c13 bash
  • Пояснение: Подключиться к контейнеру с ID 107b52416c13 и выполнить команду bash.

Внутри контейнера с ним можно взаимодействовать как с обычной Linux-средой. Используя ранее заданные учетные данные, можно подключиться к MariaDB.

[root@novita ~]# docker exec -it 107b52416c13 bash 
root@107b52416c13:/# mysql -u root -p123456 
Welcome to the MariaDB monitor.  Commands end with ; or \g. 
Your MariaDB connection id is 11 
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
MariaDB [(none)]> 

Вы освоили основы Docker. Пробуйте изучать дальше.

Novita AI — это универсальная облачная платформа, которая воплощает ваши AI-амбиции. Благодаря бесшовно интегрированным API, бессерверным вычислениям и GPU-ускорению, мы предоставляем экономичные инструменты, необходимые для быстрого создания и масштабирования вашего бизнеса на основе ИИ. Избавьтесь от инфраструктурных проблем и начните бесплатно — Novita AI превращает ваши мечты об ИИ в реальность.