Длительность: ~30 минут
Контекст: Поздравляю! Ваш первый торговый бот уже работает в production. Вы настроили Docker, мониторинг, бэкапы и CI/CD. Он стабильно работает и, надеемся, приносит прибыль. Но рынок не стоит на месте, и у вас появилась новая идея — новая стратегия для другой торговой пары. Что делать? Покупать второй VPS? Удваивать расходы? Нет. Давайте поступим умнее и научимся размещать несколько ботов на одной машине, экономя деньги и не теряя в стабильности.
Прежде чем мы погрузимся в детали, давайте определим несколько понятий простыми словами. Это наша основа.
Вот как меняется наш подход:
❌ ДО (Дорого и неэффективно):
VPS_1 (€10/мес)
└── Бот_BTC
└── Postgres
└── Grafana
VPS_2 (€10/мес) - ???
└── Бот_ETH
└── Postgres
└── Grafana
ИТОГО: ~€20/мес
✅ ПОСЛЕ (Экономно и централизованно):
VPS_1 (€10/мес)
├── Бот_BTC (свой контейнер)
├── Бот_ETH (свой контейнер)
│
└── Общая инфраструктура
├── Postgres (общая база)
└── Grafana (общий мониторинг)
ИТОГО: ~€10/мес
Давайте назовем нашего студента Алексеем. Его бот, торгующий парой BTC/USDT, уже три месяца стабильно работает на небольшом VPS. Алексей доволен. За это время он разработал и протестировал новую стратегию для ETH/USDT. Она выглядит еще более многообещающей.
И вот он стоит перед выбором. "Я хочу запустить второго бота, — думает Алексей, — но я боюсь. Что если они начнут конфликтовать? Вдруг новый бот 'съест' всю память, и мой старый, проверенный BTC-бот упадет в самый ответственный момент? А что если они как-то перезапишут данные друг друга в базе данных? Покупать второй VPS — это значит удвоить расходы на инфраструктуру. Я хочу реинвестировать прибыль в торговлю, а не в железо".
Эта боль абсолютно реальна. Без правильного подхода два бота на одной машине могут превратиться в двух пауков в одной банке. Наша задача — сделать из них дружных соседей по коммунальной квартире, где у каждого своя комната, но кухня и ванная — общие.
Это ключевой "Ага!"-момент. Секрет не в том, чтобы изолировать всё, а в том, чтобы грамотно разделить зоны ответственности.
.env файлах.trades_btc и trades_eth), либо, что еще лучше, с разными схемами. Это экономит ресурсы и упрощает бэкапы.btc:last_price, eth:last_price) или разные базы данных внутри одного Redis.Теперь превратим наши принципы в код. Возьмем ваш существующий docker-compose.yml для одного бота и расширим его для второго.
Основное изменение: в секции services у нас теперь будет не один бот, а два — bot_btc и bot_eth. Каждый со своим env_file.
# docker-compose.yml
version: '3.8'
services:
# ==================================================
# Первый бот: BTC/USDT
# ==================================================
bot_btc:
container_name: bot_btc
build:
context: ./bots/btc_bot # Указываем путь к Dockerfile и коду первого бота
env_file:
- ./bots/btc_bot/.env # У него свой файл с настройками
restart: unless-stopped
depends_on:
- postgres
networks:
- backend
# ==================================================
# Второй бот: ETH/USDT
# ==================================================
bot_eth:
container_name: bot_eth
build:
context: ./bots/eth_bot # Указываем путь к Dockerfile и коду второго бота
env_file:
- ./bots/eth_bot/.env # И у него свой файл с настройками
restart: unless-stopped
depends_on:
- postgres
networks:
- backend
# ==================================================
# Общая инфраструктура
# ==================================================
postgres:
container_name: postgres
image: postgres:14-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: trading_bots
ports:
- "5432:5432" # Пробрасываем порт для удобства подключения извне (например, DBeaver)
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
networks:
- backend
grafana:
container_name: grafana
image: grafana/grafana:latest
ports:
- "3000:3000" # Пробрасываем порт для доступа к веб-интерфейсу
volumes:
- grafana_data:/var/lib/grafana
restart: unless-stopped
networks:
- backend
# ==================================================
# Настройки сетей и volumes
# ==================================================
volumes:
postgres_data:
grafana_data:
networks:
backend:
driver: bridge
Теперь, когда вы запустите docker-compose up -d, Docker поднимет оба бота и общую инфраструктуру. Каждый бот будет использовать свои настройки из своего .env файла, но оба будут подключаться к одной и той же базе данных postgres по адресу host=postgres.
Чтобы один бот не "съел" всю память и процессор, добавим ограничения. Это делается с помощью ключа deploy. Он гарантирует, что даже если в коде бота есть утечка памяти, она не затронет соседа и всю систему.
Добавим этот блок в описание сервисов bot_btc и bot_eth в нашем docker-compose.yml:
# ... фрагмент docker-compose.yml для одного из ботов ...
bot_btc:
# ... все предыдущие настройки ...
deploy:
resources:
limits:
cpus: '0.50' # Может использовать не более 50% одного ядра CPU
memory: '512M' # Может использовать не более 512 MB RAM
reservations:
cpus: '0.25' # Гарантированно получит 25% одного ядра CPU
memory: '256M' # Гарантированно получит 256 MB RAM
Важно: ключ deploy работает в "swarm mode" или при использовании docker stack deploy. Если вы используете простой docker-compose up, для версий compose файла до 3.x и Docker Engine до 19.03 эти лимиты могут не применяться. В современных версиях Docker Compose V2 это работает "из коробки". Это страховка от плохого поведения одного из ваших приложений.
В нашем примере выше мы уже использовали базовую изоляцию, создав сеть backend. Все сервисы находятся в ней и могут общаться друг с другом по именам (bot_btc может достучаться до postgres). Никто извне не может подключиться к нашей базе данных, кроме тех сервисов, чьи порты мы явно "пробросили" (Grafana и Postgres).
Для еще большей безопасности можно создать несколько сетей. Например, frontend для сервисов, смотрящих наружу (Grafana), и backend для внутренней кухни (боты и база данных).
По умолчанию Docker пишет логи всех контейнеров в один общий поток. Это неудобно. Давайте настроим запись логов каждого бота в свой отдельный файл на сервере.
Добавим секцию logging в описание сервисов ботов:
# ... фрагмент docker-compose.yml для одного из ботов ...
bot_btc:
# ... все предыдущие настройки ...
logging:
driver: "json-file"
options:
max-size: "10m" # Максимальный размер лог-файла 10 MB
max-file: "3" # Хранить 3 последних лог-файла (ротация)
# Путь к файлу логов на хост-машине. Убедитесь, что директория существует.
path: "/var/log/docker/bot_btc.log"
Сделайте то же самое для bot_eth, указав другой путь, например, /var/log/docker/bot_eth.log. Теперь, если BTC-бот упадет, вам нужно будет смотреть только один маленький и чистый файл логов, а не продираться через сообщения от всех сервисов сразу.
Ваш сервер Grafana уже работает. Зайдите в него по адресу http://your_vps_ip:3000. Ваша задача проста:
postgres.SELECT * FROM trades WHERE bot_name = 'btc').'btc' на 'eth'.Готово! У вас есть раздельный, наглядный мониторинг для каждого из ваших активов.
Думаете, два бота — это предел? Это только начало. Чтобы доказать, что этот подход работает в реальном мире, вот пример из нашей собственной инфраструктуры проекта NEXUS.
На одном-единственном сервере Hetzner CX22 (2 vCPU, 4 GB RAM) стоимостью всего €4.79 в месяц у нас одновременно работают:
И все это работает стабильно, с разделением ресурсов, логов и конфигураций по тем же самым принципам, которые мы только что рассмотрели. Экономия очевидна.
Поздравляю! Ваши боты работают в гармонии, экономят вам деньги и приносят прибыль. Вы — настоящий хозяин своей инфраструктуры.
Но... проходит неделя, и вы замечаете странное. Раз в несколько дней один из ботов на пару минут падает. Docker его автоматически перезапускает, и он работает дальше. В логах, которые вы настроили, пусто — ошибка происходит так быстро, что вы не успеваете ее "поймать". Что это было? Кратковременный скачок нагрузки? Проблема с сетью? Ошибка в коде, которая проявляется раз в 100 000 сделок?
Как поймать ошибку, которая живет всего 5 секунд? Как анализировать поведение всей системы целиком, а не только отдельных ее частей?
Для этого нам нужен "черный ящик" для наших сервисов. Система, которая собирает ВСЕ логи от ВСЕХ ботов и сервисов в одном месте, индексирует их и позволяет делать поиск в реальном времени. Это следующий шаг к настоящему Production Mastery.
В следующем уроке мы подключим Loki...
Хочешь больше? Полный курс AI Agents включает Production-модуль + 27 других уроков
AI Agents $199 →