⏱ ~25 минут чтения
Вы вручную устанавливали Python и библиотеки (`pip install -r requirements.txt`) прямо на сервер. Если нужно было запустить второго бота с другой версией библиотеки, начинались проблемы ("dependency hell"). Переезд на новый сервер означал повторение всей настройки с нуля. Масштабирование было сложным и непредсказуемым.
Ваш бот и все его зависимости (база данных, кэш) упакованы в контейнеры. Вы можете запустить весь комплекс на любом сервере, где есть Docker, всего одной командой. Запуск нескольких ботов на одном сервере становится тривиальной задачей, так как они полностью изолированы друг от друга.
Представьте: ваш первый бот, которого мы настраивали в Уроке 1, уже месяц успешно торгует на Hetzner. Вы, вдохновленный успехом, написали вторую, совершенно новую стратегию. Теперь её нужно запустить. Вы подключаетесь к серверу, копируете код... и тут выясняется, что для новой стратегии нужна библиотека pandas версии 2.0, а старый бот работает на 1.5 и ломается при обновлении. Что делать? Создавать вторую виртуальную машину за 5 евро/месяц? Пытаться настроить сложные виртуальные окружения Python, которые постоянно конфликтуют? А если ботов будет десять? В этот момент ручная настройка превращается из простого решения в ночной кошмар, который мешает главному — зарабатывать деньги, а не администрировать серверы.
Давайте закрепим метафору. Раньше, чтобы запустить бота, вы приходили на "голый" сервер (пустую квартиру) и начинали завозить всё необходимое: Python (кровать), нужные библиотеки (стол, стулья), код вашего бота (телевизор). Если приезжал новый жилец (второй бот) со своей мебелью, начинался хаос и конфликты.
Docker предлагает другой подход.
Образ (Image) — это инструкция по сборке мебели из IKEA. В файле `Dockerfile` вы пишете: "1. Взять за основу комнату с отделкой 'Python 3.9'. 2. Принести инструменты из 'requirements.txt'. 3. Поставить в центр комнаты мой код. 4. Включить телевизор ('main.py')".
Контейнер (Container) — это готовая, собранная комната. Docker берёт вашу инструкцию (образ) и создаёт по ней полностью изолированное пространство. Внутри этой "комнаты" есть всё, что нужно боту, и ничего лишнего. Он не видит, что происходит в "соседних комнатах" (других контейнерах) или в основной "квартире" (сервере). Вы можете создать сколько угодно одинаковых комнат из одной инструкции.
Это решает главные проблемы: "у меня на компьютере работало" и "конфликт зависимостей". Если это работает в контейнере на вашем ноутбуке, это с 99% вероятностью так же заработает в контейнере на сервере Hetzner.
Подключитесь к вашему серверу по SSH. Большинство VPS на Hetzner работают на Ubuntu, поэтому команды приводим для него. Это займет 5 минут.
1. Обновим список пакетов и установим всё необходимое:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
2. Добавим официальный ключ GPG от Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
3. Добавим репозиторий Docker в список источников:
echo \
"deb [arch=$(dpkg --print-architecture) 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
4. Установим сам Docker Engine:
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
5. Установим docker-compose:
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
6. Проверим, что всё установилось корректно:
docker --version
docker-compose --version
Вы должны увидеть версии установленных программ. Готово! Сервер готов к контейнеризации.
В корневой папке вашего проекта с ботом создайте файл с именем `Dockerfile` (без расширения). Вот его содержимое:
# Используем официальный легковесный образ Python
FROM python:3.9-slim
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем файл с зависимостями ВНАЧАЛЕ.
# Это позволяет Docker кэшировать установку и ускорять сборку,
# если зависимости не менялись.
COPY requirements.txt .
# Устанавливаем зависимости
RUN pip install --no-cache-dir -r requirements.txt
# Копируем весь остальной код проекта в рабочую директорию
COPY . .
# Команда, которая будет выполняться при запуске контейнера
CMD ["python", "main.py"]
Разберем каждую строчку:
FROM python:3.9-slim: Начинаем с готового "фундамента". Это официальный образ от создателей Python, содержащий только самое необходимое для запуска программ на Python 3.9.WORKDIR /app: Создаем папку `/app` внутри контейнера и "заходим" в неё. Все последующие команды будут выполняться из этой папки.COPY requirements.txt .: Копируем файл `requirements.txt` с вашего компьютера в папку `/app` внутри контейнера.RUN pip install ...: Выполняем команду установки библиотек. Флаг `--no-cache-dir` нужен, чтобы не хранить кэш pip и делать образ меньше по размеру.COPY . .: Копируем всё остальное из текущей папки проекта (ваш `.py` код и т.д.) в папку `/app` контейнера.CMD ["python", "main.py"]: Указываем, какую команду запустить, когда контейнер стартует. В нашем случае — запустить главного бота.Теперь самое интересное. Нашему боту часто нужны другие сервисы. Например, Redis для быстрого кэширования цен и Postgres для хранения истории сделок. Вместо того чтобы устанавливать их на сервер вручную, мы опишем их как контейнеры.
Создайте в корне проекта файл `docker-compose.yml`:
version: '3.8'
services:
bot:
build: .
container_name: trading_bot
restart: always
depends_on:
- redis
- postgres
env_file:
- .env
redis:
image: redis:6-alpine
container_name: trading_redis
restart: always
postgres:
image: postgres:13-alpine
container_name: trading_postgres
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Что здесь происходит:
services:: Мы описываем наш "оркестр" — набор сервисов.bot:: Наш основной сервис.
build: .: Говорит docker-compose, что для этого сервиса нужно собрать образ из `Dockerfile` в текущей папке.restart: always: Очень важная строка. Если контейнер упадет (из-за ошибки в коде или на сервере), Docker автоматически его перезапустит.depends_on:: Указывает, что наш бот зависит от `redis` и `postgres`. Docker-compose сперва запустит базы данных, и только потом — нашего бота.env_file: .env: Подгружает переменные окружения (API ключи, пароли) из файла `.env`. Это безопаснее, чем хранить их в коде.redis: и postgres:: Наши базы данных.
image: redis:6-alpine: Здесь мы не строим образ сами, а берем готовый официальный образ Redis с Docker Hub. Версия `alpine` — самая маленькая.environment:: Передаем переменные окружения прямо в контейнер Postgres для создания пользователя и базы данных.volumes:: Критически важный раздел! Данные внутри контейнера временные. Если удалить контейнер Postgres, все данные пропадут. Эта строка "пробрасывает" папку с данными из контейнера (`/var/lib/postgresql/data`) в специальный раздел на диске сервера (`postgres_data`). Теперь, даже если вы перезапустите или обновите контейнер, ваши данные останутся в целости.Важный момент: теперь ваш бот должен подключаться к базам данных по их именам сервисов. В коде подключения к Postgres хостом будет `postgres`, а к Redis — `redis`, а не `localhost` или `127.0.0.1`.
Теперь, когда все файлы готовы, скопируйте ваш проект на сервер Hetzner (например, через `git clone`). Зайдите в папку проекта и выполните одну команду:
docker-compose up -d
Всё. Docker-compose прочитает ваш `yml` файл, соберет образ для бота (если это первый запуск), скачает образы для Redis и Postgres и запустит все три контейнера в фоновом режиме (`-d` значит "detached").
Полезные команды:
docker-compose psdocker-compose logs -f bot (Нажмите `Ctrl+C` чтобы выйти).docker-compose downDocker — это мощный инструмент, но он добавляет дополнительный слой абстракции. Если ваш проект — это один простой скрипт, который вы запускаете раз в неделю, и у вас нет планов по его расширению или переносу, то настройка Docker может быть избыточной. Наш старый добрый `systemd` из Урока 1 отлично справится с этой задачей и будет проще в поддержке для такого простого случая. Всегда выбирайте инструмент под задачу. Docker сияет там, где важны изоляция, переносимость и масштабирование.
Отлично, теперь у нас есть надежный способ запускать одного бота со всеми его зависимостями. Но что, если у вас 10 клиентов, и для каждого нужно запустить свою копию бота с разными настройками и API-ключами? Создавать 10 папок и запускать 10 раз `docker-compose up`? Это быстро превратится в хаос. А как убедиться, что один "прожорливый" бот не съест всю память и CPU, оставив других без ресурсов? Как элегантно управлять этим "флотом" ботов?
В Уроке 9 мы разберем архитектуру для управления целым флотом ботов, используя продвинутые возможности Docker и посмотрим на такие инструменты, как Docker Swarm или Portainer.
А в следующем уроке мы сделаем наш health-check эндпоинт (или веб-интерфейс для управления ботом) доступным извне через доменное имя, защитив его бесплатным SSL-сертификатом. Это сделает мониторинг и управление ботом еще удобнее и безопаснее.
[tokens: in=666 out=3775 thinking=2700 | cost=$0.0656]Хочешь больше? Полный курс AI Agents включает Production-модуль + 27 других уроков
AI Agents $199 →