From bcc7ca5d12d33504f667994245be0f9d8801a920 Mon Sep 17 00:00:00 2001 From: Liosha Date: Fri, 1 May 2026 16:06:11 +0300 Subject: [PATCH] [Monitoring] MongoDB Metrics in Grafana --- LOCAL_INFRASTRUCTURE.md | 58 +++++ build.gradle | 198 +++++++++--------- docker-compose.dev.yml | 81 +++++++ hetzner/caddy/docker-compose.yml | 11 +- hetzner/caddy/prometheus.yml | 6 +- .../docker-compose.staging.yml | 45 ++++ 6 files changed, 294 insertions(+), 105 deletions(-) create mode 100644 LOCAL_INFRASTRUCTURE.md create mode 100644 docker-compose.dev.yml create mode 100644 hetzner/jambotron-infra/docker-compose.staging.yml diff --git a/LOCAL_INFRASTRUCTURE.md b/LOCAL_INFRASTRUCTURE.md new file mode 100644 index 0000000..e0d38a2 --- /dev/null +++ b/LOCAL_INFRASTRUCTURE.md @@ -0,0 +1,58 @@ +# 💻 Local Development Infrastructure: Jambotron PaaS + +Этот файл описывает конфигурацию локальной среды разработки, которая зеркально отражает серверную инфраструктуру в Хельсинки. Локальный кластер настроен для обеспечения бесшовного процесса созидания и мониторинга контейнеров. + +## 🏗️ Архитектура системы + +Локальная среда построена на базе Docker и управляется через единую сеть для обеспечения связи между системными базами и динамическими проектами. + +* **Runtime**: Docker Engine / Docker Desktop. +* **Network**: `jambotron-net` (Тип: bridge, внешняя). +* **Оркестрация**: Docker Compose. +* **JDK**: Version 21 (LTS). +* **Build Tool**: Gradle. + +## 📦 Реестр локальных сервисов + +| Сервис | Образ | URL / Порт | Назначение | +| :--- | :--- | :--- | :--- | +| **caddy-dev** | `lucaslorentz/caddy-docker-proxy` | `*.localhost` | Обратный прокси с авто-обнаружением через Docker Socket. | +| **jambo-postgres** | `postgres:15-alpine` | `localhost:5432` | Системная БД (Пользователи, настройки, биллинг). | +| **jambotron-mongo** | `mongo:6.0` | `localhost:27017` | Хранилище метаданных проектов и контейнеров (SaaS 2.0). | +| **jambo-pgadmin** | `dpage/pgadmin4` | `pgadmin.localhost` | Веб-интерфейс для управления PostgreSQL. | +| **portainer-dev** | `portainer/portainer-ce` | `localhost:9443` | Визуальный мониторинг и управление Docker-ресурсами. | + +## 🛠️ Стек разработки (Dev Mode) + +* **Backend**: Spring Boot 3.5.0 (профиль `dev`). +* **Frontend**: Angular 17+ (интегрирован в Gradle-таски). +* **БД Миграции**: Flyway. +* **API управления**: Docker Java Client (через `/var/run/docker.sock`). + +## 🚀 Быстрый старт + +### 1. Подготовка сети +Перед первым запуском необходимо создать общую сеть, если она еще не создана: +```bash +docker network create jambotron-net +``` +2. Запуск инфраструктуры +Запуск всех баз данных и системных сервисов: + +Bash +docker-compose -f docker-compose.dev.yml up -d +3. Запуск приложения (Spring + Angular) +Используй кастомный Gradle-таск для запуска приложения с профилем разработчика: + +Bash +./gradlew bootRun_Dev +Команда автоматически соберет фронтенд, скопирует статику в src/main/resources/static и запустит сервер. + +🔗 Особенности созидания проектов +Для реализации динамического деплоя внутри PaaS, приложение использует проброс Docker Socket. + +Docker Labels: При создании нового контейнера через API, необходимо вешать лейблы caddy и caddy.reverse_proxy, чтобы локальный Caddy автоматически создал маршрут на project-name.localhost. + +Volumes: Данные PostgreSQL и MongoDB сохраняются в именованных томах jambo_db_dev_data и mongo_dev_data соответственно. + +Lombok: Для корректной сборки на JDK 21 используется версия 1.18.34. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 12b9512..faf4e4c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,149 +1,141 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.5.0' - id 'io.spring.dependency-management' version '1.1.7' - id 'org.flywaydb.flyway' version '10.4.1' + id 'java' + id 'org.springframework.boot' version '3.5.0' + id 'io.spring.dependency-management' version '1.1.7' + id 'org.flywaydb.flyway' version '10.4.1' } group = 'com.jambotronGroup' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } + toolchain { + // Устанавливаем актуальную LTS версию 21 для Spring Boot 3.5 + languageVersion = JavaLanguageVersion.of(21) + } } repositories { - - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter' - implementation 'org.projectlombok:lombok:1.18.26' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0' - implementation 'jakarta.validation:jakarta.validation-api:3.0.2' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' // For JSON serialization/deserialization - implementation 'org.postgresql:postgresql:42.6.0' - implementation 'org.flywaydb:flyway-core' - implementation("org.flywaydb:flyway-database-postgresql:10.4.1") + // Ядро Spring Boot + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'jakarta.validation:jakarta.validation-api:3.0.2' - implementation 'org.springframework.ai:spring-ai-zhipuai-spring-boot-starter:1.0.0-M6' - implementation 'org.springframework:spring-mock:2.0.8' + // --- НОВОЕ: Реактивная MongoDB 6.0 для метаданных PaaS --- + implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive' - // Apache Commons Exec for process execution - implementation 'org.apache.commons:commons-exec:1.3' + // --- НОВОЕ: Docker API для управления контейнерами (Созидание) --- + implementation 'com.github.docker-java:docker-java-core:3.3.6' + implementation 'com.github.docker-java:docker-java-transport-httpclient5:3.3.6' - implementation 'com.google.guava:guava:33.4.8-jre' - implementation 'io.micrometer:micrometer-core:1.12.0' - implementation 'org.springframework.boot:spring-boot-starter-actuator' + // Работа с SQL и PostgreSQL[cite: 3] + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.postgresql:postgresql:42.6.0' + implementation 'org.flywaydb:flyway-core' + implementation "org.flywaydb:flyway-database-postgresql:10.4.1" + implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0' + + // Безопасность и JWT + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' + + // Lombok с поддержкой JDK 21 + compileOnly 'org.projectlombok:lombok:1.18.34' + annotationProcessor 'org.projectlombok:lombok:1.18.34' + testCompileOnly 'org.projectlombok:lombok:1.18.34' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.34' + + // Spring AI и дополнительные утилиты + implementation 'org.springframework.ai:spring-ai-zhipuai-spring-boot-starter:1.0.0-M6' + implementation 'com.google.guava:guava:33.4.8-jre' + implementation 'org.apache.commons:commons-exec:1.3' + implementation 'io.micrometer:micrometer-core:1.12.0' + + // Тестирование + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'io.projectreactor:reactor-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // Временный фикс для обратной совместимости (если требуется) + implementation 'org.springframework:spring-mock:2.0.8' } apply plugin: 'io.spring.dependency-management' - dependencyManagement { - imports { - mavenBom ("org.springframework.ai:spring-ai-retry:1.0.0") - } - } +dependencyManagement { + imports { + mavenBom ("org.springframework.ai:spring-ai-retry:1.0.0") + } +} -apply plugin: 'java' +// --- Задачи сборки Angular (Твой монолитный код существования) --- +import org.apache.tools.ant.taskdefs.condition.Os tasks.register("bootRun_Dev") { - group = "_jambotron_build" - description = "Runs the Spring Boot application with the dev profile" - doFirst { - tasks.bootRun.configure { - systemProperty("spring.profiles.active", "dev") - } - } - finalizedBy("bootRun") + group = "_jambotron_build" + description = "Runs the Spring Boot application with the dev profile" + doFirst { + tasks.bootRun.configure { + systemProperty("spring.profiles.active", "dev") + } + } + finalizedBy("bootRun") } - - tasks.register('buildAngular_dev', Exec) { - group = "_jambotron_build" - description = "Builds the Angular application in development mode" - - workingDir './jambotron-ui' // Path to your Angular project (e.g., './angular-app') - executable 'npm.cmd' // Use 'npm' for Unix-like systems or 'npm.cmd' for Windows - - // Your Angular build command - //do not forget build_dev used port 8082 with proxy for connect to backend rest api - args = ['run', 'build_dev'] - -} - -import org.apache.tools.ant.taskdefs.condition.Os // Обязательно добавь этот импорт в самое начало файла -tasks.register('buildAngular_prod', Exec) { - group = "_jambotron_build" - - workingDir './jambotron-ui' // Path to your Angular project (e.g., './angular-app') - // Use 'npm' for Unix-like systems or 'npm.cmd' for Windows + group = "_jambotron_build" + workingDir './jambotron-ui' executable = Os.isFamily(Os.FAMILY_WINDOWS) ? 'npm.cmd' : 'npm' - - // Your Angular build command - args = ['run', 'build'] - + args = ['run', 'build_dev'] } +tasks.register('buildAngular_prod', Exec) { + group = "_jambotron_build" + workingDir './jambotron-ui' + executable = Os.isFamily(Os.FAMILY_WINDOWS) ? 'npm.cmd' : 'npm' + args = ['run', 'build'] +} tasks.register('deleteStaticFolder_prod', Delete) { - group = "_jambotron_build" - - dependsOn buildAngular_prod - def dirName = "src/main/resources/static" - file(dirName).list().each { - f -> - delete "${dirName}/${f}" - } + group = "_jambotron_build" + dependsOn buildAngular_prod + delete "src/main/resources/static" } tasks.register('deleteStaticFolder_dev', Delete) { - group = "_jambotron_build" - - dependsOn buildAngular_dev - def dirName = "src/main/resources/static" - file(dirName).list().each { - f -> - delete "${dirName}/${f}" - } + group = "_jambotron_build" + dependsOn buildAngular_dev + delete "src/main/resources/static" } tasks.register('copyAngularBuild_prod', Copy) { - group = "_jambotron_build" + group = "_jambotron_build" + dependsOn deleteStaticFolder_prod + from 'jambotron-ui/dist/jambotron-ui/browser' + into "src/main/resources/static" +} - dependsOn deleteStaticFolder_prod - - from 'jambotron-ui/dist/jambotron-ui/browser' // Path to your Angular dist folder - into "src/main/resources/static" // Path INSIDE the WAR +tasks.register('copyAngularBuild_dev', Copy) { + group = "_jambotron_build" + dependsOn deleteStaticFolder_dev + from 'jambotron-ui/dist/jambotron-ui' + into "src/main/resources/static" } -// Говорим задаче обработки ресурсов, что она НЕ ДОЛЖНА трогать статику фронтенда, -// пока фронтенд-задача не закончит свою работу. processResources { - if (!gradle.startParameter.taskNames.any { it.toLowerCase().contains("dev") }) - { + // В продакшн сборке всегда копируем фронтенд + if (!gradle.startParameter.taskNames.any { it.toLowerCase().contains("dev") }) { dependsOn copyAngularBuild_prod } - -} -tasks.register('copyAngularBuild_dev', Copy) { - group = "_jambotron_build" - dependsOn deleteStaticFolder_dev - from 'jambotron-ui/dist/jambotron-ui' // Path to your Angular dist folder - into "src/main/resources/static" // Path INSIDE the WAR } tasks.named('test') { - useJUnitPlatform() -} + useJUnitPlatform() +} \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..d5c45a9 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,81 @@ +version: '3.8' + +services: + # Основная БД для системных данных (JPA/Hibernate) + jambo-postgres: + image: postgres:15-alpine + container_name: jambo-postgres + environment: + - POSTGRES_USER=jambotron_admin + - POSTGRES_PASSWORD=jambo_secret_pass + - POSTGRES_DB=jambotron_dev + ports: + - "5432:5432" + volumes: + - jambo_db_dev_data:/var/lib/postgresql/data + networks: + - jambotron-net + + # Гибкое хранилище для SaaS 2.0 (Метаданные контейнеров) + jambotron-mongo: + image: mongo:6.0 + container_name: jambotron-mongo + ports: + - "27017:27017" + volumes: + - mongo_dev_data:/data/db + networks: + - jambotron-net + + # UI для управления БД (Postgres)[cite: 3] + jambo-pgadmin: + image: dpage/pgadmin4 + container_name: jambo-pgadmin + environment: + - PGADMIN_DEFAULT_EMAIL=admin@jambotron.com + - PGADMIN_DEFAULT_PASSWORD=admin + labels: + - "caddy=pgadmin.localhost" # Локальный домен вместо порта 5050 + - "caddy.reverse_proxy={{upstreams 80}}" + ports: + - "5050:80" + networks: + - jambotron-net + + # Контроль кластера (вместо ручного терминала)[cite: 1, 3] + portainer: + image: portainer/portainer-ce:latest + container_name: portainer-dev + command: -H unix:///var/run/docker.sock + ports: + - "9443:9443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_dev_data:/data + networks: + - jambotron-net + # Обратный прокси (Caddy) — сердце маршрутизации + caddy: + image: lucaslorentz/caddy-docker-proxy:latest + container_name: caddy-dev + ports: + - "80:80" + - "443:443" + environment: + - CADDY_INGRESS_NETWORKS=jambotron-net + volumes: + - /var/run/docker.sock:/var/run/docker.sock # Чтобы Caddy видел новые контейнеры[cite: 2, 3] + - caddy_dev_data:/data + networks: + - jambotron-net + restart: always + +networks: + jambotron-net: + external: true + +volumes: + jambo_db_dev_data: + mongo_dev_data: + portainer_dev_data: + caddy_dev_data: \ No newline at end of file diff --git a/hetzner/caddy/docker-compose.yml b/hetzner/caddy/docker-compose.yml index 03144d5..636176c 100644 --- a/hetzner/caddy/docker-compose.yml +++ b/hetzner/caddy/docker-compose.yml @@ -82,7 +82,16 @@ services: caddy: test-app1.jambotron.com caddy.reverse_proxy: "{{upstreams 80}}" restart: always - + loki: + image: grafana/loki:2.9.0 + container_name: jambo-loki + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + networks: + - jambotron-net + restart: always + networks: jambotron-net: name: jambotron-net diff --git a/hetzner/caddy/prometheus.yml b/hetzner/caddy/prometheus.yml index 37b91f9..a4f2660 100644 --- a/hetzner/caddy/prometheus.yml +++ b/hetzner/caddy/prometheus.yml @@ -8,4 +8,8 @@ scrape_configs: - job_name: 'cadvisor' static_configs: - - targets: ['cadvisor:8080'] \ No newline at end of file + - targets: ['cadvisor:8080'] + + - job_name: 'mongodb' + static_configs: + - targets: ['mongodb-exporter:9216'] \ No newline at end of file diff --git a/hetzner/jambotron-infra/docker-compose.staging.yml b/hetzner/jambotron-infra/docker-compose.staging.yml new file mode 100644 index 0000000..70add7f --- /dev/null +++ b/hetzner/jambotron-infra/docker-compose.staging.yml @@ -0,0 +1,45 @@ +version: '3.8' + +services: + # База данных для стейджинга + jambo-db-staging: + image: postgres:15-alpine + container_name: jambo-db-staging + restart: always + networks: + - jambotron-staging-net + environment: + POSTGRES_USER: ${STAGING_DB_USER} + POSTGRES_PASSWORD: ${STAGING_DB_PASSWORD} + POSTGRES_DB: ${STAGING_DB_NAME} + volumes: + - jambo_db_staging_data:/var/lib/postgresql/data + + # Backend-приложение (Staging версия) + jambotron-app-stg: + image: jambotron-app:stg-latest + container_name: jambotron-app-stg + restart: always + depends_on: + - jambo-db-staging + networks: + - jambotron-staging-net + - jambotron-net # Для связи с Caddy + environment: + SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE} + SPRING_DATASOURCE_URL: jdbc:postgresql://jambo-db-staging:5432/${STAGING_DB_NAME} + SPRING_DATASOURCE_USERNAME: ${STAGING_DB_USER} + SPRING_DATASOURCE_PASSWORD: ${STAGING_DB_PASSWORD} + labels: + # Настройки для caddy-docker-proxy + caddy: ${STAGING_DOMAIN} + caddy.reverse_proxy: "{{upstreams 8080}}" + +networks: + jambotron-staging-net: + driver: bridge + jambotron-net: + external: true # Используем существующую сеть + +volumes: + jambo_db_staging_data: