Merge pull request '[Monitoring] MongoDB Metrics in Grafana' (#17) from development into 15-docker-client

Reviewed-on: Liosha84/jambotron#17
This commit is contained in:
2026-05-01 18:19:31 +00:00
6 changed files with 294 additions and 105 deletions
+58
View File
@@ -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.
+95 -103
View File
@@ -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()
}
+81
View File
@@ -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:
+10 -1
View File
@@ -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
+5 -1
View File
@@ -8,4 +8,8 @@ scrape_configs:
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- targets: ['cadvisor:8080']
- job_name: 'mongodb'
static_configs:
- targets: ['mongodb-exporter:9216']
@@ -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: