diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb6d0bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# Зависимости +node_modules/ +/.pnp +.pnp.js + +# Логи +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Файлы окружения +.env +.env.local +.env.development.local +.env.test.local +.env.production.local +backend/.env +frontend/.env + +# Файлы сборки +/dist +/build +/out + +# Кэши и временные файлы +.cache/ +.temp/ +.DS_Store +.idea/ +.vscode/ +*.swp +*.swo + +# Docker тома +/data + +# Приватные ключи и сертификаты +*.pem +*.key + +# Локальные настройки +.prettierrc.local +.eslintrc.local + +# Файлы базы данных +*.db +*.sqlite +*.sqlite3 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2eab8c --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# DApp-for-Business + +Бизнес-платформа для работы с блокчейн и интеграцией ИИ. + +## Требования + +- Docker и Docker Compose +- Git + +## Быстрый запуск + +Чтобы запустить проект одной командой, выполните следующие шаги: + +1. Клонируйте репозиторий: +```bash +git clone https://github.com/yourusername/DApp-for-Business.git +cd DApp-for-Business +``` + +2. Настройте переменные окружения: +```bash +# Создайте файлы .env из примеров +cp backend/.env.example backend/.env +cp frontend/.env.example frontend/.env + +# Отредактируйте файлы .env с вашими настройками +nano backend/.env +nano frontend/.env +``` + +3. Запустите скрипт установки: +```bash +./setup.sh +``` + +Скрипт автоматически: +- Проверит наличие Docker и Docker Compose +- Запустит PostgreSQL в контейнере +- Запустит Ollama и загрузит модель qwen2.5:7b +- Запустит backend и frontend сервисы +- Выведет адреса для доступа к сервисам + +## Доступные сервисы + +После успешного запуска вы получите доступ к следующим сервисам: + +- Frontend: http://localhost:5173 +- Backend API: http://localhost:8000 +- Ollama API: http://localhost:11434 +- PostgreSQL: localhost:5432 (по умолчанию dapp_db/dapp_user/dapp_password) + +## Ручной запуск + +Если вы хотите запустить проект вручную: + +```bash +# Запуск в фоновом режиме +docker compose up -d + +# Запуск с логами +docker compose up + +# Остановка сервисов +docker compose down + +# Остановка сервисов и удаление томов +docker compose down -v +``` + +## Безопасность + +По умолчанию проект настроен с базовыми учетными данными для разработки. Перед использованием в продакшене: + +1. **Измените все пароли и ключи в .env файлах** +2. **Не публикуйте .env файлы в репозитории** (они добавлены в .gitignore) +3. **Обновите SESSION_SECRET для защиты сессий** +4. **Используйте безопасные пароли для базы данных** +5. **Настройте SSL/TLS для продакшен-окружения** + +## Переменные окружения + +Основные переменные, которые следует настроить: + +- `DB_USER`, `DB_PASSWORD` - учетные данные для базы данных +- `SESSION_SECRET` - секрет для шифрования сессий +- `PRIVATE_KEY` - приватный ключ для подписи транзакций +- `EMAIL_*` - настройки почтового сервера +- `TELEGRAM_BOT_TOKEN` - токен для Telegram бота + +## Примечания + +- Загрузка модели qwen2.5:7b может занять некоторое время в зависимости от скорости интернета +- Для использования GPU Ollama требуются установленные драйверы NVIDIA и nvidia-container-toolkit \ No newline at end of file diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..809176e --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,41 @@ +PORT=8000 +NODE_ENV=development +SESSION_SECRET=your_session_secret + +# RPC URLs +RPC_URL_ETH=https://your-ethereum-rpc-url +RPC_URL_POLYGON=https://your-polygon-rpc-url +RPC_URL_BSC=https://your-bsc-rpc-url +RPC_URL_ARBITRUM=https://your-arbitrum-rpc-url +RPC_URL=https://your-default-rpc-url +ETHEREUM_NETWORK_URL=https://your-ethereum-network-url +PRIVATE_KEY=your_private_key_here +ETHERSCAN_API_KEY=your_etherscan_api_key + +# Database +DATABASE_URL=postgresql://dapp_user:dapp_password@postgres:5432/dapp_db +DB_HOST=postgres +DB_PORT=5432 +DB_NAME=dapp_db +DB_USER=dapp_user +DB_PASSWORD=dapp_password + +# Email Configuration +EMAIL_USER=your_email@example.com +EMAIL_PASSWORD=your_email_password +EMAIL_SMTP_HOST=smtp.example.com +EMAIL_SMTP_PORT=465 +EMAIL_IMAP_HOST=imap.example.com +EMAIL_IMAP_PORT=993 + +# Ollama AI Configuration +OLLAMA_BASE_URL=http://ollama:11434 +OLLAMA_EMBEDDINGS_MODEL=qwen2.5:7b +OLLAMA_MODEL=qwen2.5:7b + +# Telegram Bot +TELEGRAM_BOT_TOKEN=your_telegram_bot_token +TELEGRAM_BOT_USERNAME=your_bot_username + +# Frontend URL +FRONTEND_URL=http://localhost:5173 \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index bcf7147..62294e8 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,45 +1,44 @@ # Зависимости node_modules/ -yarn-error.log - -# Переменные окружения -.env -.env.local -.env.development -.env.test -.env.production +/.pnp +.pnp.js # Логи -logs/* -!logs/.gitkeep +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* -# Кэш и временные файлы +# Файлы окружения +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Кэши и временные файлы .cache/ -cache/ -dist/ -build/ -tmp/ -temp/ - -# Артефакты Hardhat -artifacts/ -cache/ -typechain/ -typechain-types/ - -# Файлы покрытия кода -coverage/ -coverage.json - -# Файлы IDE +.temp/ +.DS_Store .idea/ .vscode/ -*.sublime-project -*.sublime-workspace +*.swp +*.swo -# Системные файлы -.DS_Store -Thumbs.db +# Compiled output +/dist +/build -# Файлы сессий -sessions/ \ No newline at end of file +# Приватные ключи и сертификаты +*.pem +*.key + +# Локальные настройки +.prettierrc.local +.eslintrc.local + +# Файлы базы данных +*.db +*.sqlite +*.sqlite3 \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..2e99769 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,21 @@ +FROM node:20-alpine + +WORKDIR /app + +# Устанавливаем зависимости, включая Python для node-gyp +RUN apk add --no-cache python3 make g++ + +# Копируем package.json и yarn.lock для установки зависимостей +COPY package.json yarn.lock ./ + +# Устанавливаем зависимости +RUN yarn install --frozen-lockfile + +# Копируем остальные файлы проекта +COPY . . + +# Экспозим порт +EXPOSE 8000 + +# Команда запуска по умолчанию +CMD ["yarn", "run", "dev"] \ No newline at end of file diff --git a/backend/app.js b/backend/app.js index 9a4fb4e..0da8959 100644 --- a/backend/app.js +++ b/backend/app.js @@ -22,7 +22,7 @@ const tokensRouter = require('./routes/tokens'); const app = express(); // Указываем хост явно -app.set('host', '127.0.0.1'); +app.set('host', '0.0.0.0'); app.set('port', process.env.PORT || 8000); // Настройка CORS diff --git a/backend/db.js b/backend/db.js index cdc7d9e..2b13556 100644 --- a/backend/db.js +++ b/backend/db.js @@ -1,6 +1,14 @@ const { Pool } = require('pg'); require('dotenv').config(); +// Выводим настройки подключения (без пароля) +console.log('Настройки подключения к базе данных:'); +console.log('DATABASE_URL:', process.env.DATABASE_URL?.replace(/:([^:@]+)@/, ':***@')); +console.log('DB_HOST:', process.env.DB_HOST); +console.log('DB_PORT:', process.env.DB_PORT); +console.log('DB_NAME:', process.env.DB_NAME); +console.log('DB_USER:', process.env.DB_USER); + // Создаем пул соединений с базой данных const pool = new Pool({ connectionString: process.env.DATABASE_URL, @@ -11,10 +19,30 @@ const pool = new Pool({ pool.query('SELECT NOW()', (err, res) => { if (err) { console.error('Ошибка подключения к базе данных:', err); - console.log('Переключение на временное хранилище данных в памяти...'); - - // Если не удалось подключиться к базе данных, используем временное хранилище - module.exports = createInMemoryStorage(); + + // Пробуем альтернативное подключение + console.log('Попытка альтернативного подключения через прямые параметры...'); + + const altPool = new Pool({ + host: process.env.DB_HOST || 'localhost', + port: parseInt(process.env.DB_PORT || '5432'), + database: process.env.DB_NAME || 'dapp_db', + user: process.env.DB_USER || 'dapp_user', + password: process.env.DB_PASSWORD, + }); + + altPool.query('SELECT NOW()', (altErr, altRes) => { + if (altErr) { + console.error('Альтернативное подключение тоже не удалось:', altErr); + console.log('Переключение на временное хранилище данных в памяти...'); + module.exports = createInMemoryStorage(); + } else { + console.log('Альтернативное подключение успешно:', altRes.rows[0]); + // Заменяем основной пул на альтернативный + module.exports.pool = altPool; + module.exports.query = (text, params) => altPool.query(text, params); + } + }); } else { console.log('Успешное подключение к базе данных:', res.rows[0]); } diff --git a/backend/db/migrations/005_messages.sql b/backend/db/migrations/005_messages.sql index 5beca71..181d5db 100644 --- a/backend/db/migrations/005_messages.sql +++ b/backend/db/migrations/005_messages.sql @@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS messages ( metadata JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, role VARCHAR(20) NOT NULL DEFAULT 'user', - guest_message_id INTEGER, + user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, tokens_used INTEGER DEFAULT 0, is_processed BOOLEAN DEFAULT FALSE ); @@ -17,4 +17,5 @@ CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation CREATE INDEX IF NOT EXISTS idx_messages_sender_type ON messages(sender_type); CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at); CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel); -CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata); \ No newline at end of file +CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata); +CREATE INDEX IF NOT EXISTS idx_messages_user_id ON messages(user_id); \ No newline at end of file diff --git a/backend/db/migrations/functions/link_guest_messages.sql b/backend/db/migrations/functions/link_guest_messages.sql index 5c37f1c..b337ad4 100644 --- a/backend/db/migrations/functions/link_guest_messages.sql +++ b/backend/db/migrations/functions/link_guest_messages.sql @@ -53,7 +53,7 @@ BEGIN content, role, channel, - guest_message_id, + user_id, created_at ) SELECT @@ -63,14 +63,16 @@ BEGIN content, CASE WHEN is_ai THEN 'assistant' ELSE 'user' END, 'chat', - id, -- Сохраняем связь с гостевым сообщением + p_user_id, created_at FROM guest_messages WHERE guest_id = p_guest_id - -- Проверка, чтобы избежать дублирования сообщений + -- Проверка, чтобы избежать дублирования сообщений на основе содержимого и времени AND NOT EXISTS ( SELECT 1 FROM messages m - WHERE m.guest_message_id = guest_messages.id + WHERE m.conversation_id = v_conversation_id + AND m.content = guest_messages.content + AND m.created_at = guest_messages.created_at ) ORDER BY created_at RETURNING id diff --git a/backend/scripts/check-ollama-models.js b/backend/scripts/check-ollama-models.js index d9ba28d..48a5e44 100644 --- a/backend/scripts/check-ollama-models.js +++ b/backend/scripts/check-ollama-models.js @@ -18,8 +18,8 @@ async function checkOllamaModels() { }); console.log('\nДля использования конкретной модели, укажите ее в .env файле:'); - console.log('OLLAMA_EMBEDDINGS_MODEL=mistral:7b-instruct-q4_K_M'); - console.log('OLLAMA_MODEL=mistral:7b-instruct-q4_K_M'); + console.log('OLLAMA_EMBEDDINGS_MODEL=qwen2.5'); + console.log('OLLAMA_MODEL=qwen2.5'); } else { console.log('Не удалось получить список моделей'); } diff --git a/backend/scripts/wait-for-postgres.sh b/backend/scripts/wait-for-postgres.sh new file mode 100755 index 0000000..a39c7c5 --- /dev/null +++ b/backend/scripts/wait-for-postgres.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +host="$1" +shift +port="$1" +shift +cmd="$@" + +until PGPASSWORD=$DB_PASSWORD psql -h "$host" -U "$DB_USER" -p "$port" -d "$DB_NAME" -c '\q'; do + >&2 echo "Ожидание подключения к PostgreSQL..." + sleep 1 +done + +>&2 echo "PostgreSQL запущен - выполнение команды" +exec $cmd \ No newline at end of file diff --git a/backend/services/ai-assistant.js b/backend/services/ai-assistant.js index 0f5cf84..5f20f7e 100644 --- a/backend/services/ai-assistant.js +++ b/backend/services/ai-assistant.js @@ -7,7 +7,7 @@ const fetch = require('node-fetch'); class AIAssistant { constructor() { this.baseUrl = process.env.OLLAMA_BASE_URL || 'http://localhost:11434'; - this.defaultModel = process.env.OLLAMA_MODEL || 'mistral:7b-instruct-q4_K_M'; + this.defaultModel = process.env.OLLAMA_MODEL || 'qwen2.5'; } // Создание экземпляра ChatOllama с нужными параметрами diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..efdcc63 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,99 @@ +version: '3.8' + +services: + postgres: + image: postgres:16-alpine + container_name: dapp-postgres + restart: unless-stopped + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + POSTGRES_DB: ${DB_NAME:-dapp_db} + POSTGRES_USER: ${DB_USER:-dapp_user} + POSTGRES_PASSWORD: ${DB_PASSWORD:-dapp_password} + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-dapp_user} -d ${DB_NAME:-dapp_db}"] + interval: 5s + timeout: 5s + retries: 5 + + ollama: + image: ollama/ollama:latest + container_name: dapp-ollama + restart: unless-stopped + volumes: + - ollama_data:/root/.ollama + ports: + - "11434:11434" + command: serve + + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: dapp-backend + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + ollama: + condition: service_started + volumes: + - ./backend:/app + - backend_node_modules:/app/node_modules + environment: + - NODE_ENV=${NODE_ENV:-development} + - PORT=${PORT:-8000} + - DB_HOST=postgres + - DB_PORT=5432 + - DB_NAME=${DB_NAME:-dapp_db} + - DB_USER=${DB_USER:-dapp_user} + - DB_PASSWORD=${DB_PASSWORD:-dapp_password} + - DATABASE_URL=postgresql://${DB_USER:-dapp_user}:${DB_PASSWORD:-dapp_password}@postgres:5432/${DB_NAME:-dapp_db} + - OLLAMA_BASE_URL=http://ollama:11434 + - OLLAMA_MODEL=${OLLAMA_MODEL:-qwen2.5:7b} + - OLLAMA_EMBEDDINGS_MODEL=${OLLAMA_EMBEDDINGS_MODEL:-qwen2.5:7b} + - FRONTEND_URL=http://localhost:5173 + ports: + - "8000:8000" + command: sh -c "yarn run dev" + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: dapp-frontend + restart: unless-stopped + depends_on: + - backend + volumes: + - ./frontend:/app + - frontend_node_modules:/app/node_modules + ports: + - "5173:5173" + command: yarn run dev -- --host 0.0.0.0 + + ollama-setup: + image: curlimages/curl:latest + container_name: dapp-ollama-setup + depends_on: + - ollama + restart: on-failure + command: | + sh -c " + echo 'Waiting for Ollama to be ready...' + until curl -s http://ollama:11434/api/tags >/dev/null; do + sleep 5 + done + echo 'Ollama is ready, pulling qwen2.5-7b model...' + curl -X POST http://ollama:11434/api/pull -d '{\"name\":\"${OLLAMA_MODEL:-qwen2.5:7b}\"}' -H 'Content-Type: application/json' + echo 'Done!' + " + +volumes: + postgres_data: + ollama_data: + backend_node_modules: + frontend_node_modules: \ No newline at end of file diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..b29075d --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,3 @@ +VITE_APP_ETHEREUM_NETWORK_URL=https://your-ethereum-network-url + +VITE_API_URL=http://localhost:8000 \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore index f6edd43..1d15916 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,23 +1,7 @@ # Зависимости node_modules/ -yarn-error.log - -# Переменные окружения -.env -.env.local -.env.development -.env.test -.env.production - -# Сборка -dist/ -dist-ssr/ -build/ - -# Кэш -.cache/ -.temp/ -.vite/ +/.pnp +.pnp.js # Логи logs/ @@ -25,21 +9,36 @@ logs/ npm-debug.log* yarn-debug.log* yarn-error.log* -pnpm-debug.log* -# Файлы IDE -.idea/ -.vscode/* -!.vscode/extensions.json -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +# Файлы окружения +.env +.env.local +.env.development.local +.env.test.local +.env.production.local -# Системные файлы +# Кэши и временные файлы +.cache/ +.temp/ .DS_Store -Thumbs.db +.idea/ +.vscode/ +*.swp +*.swo -# Локальные файлы -*.local \ No newline at end of file +# Файлы сборки +/dist +/dist-ssr +/build +*.local + +# Тесты +/coverage + +# Приватные ключи и сертификаты +*.pem +*.key + +# Локальные настройки +.prettierrc.local +.eslintrc.local \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..83023c6 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,21 @@ +FROM node:20-alpine + +WORKDIR /app + +# Устанавливаем дополнительные зависимости +RUN apk add --no-cache python3 make g++ + +# Копируем package.json и yarn.lock для установки зависимостей +COPY package.json yarn.lock ./ + +# Устанавливаем зависимости +RUN yarn install --frozen-lockfile + +# Копируем остальные файлы проекта +COPY . . + +# Экспозим порт +EXPOSE 5173 + +# Команда запуска по умолчанию +CMD ["yarn", "run", "dev"] \ No newline at end of file diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..d5c0c7c --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,28 @@ +server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + # Поддержка SPA (Single Page Application) + location / { + try_files $uri $uri/ /index.html; + } + + # Настройка кеширования для статических файлов + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 30d; + add_header Cache-Control "public, no-transform"; + } + + # Настройка для API запросов на бэкенд + location /api/ { + proxy_pass http://backend:8000/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} \ No newline at end of file diff --git a/frontend/src/api/axios.js b/frontend/src/api/axios.js index ca8497c..146073e 100644 --- a/frontend/src/api/axios.js +++ b/frontend/src/api/axios.js @@ -1,8 +1,18 @@ import axios from 'axios'; +// Определяем baseURL в зависимости от окружения +const getBaseUrl = () => { + // В браузере используем localhost + if (typeof window !== 'undefined' && window.location.hostname === 'localhost') { + return 'http://localhost:8000'; + } + // В других случаях используем переменную окружения + return import.meta.env.VITE_API_URL || ''; +}; + // Создаем экземпляр axios с базовым URL const api = axios.create({ - baseURL: import.meta.env.VITE_API_URL || '', + baseURL: getBaseUrl(), withCredentials: true, headers: { 'Content-Type': 'application/json' diff --git a/frontend/src/main.js b/frontend/src/main.js index f1ac088..2d0591b 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -7,7 +7,9 @@ import router from './router'; import axios from 'axios'; // Настройка axios -axios.defaults.baseURL = import.meta.env.VITE_API_URL || ''; +// В Docker контейнере localhost:8000 не работает, поэтому используем явное значение +const apiUrl = window.location.hostname === 'localhost' ? 'http://localhost:8000' : import.meta.env.VITE_API_URL; +axios.defaults.baseURL = apiUrl; axios.defaults.withCredentials = true; // Создаем и монтируем приложение Vue @@ -25,7 +27,7 @@ app.use(router); // ]).catch(err => console.error('Failed to load API mocks:', err)); // } -console.log('API URL:', import.meta.env.VITE_API_URL); +console.log('API URL:', apiUrl); console.log('main.js: Starting application with router'); app.mount('#app'); diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..1d65edb --- /dev/null +++ b/setup.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +# Вывод цветного текста +print_green() { + echo -e "\e[32m$1\e[0m" +} + +print_blue() { + echo -e "\e[34m$1\e[0m" +} + +print_yellow() { + echo -e "\e[33m$1\e[0m" +} + +print_red() { + echo -e "\e[31m$1\e[0m" +} + +# Проверка установки Docker и Docker Compose +check_docker() { + print_blue "Проверка наличия Docker..." + if ! command -v docker &> /dev/null; then + print_yellow "Docker не установлен. Установите Docker перед запуском." + print_yellow "Инструкции по установке: https://docs.docker.com/get-docker/" + exit 1 + fi + print_green "Docker установлен." + + print_blue "Проверка Docker Compose..." + if ! docker compose version &> /dev/null; then + print_yellow "Docker Compose не установлен или требуется обновление." + print_yellow "Инструкции по установке: https://docs.docker.com/compose/install/" + exit 1 + fi + print_green "Docker Compose установлен." +} + +# Проверка и создание .env файлов +check_env_files() { + print_blue "Проверка наличия файлов конфигурации..." + + # Проверяем backend/.env + if [ ! -f backend/.env ]; then + if [ -f backend/.env.example ]; then + print_yellow "Файл backend/.env не найден. Создаю из примера..." + cp backend/.env.example backend/.env + print_green "Файл backend/.env создан. Рекомендуется настроить его вручную." + else + print_red "Файл backend/.env.example не найден. Невозможно создать файл конфигурации." + exit 1 + fi + else + print_green "Файл backend/.env уже существует." + fi + + # Проверяем frontend/.env + if [ ! -f frontend/.env ]; then + if [ -f frontend/.env.example ]; then + print_yellow "Файл frontend/.env не найден. Создаю из примера..." + cp frontend/.env.example frontend/.env + print_green "Файл frontend/.env создан. Рекомендуется настроить его вручную." + else + print_red "Файл frontend/.env.example не найден. Невозможно создать файл конфигурации." + exit 1 + fi + else + print_green "Файл frontend/.env уже существует." + fi + + print_blue "Проверка файлов конфигурации завершена." + print_yellow "ВАЖНО: По соображениям безопасности используйте свои значения для паролей и ключей в .env файлах." +} + +# Предварительная загрузка образов +pull_images() { + print_blue "Предварительная загрузка образов Docker..." + + images=("node:20-alpine" "postgres:16-alpine" "ollama/ollama:latest" "curlimages/curl:latest") + + for img in "${images[@]}"; do + print_blue "Загрузка образа: $img" + docker pull $img + if [ $? -ne 0 ]; then + print_yellow "Предупреждение: Не удалось загрузить образ $img, но продолжаем работу..." + else + print_green "Образ $img успешно загружен." + fi + done +} + +# Запуск проекта +start_project() { + print_blue "Запуск проекта..." + + # Сначала убедимся, что предыдущие контейнеры остановлены + print_blue "Остановка существующих контейнеров..." + docker compose down + + # Запуск сервисов в Docker Compose + print_blue "Запуск сервисов (PostgreSQL, Ollama, Backend, Frontend)..." + docker compose up -d + + # Проверяем, что сервисы запустились + if [ $? -eq 0 ]; then + print_green "Сервисы успешно запущены!" + print_green "----------------------------------------" + print_green "Проект DApp-for-Business доступен по адресам:" + print_green "Frontend: http://localhost:5173" + print_green "Backend API: http://localhost:8000" + print_green "Ollama API: http://localhost:11434" + print_green "PostgreSQL: localhost:5432" + print_green "----------------------------------------" + print_green "Загрузка модели qwen2.5:7b может занять некоторое время..." + print_green "Вы можете проверить статус загрузки модели командой:" + print_green "docker logs -f dapp-ollama-setup" + print_green "----------------------------------------" + else + print_red "Произошла ошибка при запуске сервисов." + print_yellow "Проверьте логи командой: docker compose logs" + print_yellow "Для просмотра логов конкретного сервиса: docker compose logs [service]" + print_yellow "Например: docker compose logs backend" + fi +} + +# Основная функция +main() { + print_blue "===============================================" + print_blue " Установка и запуск DApp-for-Business" + print_blue "===============================================" + + check_docker + check_env_files + pull_images + start_project +} + +# Запуск основной функции +main \ No newline at end of file