Docker 28.07.2026 223 просмотров

Self-hosted AI-стек на Docker Compose: n8n + Ollama + Qdrant в одном файле

#Docker #self-hosted #n8n #Ollama #Qdrant #RAG #Docker Compose
Self-hosted AI-стек на Docker Compose: n8n + Ollama + Qdrant в одном файле
Собираем весь AI-стек в одном docker-compose.yml: оркестратор n8n, локальная LLM через Ollama, векторная база Qdrant для RAG. Без платы за токены.

Зачем собирать весь AI-стек в одном Docker Compose

Для практической AI-автоматизации редко достаточно одного n8n. Нужна связка из нескольких сервисов: оркестратор воркфлоу (n8n), локальная LLM (Ollama) и векторная база для RAG (Qdrant). Запускать их отдельными командами неудобно — теряются зависимости запуска, общая сеть, единый бэкап. Правильный подход — один docker-compose.yml, который поднимает весь стек одной командой.

Эта связка особенно ценна для российского бизнеса: данные не покидают сервер, нет зависимости от OpenAI API, нет платы за токены — всё работает локально и подходит под требования ФЗ-152.

Архитектура self-hosted AI-стека

  • n8n — визуальный оркестратор: принимает вебхуки, запускает воркфлоу, вызывает остальные сервисы
  • Ollama — локальный LLM-сервер (Qwen, Llama, DeepSeek) с REST API в формате OpenAI
  • Qdrant — векторная база данных для семантического поиска и RAG
  • PostgreSQL — основная база данных n8n (вместо SQLite для production)

Все сервисы общаются внутри одной Docker-сети по именам контейнеров — никаких портов не нужно открывать наружу, кроме n8n (через nginx).

Полный docker-compose.yml

version: "3.8"

services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n_user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n_user"]
      interval: 10s
      retries: 5

  ollama:
    image: ollama/ollama
    volumes:
      - ./data/ollama:/root/.ollama
    restart: unless-stopped
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    # Удалите блок deploy выше, если нет GPU — будет работать на CPU

  qdrant:
    image: qdrant/qdrant
    volumes:
      - ./data/qdrant:/qdrant/storage
    restart: unless-stopped

  n8n:
    image: n8nio/n8n:latest
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n_user
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_HOST=${N8N_HOST}
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${N8N_HOST}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # Внутри n8n обращайтесь к сервисам по именам контейнеров:
      # Ollama: http://ollama:11434
      # Qdrant:  http://qdrant:6333
    volumes:
      - ./data/n8n:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      ollama:
        condition: service_started
      qdrant:
        condition: service_started
    ports:
      - "5678:5678"
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/n8n.conf:/etc/nginx/conf.d/default.conf
      - /etc/letsencrypt:/etc/letsencrypt:ro
    depends_on:
      - n8n
    restart: unless-stopped

Запуск стека

# .env файл рядом с docker-compose.yml
echo "POSTGRES_PASSWORD=$(openssl rand -hex 16)" >> .env
echo "N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
echo "N8N_HOST=n8n.вашдомен.ru" >> .env

# Поднять весь стек одной командой
docker compose up -d

# Проверить статус всех сервисов
docker compose ps

# Скачать модель в Ollama (после старта контейнера)
docker exec -it $(docker compose ps -q ollama) ollama pull qwen3:8b

Настройка n8n для работы с Ollama и Qdrant внутри сети

Главное преимущество единого docker-compose.yml — сервисы видят друг друга по имени контейнера, без localhost и портов наружу:

  • Ollama Credential в n8n: Base URL — http://ollama:11434 (не localhost!)
  • Qdrant через HTTP Request: эндпоинт — http://qdrant:6333/collections/мои_документы/points/search

Пример воркфлоу RAG целиком внутри стека: документ → embeddings через Ollama (модель nomic-embed-text) → сохранение вектора в Qdrant → при вопросе пользователя — поиск похожих векторов в Qdrant → передача найденного контекста в LLM-ноду Ollama → ответ.

Минимальные требования к серверу для полного стека

КомпонентRAMДиск
n8n + PostgreSQL1–2 GB10 GB
Qdrant (до 1М векторов)1–2 GB5–20 GB
Ollama + модель 8B8–10 GB10 GB на модель
Итого минимум12–16 GB40–60 GB

На сервере с GPU (рекомендуется для Ollama) скорость генерации вырастает в 5–10 раз. Без GPU на CPU стек тоже работает, но ответы LLM будут генерироваться заметно медленнее (десятки секунд на ответ вместо секунд).

Бэкап всего стека одной командой

#!/bin/bash
# backup-stack.sh
DATE=$(date +%Y%m%d_%H%M)
mkdir -p /backups/$DATE

docker exec postgres pg_dump -U n8n_user n8n | gzip > /backups/$DATE/n8n_db.sql.gz
tar -czf /backups/$DATE/qdrant_data.tar.gz ./data/qdrant
tar -czf /backups/$DATE/n8n_data.tar.gz ./data/n8n

echo "Backup completed: /backups/$DATE"

Модели Ollama бэкапить не нужно — они скачиваются заново командой ollama pull за несколько минут, не имеет смысла хранить их копии.

Почему это лучше, чем облачные API

ПараметрOpenAI/Claude APISelf-hosted стек
Стоимость при росте объёмаРастёт линейно с токенамиФиксированная (только сервер)
Данные клиентовУходят за рубежОстаются на вашем сервере
Соответствие ФЗ-152НетДа (при сервере в РФ)
Задержка ответаЗависит от интернетаЗависит только от вашего железа
Качество моделиВыше (GPT-4o, Claude)Близкое для большинства задач (Qwen 3)

Часто задаваемые вопросы

Можно ли запустить весь AI-стек без GPU?

Да, удалите блок deploy/resources из секции ollama в docker-compose.yml — Ollama автоматически переключится на CPU-инференс. Для моделей 7-8B на CPU это будет работать, но медленнее: 5-15 токенов в секунду вместо 50-100 на GPU.

Как n8n обращается к Ollama и Qdrant в одном Docker Compose?

Все сервисы в одном docker-compose.yml автоматически попадают в общую Docker-сеть и видят друг друга по имени сервиса вместо localhost. Используйте http://ollama:11434 для Ollama и http://qdrant:6333 для Qdrant — порты наружу открывать не нужно.

Сколько стоит содержать такой self-hosted AI-стек?

VPS с 16 GB RAM и GPU обходится от 3000-5000 рублей в месяц у российских провайдеров (Selectel, Timeweb). Без GPU, только на CPU — от 1500-2000 рублей за 16 GB RAM. Это разовая фиксированная стоимость независимо от объёма запросов, в отличие от платы за токены облачных API.

Полезные материалы по теме