Продакшен и Деплой
2026-02-26 22:59 Diff

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

  1. Скачивание нужного образа на сервера
  2. Остановка старого контейнера
  3. Запуск нового контейнера из скаченного образа

В продвинутых сценариях деплой образов выполняется с помощью Kubernetes. А здесь мы выполняем деплой напрямую, с помощью Ansible. Почему именно он? Ansible наиболее простой и удобный инструмент, из существующих, который позволяет буквально небольшим yaml файлом описать процесс деплоя и использовать его для любого количества серверов. Ansible берет на себя обработку ошибок, параллельное выполнение и многое другое.

Подготовка сервера

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

Создайте самый дешевый сервер (Droplet в терминах DigitalOcean, Compute Cloud у Yandex Cloud) для деплоя. Его стоимость 5$ в месяц. Здесь есть хитрость, по умолчанию DO предлагает сервера с чистыми операционными системами, но если переключиться на вкладку Markeplace, то там есть Ubuntu с предустановленным Docker. То что нам нужно.

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

Когда сервер будет готов, DO покажет вам его ip-адрес. Возьмите этот адрес и попробуйте подключиться к серверу по ssh. Если у вас получилось, то можно готовиться к деплою.

Подготовка к деплою

Для деплоя нам понадобится настроенный Ansible. Установите его локально на свой компьютер. Все файлы Ansible мы будем хранить в директории ansible.

Создадим плейбук, который выполняет всю работу по деплою приложения. Первым делом нам нужно установить python-пакет docker, который используется Ansible для управления Docker. В свою очередь python-пакеты устанавливаются через pip3, который тоже нужно установить. В ручную мы бы сделали это так:

Теперь тоже самое, но через Ansible:

Осталось добавить старт приложения и можно пробовать запускать. Для работы с Docker у Ansible есть специальный модуль community.docker.docker_container. У него много настроек, но нам сейчас нужны лишь некоторые:

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

Осталось создать inventory-файл. Здесь все просто. Добавляем группу webservers с одним сервером web1:

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

Деплой

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

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

У такого способа деплоя, когда рестартует контейнер, есть одна особенность о которой нужно знать. Остановка старого контейнера и запуск нового — не моментальная операция. Какое-то время не будет запущен ни один контейнер, а значит пользователь увидит ошибку. Чтобы избежать этого, нужно перед приложением добавить реверспрокси (Nginx, Caddy, ...), в котором будет настроена обработка подобных ошибок и возврат красивой страницы с объяснением того, что происходит. Об этом в следующем уроке.

Откат

Во время деплоя могут возникнуть проблемы и тогда потребуется откат. Как его выполнять? Секрет в том, что откатов не существует. Мы всегда движемся вперед, даже если переключаемся на старую версию кода. Все что нужно — выполнить плейбук с нужной версией кода:

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

Разделение плейбуков

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