Теперь, когда у нас есть готовый образ приложения, выполним его деплой. Деплой через Docker содержит такие шаги:
- Скачивание нужного образа на сервера
- Остановка старого контейнера
- Запуск нового контейнера из скаченного образа
В продвинутых сценариях деплой образов выполняется с помощью 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, который тоже нужно установить. В ручную мы бы сделали это так:
# Работает на Ubuntu
apt update # обновляем список последних пакетов
apt install python3-pip
pip install docker
Теперь тоже самое, но через Ansible:
# file: ansible/release.yml
- hosts: all
tasks:
- apt:
name: python3-pip
update_cache: yes
cache_valid_time: 604800 # 1 week
- pip:
name: docker
Осталось добавить старт приложения и можно пробовать запускать. Для работы с Docker у Ansible есть специальный модуль community.docker.docker_container. У него много настроек, но нам сейчас нужны лишь некоторые:
- hosts: all
tasks:
- apt:
name: python3-pip
update_cache: yes
cache_valid_time: 604800 # 1 week
- pip:
name: docker
- community.docker.docker_container:
name: app
# Обязательно указываем тег, который хотим деплоить
# Если образа на сервере нет, Ansible его автоматически скачает
image: "hexletcomponents/devops-example-app:{{ version }}"
# Подключаем супервизор
# Если контейнер остановится, например, из-за ошибок
# супервизор Docker его перезапустит
restart_policy: always
# Запускаем, если не запущен
state: started
# Делаем доступным снаружи
ports:
- 3000:3000
env: # Настраиваем
NODE_ENV: production
Процесс деплоя состоит буквально из одной задачи, которая скачивает новый образ и перезапускает приложение.
Осталось создать inventory-файл. Здесь все просто. Добавляем группу webservers с одним сервером web1:
# ansible/inventory.yml
all:
children:
webservers: # группа веб-серверов
hosts:
web1: # имя сервера выбрано произвольно
# Поменяйте на ip вашего сервера
ansible_host: 65.108.149.193
По необходимости сюда легко добавляются новые сервера. Схема с деплоем на множество серверов рассматривается в одном из следующих уроков.
Деплой
Когда все готово, остается запустить одну команду, которая выполнит деплой:
ansible-playbook ansible/release.yml -i ansible/inventory.yml -vv --extra-vars "version=v5"
Во время деплоя передается версия, которую мы хотим выкатить. В нашем случае она совпадает с именем тега у Docker-образа и git-репозитория.
У такого способа деплоя, когда рестартует контейнер, есть одна особенность о которой нужно знать. Остановка старого контейнера и запуск нового — не моментальная операция. Какое-то время не будет запущен ни один контейнер, а значит пользователь увидит ошибку. Чтобы избежать этого, нужно перед приложением добавить реверспрокси (Nginx, Caddy, ...), в котором будет настроена обработка подобных ошибок и возврат красивой страницы с объяснением того, что происходит. Об этом в следующем уроке.
Откат
Во время деплоя могут возникнуть проблемы и тогда потребуется откат. Как его выполнять? Секрет в том, что откатов не существует. Мы всегда движемся вперед, даже если переключаемся на старую версию кода. Все что нужно — выполнить плейбук с нужной версией кода:
ansible-playbook ansible/release.yml -i ansible/inventory.yml -vv --extra-vars "version=v4"
Ситуация чуть сложнее когда у нас есть база данных, но об этом дальше по курсу.
Разделение плейбуков
Плейбук, который мы создали выше, состоит из двух независимых частей — настройки сервера и самого деплоя. В простейшем случае мы можем оставить все как есть, но настройка может усложниться и замедлить скорость деплоя. Поэтому, лучше, вынести настройку в отдельный плейбук и запускать ее независимо. Такая схема безопаснее, если вы захотите обновить сервер, то случайно не перезапустите приложение и наоборот, если захотите деплоить, то случайно не обновите сервер.
# Лучше перенести в другой файл
# file: ansible/setup.yml
- hosts: all
tasks:
- apt:
name: python3-pip
update_cache: yes
cache_valid_time: 604800 # 1 week
- pip:
name: docker
Самостоятельная работа
-
Создайте сервер в облачном провайдере и задеплойте туда devops-example-app
-
Зарегистрируйте домен в любом регистраторе на выбор. Например NameCheap.com или Reg.ru
-
Привяжите созданный домен к NS-серверам облачного провайдера. Инструкция для DO и Яндекс Облака
-
Подключите созданный домен к серверу
В результате у вас будет создан сайт доступный по домену с указанием порта, например, example.com:3000
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.