Перейти к содержимому

Docker python что это

  • автор:

[Python Intermediate] Урок 2. Docker и docker-compose

Всё, что написано ниже, является прямым продолжением предыдущего материала, и если ты его пропустил, то многое покажется тебе непонятным или неочевидным. Поэтому я рекомендую не торопиться и соблюдать последовательность.

И ещё важный момент — если ты совсем не знаком с Docker, то прежде чем двигаться дальше, обязательно почитай про основы данной технологии, благо статей в интернете немало, например, вот. Или хотя бы ознакомься с моей памяткой (VK, Github). Просто чтобы понимать, о чём вообще речь.

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

Благодаря контейнеризации и использованию Docker, разработчики больше не задумываются о том, в какой среде будет функционировать их приложение и будут ли в этой в среде необходимые для тестирования опции и зависимости. Достаточно упаковать приложение со всеми зависимостями и процессами в контейнер, чтобы запускать в любых системах: Linux, Windows и macOS. Платформа Docker позволила отделить приложения от инфраструктуры. Контейнеры не зависят от базовой инфраструктуры, их можно легко перемещать между облачной и локальной инфраструктурами.

Не переживай, супер глубокое понимание технологии в рамках данного материала не потребуется. Но если всё-таки очень хочется погрузиться, то на Хабре есть перевод серии статей от Джеффа Хейла.

К сожалению, в python-мире до сих пор повсеместно применяется неизолированный запуск приложения и его инфраструктуры на личных устройствах. Боюсь, даже опытные специалисты неохотно используют контейнеризацию, хотя в действительности её плюсы неоспоримы.

Во-первых, она позволяет при локальном запуске повторить среду продакшена, что может уберечь от многих неочевидных ошибок. А во-вторых, при переезде с компа на комп или при появлении нового разработчика не придётся в сотый раз корячиться с настройкой приложения и инфраструктуры. Конфигурация производится лишь однажды и в дальнейшем просто поддерживается в актуальном состоянии.

Разумеется, «контейнерная» разработка, как и всё в нашем мире, имеет свои недостатки. Главный из них сопряжён с локальной отладкой приложения — при запуске через системный интерпретатор сделать это куда проще. Однако технологии тоже не стоят на месте, и такие популярные IDE, как PyCharm Professional и VS Code, уже способны справиться с данной задачей.

Отдельной строкой следует упомянуть ещё один нюанс: при работе с докером на чипах M1 можно напороться на трудности. Не всегда очевидные, но решаемые, и ситуация постоянно улучшается.

Тизер

Чтобы понимать, к чему мы вообще стремимся, предлагаю тебе сначала установить Docker и Docker Compose.

Затем стяни этот репозиторий и перейди в директорию текущего урока:

cd lesson_2

В ней создай папку secrets и положи туда два файла: event_broker_password и service_db_password . В первый файл впиши python_garden , а во второй — postgres .

Проверь, всё ли правильно получилось? (Команда cat выводит содержимое файла).

cat secrets/event_broker_password > python_garden cat secrets/service_db_password > postgres

Введи в терминале из корня проекта следующую команду:

docker compose up -d

После того, как её выполнение закончится, введи:

docker compose ps

В результате у тебя должно получиться следующее:

Список запущенных контейнеров

Если ты счастливый обладатель компа с чипом M1, то смотри README.

Теперь, чтобы убедиться в правдивости напечатанных статусов, выведи логи любого сервиса при помощи команды docker compose logs (имена в столбце SERVICE ).

Логи консьюмера: распечатаны объекты с переменными окружения из первого урока

Также можешь дёрнуть апишку из предыдущего урока обычным курлом: curl http://0.0.0.0:8000 .

Логи апишки: распечатан объект с переменными окружения из первого урока

При желании открой адрес http://0.0.0.0:8000 в браузере и убедись в наличии идентичного ответа.

Ну и напоследок небольшой бонус. Зайди на http://0.0.0.0:15672, введи в оба поля python_garden и нажми «Login».

Добро пожаловать в веб-интерфейс локального RabbitMQ! Вот так просто.

Web-интерфейс RabbitMQ

Прежде чем продолжить, давай откатимся в самое начало и удалим всё, что мы создали на данном этапе. Введи поочерёдно следующие команды:

docker compose down docker system prune --all

Dockerfile

Знакомство с контейнеризацией мы начнём с описания докер-файла ( ./Dockerfile ), где будут перечислены инструкции для сборки нужного нам образа.

FROM python:3.9-slim as base LABEL maintainer # Сборка зависимостей ARG BUILD_DEPS="curl" RUN apt-get update && apt-get install -y $BUILD_DEPS # Установка poetry RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.2.0 POETRY_HOME=/root/poetry python3 - ENV PATH="$:/root/poetry/bin" # Инициализация проекта WORKDIR /opt/lesson_2 ENTRYPOINT ["./docker-entrypoint.sh"] ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # Установка питонячьих библиотек COPY poetry.lock pyproject.toml / RUN poetry config virtualenvs.create false && \ poetry install --no-interaction --no-ansi # Копирование в контейнер папок и файлов. COPY . .

�� В самой первой строке мы ссылаемся на базовый образ из публичного репозитория. Можешь выбрать любой другой из списка, если тебя, скажем, не устраивает версия. Только прошу обратить внимание: лучше брать slim-образы, поскольку при работе с alpine ты неизбежно столкнёшься с трудностями во время установки некоторых библиотек. Также замечу: во всех уважающих себя компаниях образы хранятся в своих, закрытых репозиториях, так что навряд ли тебе придётся где-то, помимо собственных проектов, обращаться к Docker Hub напрямую.

�� Во второй строке указан ответственный за создание и поддержку образа. Обычно здесь оставляют name и email команды разработчиков.

�� В блоке «Сборка зависимостей» мы сначала объявляем переменную BUILD_DEPS , в которой перечисляем необходимые утилиты и функции ОС, затем запускаем обновление списков пакетов и устанавливаем перечисленные сущности.

Инструкцию ARG вместе с переменной можешь опустить, объединив со следующей. Это лишь вопрос эстетики и удобства.

RUN apt-get update && apt-get install -y curl

Главное, никогда без веской причины не запускай в докер-файле команду apt-get upgrade , которая часто встречается в различных сниппетах рядом с apt-get update .

Запомни разницу (подробности здесь):

  • apt-get update — обновляет списки пакетов, т.е. получает информацию о новейших версиях и зависимостях;
  • apt-get upgrade — на основе существующих списков ( /etc/apt/sources.list ) запускает обновление всех установленных в настоящее время пакетов.

Допустим, мы ожидаем некий пакет версии «1.0», установленный в базовом образе, и ориентируемся на вполне конкретное поведение. А после апгрейда получаем, к примеру, версию «3.5» с совершенно иным поведением. Думаю, ты представляешь степень боли, которую нам предстоит испытать в подобном случае.

�� Далее принимаемся за установку poetry. Это модный и полезный менеджер зависимостей для Python. Если ты с ним ещё не знаком, то пока не заморачивайся — обсудим его как-нибудь отдельно. Просто пропускай обе инструкции.

�� В «Инициализации проекта» проводим подготовительные мероприятия, а именно:

  • задаём рабочую директорию для всех последующих директив;
  • указываем sh-скрипт с вариантами запуска нашего приложения (о них ниже);
  • устанавливаем две переменные среды, которые очень важны.

PYTHONUNBUFFERED отвечает за отключение буферизации вывода (output). То есть непустое значение данной переменной среды гарантирует, что мы можем видеть выходные данные нашего приложения в режиме реального времени.

PYTHONDONTWRITEBYTECODE означает, что Python не будет пытаться создавать файлы .pyc .

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

Добавляй эти две переменные в Dockerfile всегда! Даже если пишешь на Go. Просто на всякий случай. ��

�� В предпоследнем блоке устанавливаем зависимости. Для poetry, когда речь идёт о контейнере, отключаем создание виртуального окружения ( virtualenvs.create false ), интерактив ( —no-interaction ) и ANSI-output ( —no-ansi ).

Если же от poetry ты решил держаться подальше, то запускай:

RUN pip3 install -r requirements

�� Последняя директива в дополнительных комментариях не нуждается: весь проект просто копируется внутрь контейнера, в WORKDIR .

Итак, мы пробежались по всем инструкциям, указанным в нашем Dockerfile. Теперь давай сбилдим образ! Для этого запусти команду:

docker build -t python_garden .

Здесь -t означает имя нашего образа, а . указывает текущую директорию в качестве целевой.

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

Docker-образ, собранный по вышеописанному Dockerfile

Точка входа

Далее приступаем к описанию sh-скрипта так называемой точки входа, она же entrypoint. Точка входа — это парадные ворота в наш сервис, которые мы обозначили в докер-файле командой ENTRYPOINT [«./docker-entrypoint.sh»] . А sh-скрипт, продолжая аналогию, что-то вроде табличек-указателей или ресепшена в отеле.

Напомню: у нашего нового бэкенд-приложения из первого урока есть два режима работы — API и консьюмер.

Схема бэкенда из первого урока

Явно опишем оба варианта в sh-скрипте, также размещённом в корне проекта ( ./docker-entrypoint.sh ), и не забудем оставить возможность для запуска иных команд.

#!/usr/bin/env sh set -e case "$1" in api) exec bash -c "uvicorn app.api.webapp:app --host 0.0.0.0 --port 8000 --reload --reload-dir app" ;; consumer) exec python run_consumer.py ;; *) exec "$@" esac

На данном этапе у тебя может возникнуть вопрос: «А зачем такие сложности? Почему бы не указать команду запуска сервиса прямо в dockerfile через директиву CMD с возможностью переопределения?». Ты прав — если речь идёт о простом приложении с одним вариантом запуска, то смысла городить огород с точкой входа, разумеется, нет. Однако в природе такие приложения попадаются очень редко. Посуди сам, даже в Django, помимо основной команды запуска python manage.py runserver , у нас имеются следующие: создание новой миграции, применение миграций, запуск какого-нибудь вспомогательного скрипта, запуск тестов и так далее.

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

Что касается продемонстрированного выше скрипта, то он, думаю, трудностей в понимании у тебя не вызовет: имеются две строго декларированные команды и отдельная ветка для всех остальных. Тут следует остановиться подробнее разве что на exec . По рекомендации разработчиков Docker, запуск процессов внутри контейнера лучше осуществлять через неё, ибо тогда вызываемая команда получит PID 1 и будет корректно работать с сигналами. Если же exec не указать, то PID 1 достанется процессу bash .

Docker Compose

Мы почти у цели! Осталось описать инфраструктуру приложения. Для этого воспользуемся инструментом под названием Docker Compose. Если говорить упрощённо, то данная технология позволяет с помощью простых команд контролировать несколько сервисов.

Там же, в корне проекта, разместим файл docker-compose.yml , где будут храниться конфиги всех сервисов инфраструктуры.

Принимаемся за настройку базы данных.

version: "3.4" services: service_db: container_name: python-garden_db image: postgres:10 ports: - "5432:5432" environment: POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres
  • имя контейнера;
  • образ, на основе которого будет собран контейнер;
  • соответствие портов на хост-машине портам в контейнере, то есть при подключении к порту № 1 мы будем попадать на порт № 2 в контейнере;
  • и переменные окружения, по сути являющиеся кредами для доступа к БД.

Для нашего примера — да и вообще для большинства локальных развёртываний PostgreSQL — этой конфигурации будет достаточно. Однако если хочешь, можешь покопаться в официальной доке и познакомиться с полным перечнем доступных настроек.

Теперь давай обратим внимание на RabbitMQ.

version: "3.4" services: mq: container_name: python-garden_mq image: rabbitmq:3-management ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_DEFAULT_USER: python_garden RABBITMQ_DEFAULT_PASS: python_garden

Как видишь, различий немного.

Попробуем поднять нашу инфраструктуру. Для этого введи в терминале из корня проекта следующую команду:

docker compose up -d # запуск всех описанных в compose-файлах сервисов

И посмотри результат:

docker compose ps

Если статусы у обоих сервисов — running , ты всё сделал правильно. Если нет, значит, я что-то упустил в своих объяснениях. Обязательно напиши об этом в комментариях!

Ну что? Вот мы и добрались, наконец-то, до нашего псевдобэкенда. Давай опишем его.

version: "3.4" services: api: container_name: python-garden_api image: python_garden build: context: . ports: - "8000:8000" command: "api" environment: PYTHONUNBUFFERED: 1 SERVICE_DB_HOST: service_db SERVICE_DB_NAME: postgres SERVICE_DB_USERNAME: postgres volumes: - .:/opt/lesson_2 consumer: container_name: python-garden_consumer image: python_garden build: context: . command: "consumer" environment: PYTHONUNBUFFERED: 1 SERVICE_DB_HOST: service_db SERVICE_DB_NAME: postgres SERVICE_DB_USERNAME: postgres EVENT_BROKER_HOST: mq EVENT_BROKER_PORT: 5672 EVENT_BROKER_USERNAME: python_garden volumes: - .:/opt/lesson_2

Новых ключей здесь немного. Начнём с build . Это раздел с настройками для сборки образа. То есть, если у тебя на момент запуска контейнера отсутствует образ python_garden , Docker Compose при помощи параметров в разделе build соберёт его сам. Параметр context: . в данном случае сообщает, что Dockerfile располагается в текущей директории.

Ключ command переопределяет команду по умолчанию, указанную в директиве CMD . В нашем случае такая инструкция отсутствует, поэтому command её заменяет. Как ты помнишь, api и consumer у нас явно описаны в docker-entrypoint.sh .

По поводу volumes смотри уже упомянутую памятку по Docker. Внешний том нам здесь нужен для того, чтобы после каждого изменения кода не приходилось пересобирать образ. Помнишь, при сборке задействовалась инструкция COPY ? После её выполнения в образе сохраняется кодовая база определённой версии, а с помощью вольюмов мы обходим это ограничение. То есть при указанном volumes образ смотрит в папку с проектом и по команде docker compose restart поднимает контейнер с обновлённой кодовой базой.

Посмотреть файл с настройками Docker Compose целиком можно по ссылке.

Заключение

Дабы убедиться, что всё работает как надо, вернись в раздел «Тизер» и проделай описанные там действия.

Согласись, это очень удобно, когда ты скачиваешь проект с гитхаба и одной командой можешь запустить его вкупе с зависимыми сервисами. Только не забывай поддерживать актуальность docker-compose.yml и docker-entrypoint.sh .

Бывают случаи, когда могут понадобиться какие-то локальные доработки — например, имя контейнера не по душе или ты используешь устройство с процессором M1, тогда как коллеги сидят на православном Intel. Разработчики предусмотрели такую ситуацию, так что не вздумай ломать работающий файл docker-compose.yml ! Вместо этого создай в корне проекта docker-compose.override.yml и изменяй существующие настройки, как тебе вздумается. Общий, совмещённый результат конфигурации ты можешь посмотреть с помощью команды:

docker compose config

В этой статье намеренно отсутствует конкретика и не используется в качестве примера какой-нибудь полурабочий прототип, чтобы на выходе у тебя получился шаблон микросервиса. Забирай результат, правь под себя и пользуйся.

Тезисы для запоминания

  1. Старайся использовать slim-образы Python, поскольку при работе с alpine ты неизбежно столкнёшься с трудностями во время установки некоторых библиотек.
  2. Не запускай в докер-файле команду apt-get upgrade .
  3. Всегда добавляй в Dockerfile переменные окружения ENV PYTHONDONTWRITEBYTECODE 1 и ENV PYTHONUNBUFFERED 1 .
  4. По рекомендации разработчиков Docker, запуск процессов внутри контейнера лучше осуществлять через exec , ибо тогда вызываемая команда получит PID 1 и будет корректно работать с сигналами.
  5. Помни про volumes . Без указания внешнего тома тебе придётся постоянно пересобирать образ.

Полезные команды

Поднять в фоне все сервисы, описанные в конфигурации:

docker compose up -d

Вывести список контейнеров:

docker compose ps

Вывести логи указанного сервиса (контейнера):

docker compose logs
docker compose restart

Посмотреть итоговую конфигурацию контейнеров:

docker compose config

Остановить все контейнеры из текущей конфигурации:

docker compose stop

Удалить все контейнеры из текущей конфигурации:

docker compose rm

Остановить и удалить все контейнеры из текущей конфигурации (последовательное выполнение двух предыдущих команд):

docker compose down

Удалить все не запущенные контейнеры и все не использующиеся образы:

docker system prune --all

Вывести список образов:

docker images

Что такое Docker: для чего он нужен и где используется

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

Изображение записи

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

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

Managed Kubernetes помогает разворачивать контейнерные приложения в инфраструктуре Selectel. Сосредоточьтесь на разработке, а мы займемся рутинными операциями по обеспечению работы вашего кластера Kubernetes.

Что такое контейнеры

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

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

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

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

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

Преимущества использования контейнеров Docker

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

Docker решает проблемы зависимостей и рабочего окружения

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

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

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

Изоляция и безопасность

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

Ускорение и автоматизация развертывания приложений и масштабируемость

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

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

Контейнеры приближают к микросервисной архитектуре

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

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

Docker compose — одновременно развернуть несколько контейнеров

Docker-compose позволяет разворачивать и настраивать несколько контейнеров одновременно. Например, для веб-приложения нужно развернуть стек LAMP: Linux + Apache, MySQL, PHP. Каждое из приложений — это отдельный контейнер для ОС Linux. Но в этой ситуации нам нужны именно все контейнеры вместе, а не отдельно взятое приложение. Docker-compose позволяет развернуть и настроить все приложения одной командой, а без него пришлось бы разворачивать и настраивать каждый контейнер отдельно.

Хранение данных в Docker

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

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

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

Тома (Docker volumes)

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

Монтирование каталога (bind mount)

В этом случае директория сначала создается на хост-машине а уже потом монтируется в контейнеры.

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

Архитектура (компоненты) Docker

Теперь расскажем подробнее про компоненты, из которых состоит Docker.

Docker daemon

Это некоторый резидентный процесс, который запущен на хост-машине постоянно. Он владеет всей инфраструктурой, а также предоставляет интерфейс взаимодействия с контейнерами, включающего создание и удаление, запуск и остановку.

В ранних версиях платформы Docker можно встретить упоминание о dockerd, но на текущий момент демоны уже успели разбиться на отдельные проекты. Все чаще можно встретить его современника — containerd.

Docker client (клиент)

Это интерфейс командной строки для управления Docker daemon. Мы пользуемся этим клиентом, когда создаем и разворачиваем контейнеры, а клиент отправляет эти запросы в Docker daemon.

Docker image (образ)

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

Приведем аналогию на примере установки операционной системы. В дистрибутиве (образе) ОС есть все, что необходимо для ее установки. Но этот образ нельзя запустить, для начала его нужно «развернуть» в готовую ОС. Так вот, дистрибутив для установки ОС — это образ, а установленная и работающая ОС — это контейнер. Но контейнеры обычно разворачиваются одной командой — это намного проще и быстрее, чем установка ОС.

Docker container (контейнер)

Это уже развернутое из образа и работающее приложение.

Docker Registry

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

Dockerfile

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

Для примера рассмотрим Dockerfile, который мы будем использовать далее в этой статье чтобы развернуть собственное приложение:

FROM python:3 COPY main.py / CMD [ "python", "./main.py" ]

Первая строчка означает, что за основу мы берем образ с названием python версии 3 это называется базовый образ. Docker найдет его в docker registry, скачает и будет использовать за основу. Вторая строчка означает, что нужно скопировать файл main.py в корень файловой системы контейнера. Третья строчка означает, что нужно запустить python и передать ему в качестве параметра название файла main.py.

Далее рассмотрим примеры нескольких команд докер и что происходит, когда мы их выполняем.

Все эти команды выполняются в Docker client, который отправляет их в Docker daemon:

  • Команда docker build (зеленая стрелка) читает dockerfile и собирает образ.
  • Команда docker pull (красная стрелка) скачивает образ из docker registry. По умолчанию docker скачивает образы из публичного репозитория Docker Hub. Но можно создать свой репозиторий и настроить докер, чтобы он работал с ним.
  • Команда docker run (черная стрелка) берет образ и запускает из него контейнер.

Создаем виртуальную машину для работы с Docker

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

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

На следующем экране выбираем параметры сервера: имя, регион, ОС, параметры производительности и так далее. Сейчас для нас важны параметры «Источник» — выбираем ОС Ubuntu 20.04 и «Конфигурация» — выбираем 2 vCPU и 8 ГБ оперативной памяти.

Далее обратите внимание на разделы Сеть и Доступ. В разделе Сеть нужно выбрать подсеть с публичным адресом, чтобы к виртуальной машине можно было подключаться из интернета. В разделе Доступ будет указан пароль для root-пользователя, а также необходимо загрузить SSH-ключ, чтобы подключаться к виртуальной машине. Подробную инструкцию о подключении смотрите в базе знаний.

После этого внизу страницы нажимаем кнопку «Создать». Виртуальная машина создается за несколько минут, и после того, как она перейдет в статус ACTIVE, к ней можно подключаться по SSH.

Установка Docker

Мы рассмотрим установку докера на примере Ubuntu. Если у вас другой дистрибутив Linux или операционная система — ищите соответствующую инструкцию на официальном сайте.

Для начала синхронизируем пакетную базу apt и установим нужные зависимости:

sudo apt-get update
sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release

Далее импортируем GPG-ключ для репозитория docker:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

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

echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

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

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

По умолчанию, доступ к docker daemon есть только у пользователя root. Чтобы с докером могли работать и другие пользователи, их нужно добавить в специальную группу — docker. Выполните эту команду из под обычного пользователя:

sudo usermod -aG docker $USER

После этого необходимо перелогиниться, чтобы изменение вступило в силу.

Запуск контейнера

Теперь попробуем запустить какое-нибудь готовое приложение. Выполните команду:

docker run ubuntu echo 'hello from ubuntu'

Команда docker run создает и запускает контейнер из образа. В этом примере мы создаем контейнер из образа ubuntu, затем выполняем в нем команду echo ‘hello from ubuntu’. Но так как у нас чистая установка докера и мы не скачали ни одного образа, докер сначала найдет этот образ в публичном репозитории Docker Hub, скачает, а потом создаст из него контейнер. В следующий раз, когда нам понадобится образ ubuntu, докер уже не будет его скачивать.

После выполнения команды в терминале появится строка hello from ubuntu, и контейнер сразу остановится. Теперь выполним другую команду:

docker run -it ubuntu

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

Создание собственного образа и запуск контейнера

Теперь создадим HelloWorld-приложение на Python, обернем его в образ и запустим.

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

mkdir first-docker-app
cd first-docker-app

Создадим файл main.py и запишем в него одну строчку кода:

echo 'print("Hello from python");' >> main.py

Проверим, что наша программа работает. Для этого выполним команду:

python main.py

В консоли должно выйти сообщение Hello from python. Это и есть наше простое приложение. Теперь нужно обернуть его в докер-образ. Для этого создадим файл Dockerfile и напишем в нем три строчки:

FROM python:3 COPY main.py / CMD [ "python", "./main.py" ]

В первой строке мы указываем образ, который берем за основу. Так как мы пишем приложение на Python, нужно чтобы в нашем образе он уже был установлен. Самый простой способ это сделать — использовать готовый официальный образ с Docker Hub. Цифра 3 — это тег. Он означает, что нужно использовать третью версию Python. Вместо этого можно было бы использовать тег latest, который означает самую последнюю версию, или можно было указать номер конкретной версии, например 3.8.8.

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

Третья строчка — запускаем python и передаем ему в качестве параметра имя нашего файла.

Теперь из этого докер-файла можно собирать образ. Выполним команду:

docker build -t first-docker-app .

Параметр -t обозначает имя нашего образа, мы назвали его first-docker-app.

Так как у нас еще нет скачанного образа python, то докер сам скачает его из Docker Hub и затем будет использовать его в качестве основы для создания нашего образа.

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

docker images

Мы увидим, что у нас установлено три образа:

REPOSITORY TAG IMAGE ID CREATED SIZE first-docker-app latest 649cceb4dfd2 4 seconds ago 885MB python 3 b1aa63f57d3c 2 days ago 885MB ubuntu latest 8e428cff54c8 4 days ago 72.9MB

first-docker-app — это наш образ, который мы только что создали. python — это образ python, который докер автоматически скачал чтобы собрать наш образ. ubuntu — образ, который мы пробовали для запуска готового приложения.

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

docker run first-docker-app

В результате нам выведется результат: Hello from python.

Итог: Мы создали свое приложение, упаковали его в докер-образ и запустили. Конечно, это очень простой пример. Наша программа состоит всего из одной строчки, а dockerfile из трех. Но это позволяет понять базовые принципы работы докера, как он устроен, как создавать свои образы и запускать контейнеры.

Готовые кластеры Kubernetes с GPU

Создайте за несколько кликов.

Что такое Docker?

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

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

Новые объявления: Docker сотрудничает с AWS, чтобы помочь разработчикам ускорить доставку современных приложений в облаке. Благодаря такому взаимодействию разработчики могут с помощью Docker Compose и Docker Desktop оптимизировать локальный рабочий процесс, применяемый на данный момент, для беспрепятственного развертывания приложений на Amazon ECS и AWS Fargate. Подробнее в блоге.

Как работает Docker

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

Такие сервисы AWS, как AWS Fargate, Amazon ECS, Amazon EKS и AWS Batch, упрощают работу с контейнерами Docker, а также управление ими в любом масштабе.

Почему следует использовать Docker

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

Быстрая доставка программного обеспечения

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

Стандартизация операций

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

Эффективное перемещение

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

Экономия

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

Когда рекомендуется использовать Docker

Контейнеры Docker можно использовать в качестве основных компонентов для создания современных платформ и приложений. Docker упрощает сборку и запуск распределенных микросервисных архитектур, развертывание кода с помощью стандартизированных конвейеров непрерывной интеграции и доставки, создание высокомасштабируемых систем обработки данных и полностью управляемых платформ для разработчиков. Сотрудничество AWS и Docker позволит упростить операцию развертывания артефактов Docker Compose в Amazon ECS и AWS Fargate.

Микросервисы

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

Непрерывная интеграция и доставка

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

Обработка данных

Обработки больших данных как сервис. Объедините пакеты данных и аналитики в портативные контейнеры, запуск которых не требует специальных технических навыков.

Контейнер как сервис

Создавайте и доставляйте распределенные приложения, содержание и инфраструктура которых программно управляема и защищена.

Вопросы и ответы по Docker

Вопрос: Как можно использовать Docker?

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

Вопрос: Что такое образ Docker?

Образ Docker – это доступный только для чтения шаблон, который задает настройки контейнера. Образ содержит исполняемый код вместе с определениями любых библиотек и зависимостей, которые могут понадобиться для его работы. Контейнер Docker представляет собой запущенный (работающий) образ Docker. AWS предоставляет реестр образов Amazon Elastic Container Registry (ECR) для хранения и быстрого извлечения образов Docker.

Вопрос: В чем разница между Docker и виртуальной машиной?

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

Запуск Docker на AWS

В AWS обеспечена поддержка решений Docker с открытым исходным кодом и коммерческого уровня. Существует несколько способов запуска контейнеров на AWS, в том числе с помощью Amazon Elastic Container Service (ECS) – высокомасштабируемого и высокопроизводительного сервиса управления контейнерами. Клиенты могут легко развернуть свои контейнерные приложения с локальной среды Docker непосредственно в Amazon ECS. AWS Fargate – это технология для Amazon ECS, которая позволяет запускать контейнеры в рабочей среде без необходимости развертывания соответствующей инфраструктуры или управления ею. Amazon Elastic Container Service for Kubernetes (EKS) упрощает запуск Kubernetes на AWS. AWS Fargate – это технология для Amazon ECS, которая позволяет запускать контейнеры без необходимости выделения серверов или управления ими. Amazon Elastic Container Registry (ECR) – это высокодоступный и защищенный частный репозиторий контейнеров, который упрощает хранение образов контейнеров Docker, а также управление ими. Сервис шифрует и сжимает образы при хранении, обеспечивая их защиту и быстрое извлечение. AWS Batch позволяет запускать рабочие нагрузки пакетной обработки на основе контейнеров Docker с широкими возможностями масштабирования.

Amazon ECS

Amazon ECS – это высокопроизводительный сервис оркестрации для запуска контейнеров Docker в облаке AWS с широкими возможностями масштабирования.

Введение в Docker: образы, контейнеры и докер-файлы

Docker

Docker — это средство или система упаковки, доставки и запуска приложений. Он позволяет запускать приложения написанные на разных языках программирования благодаря унифицированному подходу к упаковке, доставке и запуску приложений. Поставляется Docker как набор Open Source программ, свободно доступных для скачивания как из репозиториев Linux, так и с сайта www.docker.com. Несмотря на то, что Docker стал уже давно стандартом в DevOps, до сих пор его установка у начинающих пользователей вызывает затруднения. Чтобы у наших читателей не было с этим проблем — мы подготовили краткую инструкцию по его установке. Появление докера сильно упростило процесс доставки и запуска приложений у конечных пользователей. Он смог стандартизировать эти процессы, предоставляя разработчикам сразу 3 мощных механизма:

  1. механизм сборки приложений в неизменяемые образа, которые избавляют от надобности сбора всех нужных зависимостей по всей хостовой ОС;
  2. механизм доставки программных продуктов до конечных пользователей, гарантирующий 100% совместимость с хостовой ОС;
  3. механизм развертывания приложений на любой *nix-системе, все зависимости от языка программирования на котором написано приложение.

Docker, следуя специальным инструкциям, прописанным разработчиком в конфигурационных файлах (Dockerfile и Docker-compose.yaml), собирает всё необходимое для запуска приложения в одно место — в образ. Docker-образ можно сравнить с CD-диском, с которого в будущем будет установлен и запущен некий софт. Контейнер в свою очередь — это запущенная копия образа.

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

Компоненты экосистемы Docker

Структура Docker

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

  1. Системные компоненты: Docker host (докер-хост), Docker daemon (докер-демон), Docker client (докер-клиент) и Docker-compose (менеджер запуска кластера контейнеров);
  2. Переменные компоненты: Docker image (докер-образ), Docker container (докер-контейнер), Docker registry (репозиторий), Dockerfile (докер-файл), Docker-compose.yaml (конфигурационный файл кластера контейнеров).

Пройдёмся вкратце по первой группе, затем подробно разберем компоненты второй группы:

  • Docker host (докер-хост) — это просто компьютер или виртуальный сервер, на котором установлен Docker. Кстати, Docker можно запустить и из WSL 2. Это удобно, если вы работаете под Windows и используете Visual Studio Code. Прочитать о том как настроить WSL для работы с докером можно здесь.
  • Docker daemon (докер-демон) — центральный системный компонент, который управляет всеми процессами докера: создание образов, запуск и остановка контейнеров, скачивание образов. Работает Docker daemon как фоновый процесс (демон) и постоянно следит за состоянием других компонентов.
  • Docker client (докер-клиент) — это утилита, предоставляющая API к докер-демону. Клиент может быть консольным (*nix-системы) или графическим (Windows).

Разберём теперь подробнее компоненты второй группы. Начнём с центральных элементов — докер-образа.

Docker-образ

Docker образ — это шаблон (физически — исполняемый пакет), из которого создаются Docker-контейнеры. Образ хранит в себе всё необходимое для запуска приложения, помещенного в контейнер: код, среду выполнения, библиотеки, переменные окружения и конфигурационные файлы.

Docker-образ создаётся с помощью команды docker build, которая считывает конфигурацию создаваемого образа из специального конфигурационного файла — dockerfile.

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

Каждая команда записанная в dockerfile создаёт свой слой. Чем больше слоёв, тем дольше будет собираться образ и дольше загружаться контейнер. Финальный Docker-образ — это объединение всех слоев в один. Благодаря такому подходу можно переиспользовать уже готовые образа для создания новых образов.

Контейнер Docker

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

Получается, чтобы запустить приложение на питоне, в контейнере должна быть ОС и Python. Возникает вопрос: откуда нам это всё взять? Разработчики Docker и здесь о нас позаботились, ведь если вы впервые собираете Docker-образ никаких готовых образов у вас на машине нет, поэтому Docker сам скачает указанный вами родительский образ в Dockerfile из репозитория hub.docker.com.

В нашем случае команды в Dockerfile будут такими:

FROM python:latest
RUN mkdir -p /usr/app/
WORKDIR /usr/app/
CMD [«python», «main.py»]

Первая команда говорит докеру следующие: возьми образ Python с тегом latest, а если его нет локально — скачай из хаба. Вторая команда — создаст директорию app. Третья команда установит директорию /usr/app/ в качестве рабочей директории, а команда CMD осуществит системный вызов, который будет выполнен при старте контейнера.

Docker заботится об используемых ресурсах, поэтому скачанные или собранные самостоятельно образы хранятся локально. Посмотреть их можно командой docker images. В ответ команда вернёт таблицу следующего вида:

REPOSITORY TAG IMAGE ID CREATED SIZE
acc-info latest 7069c8d4c76b 27 hours ago 1.05GB
python latest a5d7930b60cc 3 weeks ago 917MB

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

Для загрузки образа в репозиторий сначала нужно залогиниться на hub.docker.com, а затем и в терминале, с помощью команды docker login. После логина соберите образ командой docker build и в качестве названия образа укажите свой никнейм с сайта hub.docker.com и через “/” желаемое название образа. В нашем случае это выглядит так:

docker build -t pseudolukian/acc-info .

После успешного создания образа, его можно загружать в удаленный репозиторий командой docker push с указанием названия образа:

docker push pseudolukian/acc-info

Загруженные образы появятся по адресу: https://hub.docker.com/repositories. Теперь вы можете их скачать на любую машине командой docker pull название образа.

Что нужно знать о Docker-образах:

  • Образ — это только шаблон для создания контейнеров.
  • В основе любого образа лежит родительский образ, который, как правило, содержит ОС.
  • Образ состоит из слоев.
  • Каждая команда в Dockerfile создаёт новый слой.
  • Образы можно переиспользовать много раз.
  • Образы можно загружать в удаленный репозиторий.

Если вы хотите больше практики и экспериментов с созданием Docker-образов — в нашей базе знаний есть инструкция, содержащая основные команды Docker по работе с образами.

Итак, с первой основной сущностью экосистемы Docker разобрались, переходим ко второй — Docker-контейнеру.

Docker-контейнер

Docker-контейнер

Контейнер — это запущенный и изолированный образ с возможностью временного сохранения данных. Данные записываются в специальный слой «сверху» контейнера и при удалении контейнера данные также удаляются.

Для работы с контейнерами Docker предоставляет всего несколько основных команд: docker run/stop/restart. Однако команда run имеет множество полезных ключей, о которых просто необходимо знать. Ознакомиться с ними можно в базе знаний, в разделе Docker.

В определение контейнера нами было сказано, что контейнер хранит данные временно до его уничтожения в специальном слое «сверху контейнера». Данные удаляются вместе с контейнером. В общем виде Docker-контейнер со слоем записи можно представить так:

Структура Docker-контейнера

Но как же быть, если мы хотим, скажем, запускать базы данных или иные приложения в контейнере, для которых важна целостность данных? Docker предлагает два решения:

  1. Монтирование папки с хоста к контейнеру. Такое решение отлично подходит для разработки и отладки приложения, когда вносимые изменения на хосте сразу отражаются в контейнере. Конечно, для продакшна такой подход не годится.
  2. Создание специальных томов для хранения данных — Docker volume. DV — это обычные каталоги хоста, которые могут быть смонтированы как отдельные файловые системы (bind mounting) внутри контейнера.

Лучше всегда использовать второй вариант. Подключается Docker volume к контейнеру двумя различными способами: с помощью команды docker run с ключом -v — docker run —name python —rm -v home/test-volume/ : /data/ -d (сначала идёт путь к папке хоста, затем указывается папка монтирования) или через инструкцию VOLUME /data в Dockerfile. Результат будет одинаковым.

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

По умолчанию демон Docker использует собственный драйвер Docker runc, который тесно связан со следующими механизмами ядра:

  • Cgroups (контрольные группы) — механизм управления ресурсами, используемыми контейнером (процессор, оперативная память и т.д.). С помощью cgroups Docker также реализует возможность остановки контейнеров — docker pause (freezing и unfreezing).
  • Namespaces (пространства имен) — механизм изоляции контейнеров, гарантирующий, что файловая система, имя хоста, пользователи, сетевая среда и процессы любого контейнера полностью отделены от остальной части системы.

Ещё одна технология, которую Docker использует для хранения слоев в контейнере — файловая система с каскадно-объединенным монтированием (Union File System – UnionFS). Как видите Docker умело использует уже хорошо работающие технологии, и в этом его сила. Именно поэтому ранее мы выпустили большую обзорную статью о контейнеризации и разобрали там базовые механизмы ядра, использующиеся в контейнеризации.

История контейнеризации

История контейнеризации

Из статьи вы узнаете, что такое cgroups и namespaces, как они работают и, какими технологиями пользовались до их появления.

Сами по себе контейнеры не эфемерны, более того Docker их не скрывает и вы можете совершенно спокойно заглянуть в них. Они располагаются здесь: /var/lib/docker/containers. Обращаться к контейнеру как к набору файлов бывает полезно, когда вам нужно прочитать логи контейнера.

