Merge pull request 'chore: upgrade logging stack - mirrors, Alloy, Loki, Grafana (#96, #97, #98, #99)' (#102) from issue-96-update-mirror-base-images into main
All checks were successful
Deploy to Staging / Build Images (push) Successful in 32s
Deploy to Staging / Deploy to Staging (push) Successful in 51s
Deploy to Staging / Verify Staging (push) Successful in 2m36s
Deploy to Staging / Notify Staging Ready (push) Successful in 7s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
All checks were successful
Deploy to Staging / Build Images (push) Successful in 32s
Deploy to Staging / Deploy to Staging (push) Successful in 51s
Deploy to Staging / Verify Staging (push) Successful in 2m36s
Deploy to Staging / Notify Staging Ready (push) Successful in 7s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Reviewed-on: #102
This commit was merged in pull request #102.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"architecture": "simplified-5-container",
|
"architecture": "9-container",
|
||||||
"repository": {
|
"repository": {
|
||||||
"host": "gitea",
|
"host": "gitea",
|
||||||
"owner": "egullickson",
|
"owner": "egullickson",
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
"project_overview": {
|
"project_overview": {
|
||||||
"instruction": "Start with README.md for complete architecture context",
|
"instruction": "Start with README.md for complete architecture context",
|
||||||
"files": ["README.md"],
|
"files": ["README.md"],
|
||||||
"completeness": "100% - all navigation and 5-container architecture information"
|
"completeness": "100% - all navigation and 9-container architecture information"
|
||||||
},
|
},
|
||||||
"application_feature_work": {
|
"application_feature_work": {
|
||||||
"instruction": "Load entire application feature directory (features are modules within backend)",
|
"instruction": "Load entire application feature directory (features are modules within backend)",
|
||||||
@@ -104,6 +104,26 @@
|
|||||||
"type": "cache",
|
"type": "cache",
|
||||||
"description": "Redis cache with AOF persistence",
|
"description": "Redis cache with AOF persistence",
|
||||||
"port": 6379
|
"port": 6379
|
||||||
|
},
|
||||||
|
"mvp-ocr": {
|
||||||
|
"type": "ocr_service",
|
||||||
|
"description": "Python-based OCR for document text extraction",
|
||||||
|
"port": 8000
|
||||||
|
},
|
||||||
|
"mvp-loki": {
|
||||||
|
"type": "log_aggregation",
|
||||||
|
"description": "Grafana Loki for centralized log storage (30-day retention)",
|
||||||
|
"port": 3100
|
||||||
|
},
|
||||||
|
"mvp-alloy": {
|
||||||
|
"type": "log_collector",
|
||||||
|
"description": "Grafana Alloy for log collection and forwarding to Loki",
|
||||||
|
"port": 12345
|
||||||
|
},
|
||||||
|
"mvp-grafana": {
|
||||||
|
"type": "log_visualization",
|
||||||
|
"description": "Grafana for log querying and visualization",
|
||||||
|
"port": 3000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"application_features": {
|
"application_features": {
|
||||||
@@ -290,6 +310,6 @@
|
|||||||
"single_tenant_architecture": true,
|
"single_tenant_architecture": true,
|
||||||
"simplified_deployment": true,
|
"simplified_deployment": true,
|
||||||
"docker_first_development": true,
|
"docker_first_development": true,
|
||||||
"container_count": 5
|
"container_count": 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ jobs:
|
|||||||
# Start shared infrastructure services (database, cache, logging)
|
# Start shared infrastructure services (database, cache, logging)
|
||||||
# These persist across blue-green deployments
|
# These persist across blue-green deployments
|
||||||
docker compose -f $COMPOSE_FILE -f $COMPOSE_BLUE_GREEN -f $COMPOSE_PROD up -d \
|
docker compose -f $COMPOSE_FILE -f $COMPOSE_BLUE_GREEN -f $COMPOSE_PROD up -d \
|
||||||
mvp-postgres mvp-redis mvp-loki mvp-promtail mvp-grafana
|
mvp-postgres mvp-redis mvp-loki mvp-alloy mvp-grafana
|
||||||
|
|
||||||
- name: Start target stack
|
- name: Start target stack
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# MotoVaultPro
|
# MotoVaultPro
|
||||||
|
|
||||||
Single-tenant vehicle management application with 9-container architecture (6 application: Traefik, Frontend, Backend, OCR, PostgreSQL, Redis + 3 logging: Loki, Promtail, Grafana).
|
Single-tenant vehicle management application with 9-container architecture (6 application: Traefik, Frontend, Backend, OCR, PostgreSQL, Redis + 3 logging: Loki, Alloy, Grafana).
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ Issues are the source of truth. See `.ai/workflow-contract.json` for complete wo
|
|||||||
## Architecture Context for AI
|
## Architecture Context for AI
|
||||||
|
|
||||||
### 9-Container Architecture
|
### 9-Container Architecture
|
||||||
**MotoVaultPro uses a unified architecture:** A single-tenant application with 9 containers - 6 application (Traefik, Frontend, Backend, OCR, PostgreSQL, Redis) + 3 logging (Loki, Promtail, Grafana). Application features in `backend/src/features/[name]/` are self-contained modules within the backend service, including the platform feature for vehicle data and VIN decoding. See `docs/LOGGING.md` for unified logging system documentation.
|
**MotoVaultPro uses a unified architecture:** A single-tenant application with 9 containers - 6 application (Traefik, Frontend, Backend, OCR, PostgreSQL, Redis) + 3 logging (Loki, Alloy, Grafana). Application features in `backend/src/features/[name]/` are self-contained modules within the backend service, including the platform feature for vehicle data and VIN decoding. See `docs/LOGGING.md` for unified logging system documentation.
|
||||||
|
|
||||||
### Key Principles for AI Understanding
|
### Key Principles for AI Understanding
|
||||||
- **Feature Capsule Organization**: Application features are self-contained modules within the backend
|
- **Feature Capsule Organization**: Application features are self-contained modules within the backend
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# config/
|
# config/
|
||||||
|
|
||||||
Configuration files for the 5-container architecture.
|
Configuration files for the 9-container architecture (6 application + 3 logging).
|
||||||
|
|
||||||
## Subdirectories
|
## Subdirectories
|
||||||
|
|
||||||
|
|||||||
29
config/alloy/config.alloy
Normal file
29
config/alloy/config.alloy
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
discovery.docker "containers" {
|
||||||
|
host = "unix:///var/run/docker.sock"
|
||||||
|
refresh_interval = "5s"
|
||||||
|
}
|
||||||
|
|
||||||
|
discovery.relabel "containers" {
|
||||||
|
targets = discovery.docker.containers.targets
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_docker_container_name"]
|
||||||
|
regex = "/(.*)"
|
||||||
|
target_label = "container"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_docker_container_label_com_docker_compose_service"]
|
||||||
|
target_label = "service"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.source.docker "containers" {
|
||||||
|
host = "unix:///var/run/docker.sock"
|
||||||
|
targets = discovery.relabel.containers.output
|
||||||
|
forward_to = [loki.write.default.receiver]
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.write "default" {
|
||||||
|
endpoint {
|
||||||
|
url = "http://mvp-loki:3100/loki/api/v1/push"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,24 +15,23 @@ ingester:
|
|||||||
schema_config:
|
schema_config:
|
||||||
configs:
|
configs:
|
||||||
- from: 2020-01-01
|
- from: 2020-01-01
|
||||||
store: boltdb-shipper
|
store: tsdb
|
||||||
object_store: filesystem
|
object_store: filesystem
|
||||||
schema: v11
|
schema: v13
|
||||||
index:
|
index:
|
||||||
prefix: index_
|
prefix: index_
|
||||||
period: 24h
|
period: 24h
|
||||||
|
|
||||||
storage_config:
|
storage_config:
|
||||||
boltdb_shipper:
|
tsdb_shipper:
|
||||||
active_index_directory: /loki/boltdb-shipper-active
|
active_index_directory: /loki/tsdb-index
|
||||||
cache_location: /loki/boltdb-shipper-cache
|
cache_location: /loki/tsdb-cache
|
||||||
shared_store: filesystem
|
|
||||||
filesystem:
|
filesystem:
|
||||||
directory: /loki/chunks
|
directory: /loki/chunks
|
||||||
|
|
||||||
compactor:
|
compactor:
|
||||||
working_directory: /loki/compactor
|
working_directory: /loki/compactor
|
||||||
shared_store: filesystem
|
|
||||||
|
|
||||||
limits_config:
|
limits_config:
|
||||||
retention_period: 720h # 30 days
|
retention_period: 720h # 30 days
|
||||||
|
allow_structured_metadata: false
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
server:
|
|
||||||
http_listen_port: 9080
|
|
||||||
grpc_listen_port: 0
|
|
||||||
|
|
||||||
positions:
|
|
||||||
filename: /tmp/positions.yaml
|
|
||||||
|
|
||||||
clients:
|
|
||||||
- url: http://mvp-loki:3100/loki/api/v1/push
|
|
||||||
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: containers
|
|
||||||
docker_sd_configs:
|
|
||||||
- host: unix:///var/run/docker.sock
|
|
||||||
refresh_interval: 5s
|
|
||||||
relabel_configs:
|
|
||||||
- source_labels: ['__meta_docker_container_name']
|
|
||||||
regex: '/(.*)'
|
|
||||||
target_label: 'container'
|
|
||||||
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
|
|
||||||
target_label: 'service'
|
|
||||||
@@ -266,7 +266,7 @@ services:
|
|||||||
|
|
||||||
# Log Aggregation - Loki
|
# Log Aggregation - Loki
|
||||||
mvp-loki:
|
mvp-loki:
|
||||||
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/loki:2.9.0
|
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/loki:3.6.1
|
||||||
container_name: mvp-loki
|
container_name: mvp-loki
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
@@ -286,20 +286,29 @@ services:
|
|||||||
max-size: "10m"
|
max-size: "10m"
|
||||||
max-file: "3"
|
max-file: "3"
|
||||||
|
|
||||||
# Log Aggregation - Promtail
|
# Log Aggregation - Alloy (replaces Promtail)
|
||||||
mvp-promtail:
|
mvp-alloy:
|
||||||
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/promtail:2.9.0
|
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/alloy:v1.12.2
|
||||||
container_name: mvp-promtail
|
container_name: mvp-alloy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/promtail/config.yml:/etc/promtail/config.yml:ro
|
- ./config/alloy/config.alloy:/etc/alloy/config.alloy
|
||||||
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
command: -config.file=/etc/promtail/config.yml
|
command:
|
||||||
|
- run
|
||||||
|
- --server.http.listen-addr=0.0.0.0:12345
|
||||||
|
- --storage.path=/var/lib/alloy/data
|
||||||
|
- /etc/alloy/config.alloy
|
||||||
networks:
|
networks:
|
||||||
- backend
|
- backend
|
||||||
depends_on:
|
depends_on:
|
||||||
- mvp-loki
|
- mvp-loki
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget -q --spider http://localhost:12345/ready || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
logging:
|
logging:
|
||||||
driver: json-file
|
driver: json-file
|
||||||
options:
|
options:
|
||||||
@@ -308,7 +317,7 @@ services:
|
|||||||
|
|
||||||
# Log Aggregation - Grafana
|
# Log Aggregation - Grafana
|
||||||
mvp-grafana:
|
mvp-grafana:
|
||||||
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/grafana:10.0.0
|
image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/grafana:12.4.0-21693836646
|
||||||
container_name: mvp-grafana
|
container_name: mvp-grafana
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -2,14 +2,20 @@
|
|||||||
|
|
||||||
## Architecture Summary
|
## Architecture Summary
|
||||||
|
|
||||||
MotoVaultPro is a single-tenant vehicle management application built with a **5-container Docker-first architecture**. All development and deployment occurs in production-configured containers with no local installation dependencies.
|
MotoVaultPro is a single-tenant vehicle management application built with a **9-container Docker-first architecture** (6 application + 3 logging). All development and deployment occurs in production-configured containers with no local installation dependencies.
|
||||||
|
|
||||||
### Core Containers
|
### Application Containers (6)
|
||||||
1. **Traefik** - Reverse proxy and service discovery
|
1. **Traefik** - Reverse proxy and service discovery
|
||||||
2. **Frontend** - React SPA with Vite (Node.js 20 + nginx)
|
2. **Frontend** - React SPA with Vite (Node.js 20 + nginx)
|
||||||
3. **Backend** - Node.js API with Fastify (Node.js 20) - includes platform feature module
|
3. **Backend** - Node.js API with Fastify (Node.js 20) - includes platform feature module
|
||||||
4. **PostgreSQL** - Primary database (PostgreSQL 18)
|
4. **OCR** - Python-based document text extraction
|
||||||
5. **Redis** - Caching layer (Redis 8)
|
5. **PostgreSQL** - Primary database (PostgreSQL 18)
|
||||||
|
6. **Redis** - Caching layer (Redis 8)
|
||||||
|
|
||||||
|
### Logging Containers (3)
|
||||||
|
7. **Loki** - Centralized log storage (30-day retention)
|
||||||
|
8. **Alloy** - Log collection and forwarding
|
||||||
|
9. **Grafana** - Log querying and visualization
|
||||||
|
|
||||||
### Key Architectural Principles
|
### Key Architectural Principles
|
||||||
- **Production-Only**: All services use production builds and configuration
|
- **Production-Only**: All services use production builds and configuration
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
**Classification:** Internal/Confidential
|
**Classification:** Internal/Confidential
|
||||||
**Audit Date:** December 13, 2025
|
**Audit Date:** December 13, 2025
|
||||||
**Application Version:** 1.0.0
|
**Application Version:** 1.0.0
|
||||||
**Architecture:** 5-Container Single-Tenant Docker Stack
|
**Architecture:** 9-Container Single-Tenant Docker Stack (6 application + 3 logging)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
### 1.1 High-Level Assessment
|
### 1.1 High-Level Assessment
|
||||||
|
|
||||||
**MotoVaultPro** is an automotive vehicle management platform built on a modern 5-container Docker architecture. The application demonstrates solid architectural foundations with proper authentication, modular feature design, and production-ready deployment configuration.
|
**MotoVaultPro** is an automotive vehicle management platform built on a modern 9-container Docker architecture (6 application + 3 logging). The application demonstrates solid architectural foundations with proper authentication, modular feature design, and production-ready deployment configuration.
|
||||||
|
|
||||||
### 1.2 Key Findings Summary
|
### 1.2 Key Findings Summary
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Database Schema Overview
|
# Database Schema Overview
|
||||||
|
|
||||||
Complete database schema for MotoVaultPro 5-container architecture with 15 feature capsules.
|
Complete database schema for MotoVaultPro 9-container architecture with 15 feature capsules.
|
||||||
|
|
||||||
## Migration System
|
## Migration System
|
||||||
|
|
||||||
|
|||||||
@@ -102,14 +102,14 @@ This creates `.env.logging` which is sourced by docker-compose.
|
|||||||
+-----------------------------------------------------------------------+
|
+-----------------------------------------------------------------------+
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
Promtail --> Loki (30-day retention) --> Grafana
|
Alloy --> Loki (30-day retention) --> Grafana
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Logs not appearing in Grafana
|
### Logs not appearing in Grafana
|
||||||
|
|
||||||
1. Check Promtail is running: `docker logs mvp-promtail`
|
1. Check Alloy is running: `docker logs mvp-alloy`
|
||||||
2. Check Loki is healthy: `curl http://localhost:3100/ready`
|
2. Check Loki is healthy: `curl http://localhost:3100/ready`
|
||||||
3. Verify log rotation is not too aggressive
|
3. Verify log rotation is not too aggressive
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# Build argument for registry (defaults to Gitea mirrors, falls back to Docker Hub)
|
# Build argument for registry (defaults to Gitea mirrors, falls back to Docker Hub)
|
||||||
ARG REGISTRY_MIRRORS=git.motovaultpro.com/egullickson/mirrors
|
ARG REGISTRY_MIRRORS=git.motovaultpro.com/egullickson/mirrors
|
||||||
|
|
||||||
FROM ${REGISTRY_MIRRORS}/python:3.11-slim
|
FROM ${REGISTRY_MIRRORS}/python:3.13-slim
|
||||||
|
|
||||||
# System dependencies
|
# System dependencies
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
|||||||
@@ -14,12 +14,10 @@ IMAGES=(
|
|||||||
"postgres:18-alpine"
|
"postgres:18-alpine"
|
||||||
"redis:8.4-alpine"
|
"redis:8.4-alpine"
|
||||||
"traefik:v3.6"
|
"traefik:v3.6"
|
||||||
"python:3.11-slim"
|
"python:3.13-slim"
|
||||||
"docker:24.0"
|
"grafana/loki:3.6.1"
|
||||||
"docker:24.0-dind"
|
"grafana/alloy:v1.12.2"
|
||||||
"grafana/loki:2.9.0"
|
"grafana/grafana:12.4.0-21693836646"
|
||||||
"grafana/promtail:2.9.0"
|
|
||||||
"grafana/grafana:10.0.0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
|
|||||||
Reference in New Issue
Block a user