Подытожим, что мы узнали о Docker-контейнерах:

  1. Docker-контейнер — это запущенный Docker-образ со специальным слоем для записи и временного хранения информации.
  2. В одном контейнере должен находится один процесс — это философия Docker.
  3. Контейнеры полностью изолированы от хостовой ОС и других контейнеров.
  4. Контейнеры хранятся в виде папок и файлов в директории /var/lib/docker/containers .
  5. Контейнерам могут быть назначены внешние порты инструкцией EXPOSE и ключом -P команды docker run .
  6. Контейнеры могут сохранять информацию после уничтожения в томах Docker volume.

Как вы наверное уже догадались, условия запуска контейнера могут быть заданы двумя путями: прописаны в конфигурационном файле — Dockerfile или указаны в качестве аргументов и ключей команды docker run . Разберём подробнее вариант с указанием инструкций в Dockerfile.

Dockerfile

Docker-контейнер

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

Например, мы изменили последнюю инструкцию в Dockerfile и собрали образ заново. Docker не будет заново всё пересобирать. Он возьмет все предшествующие слои и переиспользует их. Вот как образно выглядит соотношение инструкций в Dockerfile со слоями в Docker-образе:

Существуют определенные правила и логика заполнения Dockerfile. Разберем базовые инструкции на примере Dockerfile с иллюстрации выше.

Любой код или набор инструкций выполняется сверху вниз. Поэтому Dockerfile всегда начинается с открывающей инструкции FROM , которая говорит демону Docker, какой образ для основы нужно взять. Если образа локально нет — он будет скачан с Docker hub.

Далее идет инструкция RUN с определенной командой. В нашем случае мы использовали команду mkdir -p для создания папки /app. Инструкций RUN может быть неограниченное количество, но стоит помнить, что каждая инструкция создает свой слой, поэтому хорошей практикой является запись цепочки команд через &&: RUN comand_1 && comand_2 && comand_3 .

Есть инструкции логически связанные между собой. Инструкция WORKDIR устанавливает активный рабочий каталог. Все последующие команды, такие как COPY , RUN , CMD и некоторые другие будут выполнены из рабочего каталога, установленного через WORKDIR .

С инструкцией COPY всё просто. Первым аргументом указывается папка для копирования, а вторым аргументом — папка в контейнере куда будут помещены файлы из копируемой директории. В нашем случае, из текущего каталога (“.” — каталог, в котором находится пользователь, “..” — каталог выше относительно “.”.), в котором находится пользователь, был скопирован файл requirements.txt и помещен в папку /app в контейнере.

Инструкцию RUN мы рассмотрели ранее. Тут лишь хотим обратить ваше внимание на её поведение в сочетании с инструкцией WORKDIR . Ранее инструкция COPY перенесла файл requirements.txt в контейнер. Кстати, в качестве финального пути мы могли указать “.”, так как инструкция WORKDIR установила в качестве рабочей директории контейнера папку /app . И теперь команда RUN будет выполнена именно из директории /app .

Финальной инструкцией в любом Dockerfile является CMD или ENTRYPOINT . В отличие от других инструкций CMD может быть только одна и она может быть переопределена при старте контейнера командой docker run . Инструкция CMD наследует условия установленные инструкцией WORKDIR .

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

Однако после запуска контейнера «постучаться» на 80 порт к нему мы не сможем. Так как для подтверждения инструкции EXPOSE используется ключ -P команды docker run . Если требуется прокинуть порт и переназначить его снаружи — используется следующая команда: docker run -p 80:80 —name test_cont -d .

Подробнее об инструкциях Dockerfile и их специфики вы можете узнать из нашей статьи в базе знаний.

Итак, мы познакомились с основными элементами экосистемы Docker. Есть ещё специальная надстройка для управления множеством контейнеров Docker-compose, ей мы посвятим отдельную статью с подробным разбором, а пока подведем итог.

Что же такое Docker?

Docker

Docker — это система упаковки, доставки и развертывания приложений, распространяющаяся бесплатно. Docker состоит из следующих компонентов: Docker host, Docker daemon, Docker client, Docker-compose (не входит в стандартную поставку).

Центральный системный элемент инфраструктуры Docker — Docker daemon. Именно он создаёт образы и контейнеры, следит за их состоянием, управляет сетевым окружением контейнеров и работает с локальным и удалённым репозиторием.

Двумя основными сущностями, которыми оперирует Docker являются: образ и контейнер. Эти понятия тесно связаны.

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

Docker-контейнер — это запущенный и изолированный образ с дополнительным верхним write/read-слоем, хранящим временные данные, которые уничтожаются после удаления контейнера. Контейнерам можно назначать лимиты ресурсов и строить между ними сети. Для управления ресурсами используются cgroups, а для изоляции — namespaces.

Образы собираются исходя из инструкций заданных в специальном конфигурационном файле — Dockerfile. Контейнеры при запуске также используют часть инструкций Dockerfile и опции команды docker run. А для управления кластером или группой контейнеров используется надстройка Docker-compose и конфигурационный файл Docker-compose.yml.

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

Docker отлично справляется с созданием и управлением образами и небольшим количеством контейнеров, однако современные инфраструктуры состоят из 100 микросервисов, для их менеджмента используется Kubernetes. О нём мы расскажем в ближайших публикациях, а пока мы готовим материалы, вы можете поупражняться в Docker, используя самые доступные серверы 1cloud на базе VMware и статьи из нашей базы знаний.

Добавить комментарий

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