feat: optimize docker-compose, add observability stack (Grafana/Loki/Prometheus), and host nginx config
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 6m10s

This commit is contained in:
shanshanzhong 2026-01-13 18:17:12 -08:00
parent e5e60f73c2
commit 01ccd44e84
10 changed files with 529 additions and 0 deletions

View File

@ -46,6 +46,8 @@ type (
RefererId int64 `json:"referer_id"`
Enable bool `json:"enable"`
IsAdmin bool `json:"is_admin"`
MemberStatus string `json:"member_status"`
Remark string `json:"remark"`
}
UpdateUserNotifySettingRequest {
UserId int64 `json:"user_id" validate:"required"`

91
configs/ppanel.yaml Normal file
View File

@ -0,0 +1,91 @@
# PPanel Server Configuration
# 完整配置示例
# 运行模式: debug, release, test
Model: release
# 监听地址
Host: 0.0.0.0
# 监听端口
Port: 8080
# 是否开启调试模式
Debug: false
# JWT 认证配置
JwtAuth:
AccessSecret: "ppanel-secret-key-change-me" # 请务必修改此密钥
AccessExpire: 604800 # Token 过期时间 (秒), 默认 7 天
MaxSessionsPerUser: 3 # 每个用户最大并发登录数
# 日志配置
Logger:
ServiceName: "PPanel"
Mode: "file" # console, file, volume
Encoding: "json" # json, plain
Path: "logs" # 日志文件路径
Level: "info" # debug, info, warn, error
Compress: true
KeepDays: 7
Rotation: "daily" # daily, size
# MySQL 数据库配置
MySQL:
Addr: "mysql:3306" # Docker 服务名:端口
Username: "root"
Password: "ppanel_password" # 与 docker-compose 中的 MYSQL_ROOT_PASSWORD 保持一致
Dbname: "ppanel_db"
Config: "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
MaxIdleConns: 10
MaxOpenConns: 100
SlowThreshold: 1000 # 慢查询阈值 (ms)
# Redis 配置
Redis:
Host: "redis:6379" # Docker 服务名:端口
Pass: ""
DB: 0
# 管理员初始化配置 (仅在首次初始化有效,后续请在数据库管理)
Administrator:
Email: "admin@ppanel.dev"
Password: "password"
# 站点配置
Site:
Title: "PPanel"
Dec: "PPanel Panel"
Url: "https://your-domain.com"
SubUrl: "https://sub.your-domain.com"
# 邮件服务配置
Email:
Enable: false
# platform: "smtp"
# platform_config: "..."
# 验证配置
Verify:
TurnstileSiteKey: ""
TurnstileSecret: ""
LoginVerify: false
RegisterVerify: false
ResetPasswordVerify: false
# 注册配置
Register:
StopRegister: false
EnableTrial: false
TrialSubscribe: 0
TrialTime: 0
TrialTimeUnit: "hour"
EnableIpRegisterLimit: false
IpRegisterLimit: 0
IpRegisterLimitDuration: 0
# 订阅配置
Subscribe:
SingleModel: false
SubscribePath: "/v1/subscribe/config"
SubscribeDomain: ""
PanDomain: false
UserAgentLimit: false
UserAgentList: ""

309
docker-compose.cloud.yml Normal file
View File

@ -0,0 +1,309 @@
# PPanel 服务部署 (云端/无源码版)
# 使用方法:
# 1. 确保已将 docker-compose.cloud.yml, configs/, loki/ 目录上传到服务器同一目录
# 2. 确保 configs/ 目录下有 ppanel.yaml 配置文件
# 3. 确保 logs/ 目录存在 (mkdir logs)
# 4. 运行: docker-compose -f docker-compose.cloud.yml up -d
services:
# ----------------------------------------------------
# 1. 业务后端 (PPanel Server)
# ----------------------------------------------------
ppanel-server:
image: registry.kxsw.us/ario-server:latest
container_name: ppanel-server
restart: always
ports:
- "8080:8080" # 暴露端口供宿主机 Nginx 反代
volumes:
# 挂载配置文件和日志
- ./configs:/app/etc
- ./logs:/app/logs
environment:
- TZ=Asia/Shanghai
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
depends_on:
- mysql
- redis
# ----------------------------------------------------
# 2. MySQL Database
# ----------------------------------------------------
mysql:
image: mysql:8.0
container_name: ppanel-mysql
restart: always
ports:
- "3306:3306" # 临时开放外部访问,用完记得关闭!
environment:
MYSQL_ROOT_PASSWORD: "ppanel_password" # 请修改为强密码
MYSQL_DATABASE: "ppanel_db"
TZ: Asia/Shanghai
command: --default-authentication-plugin=mysql_native_password
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d # 初始化脚本
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 3. Redis
# ----------------------------------------------------
redis:
image: redis:7.0
container_name: ppanel-redis
restart: always
volumes:
- redis_data:/data
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 4. Loki (日志存储)
# ----------------------------------------------------
loki:
image: grafana/loki:3.0.0
container_name: ppanel-loki
restart: always
volumes:
# 必须上传 loki 目录到服务器
- ./loki/loki-config.yaml:/etc/loki/local-config.yaml
- loki_data:/loki
command: -config.file=/etc/loki/local-config.yaml
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 5. Promtail (日志采集)
# ----------------------------------------------------
promtail:
image: grafana/promtail:3.0.0
container_name: ppanel-promtail
restart: always
volumes:
- ./loki/promtail-config.yaml:/etc/promtail/config.yaml
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock
# 采集当前目录下的 logs 文件夹
- ./logs:/var/log/ppanel-server:ro
command: -config.file=/etc/promtail/config.yaml
networks:
- ppanel_net
depends_on:
- loki
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 6. Grafana (日志界面)
# ----------------------------------------------------
grafana:
image: grafana/grafana:latest
container_name: ppanel-grafana
restart: always
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
# 自动加载数据源和仪表盘配置
- ./grafana/provisioning:/etc/grafana/provisioning
# 挂载本地仪表盘 JSON 文件目录
- ./grafana/dashboards:/var/lib/grafana/dashboards
networks:
- ppanel_net
depends_on:
- loki
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 7. Prometheus (指标采集)
# ----------------------------------------------------
prometheus:
image: prom/prometheus:latest
container_name: ppanel-prometheus
restart: always
ports:
- "9090:9090" # 暴露端口便于调试
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.enable-lifecycle'
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 8. Redis Exporter (Redis指标导出)
# ----------------------------------------------------
redis-exporter:
image: oliver006/redis_exporter:latest
container_name: ppanel-redis-exporter
restart: always
environment:
- REDIS_ADDR=redis://redis:6379
networks:
- ppanel_net
depends_on:
- redis
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 9. Nginx Exporter (监控宿主机 Nginx)
# ----------------------------------------------------
nginx-exporter:
image: nginx/nginx-prometheus-exporter:latest
container_name: ppanel-nginx-exporter
restart: always
# 使用 host.docker.internal 访问宿主机
command:
- -nginx.scrape-uri=http://host.docker.internal:80/nginx_status
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 10. MySQL Exporter (MySQL指标导出)
# ----------------------------------------------------
mysql-exporter:
image: prom/mysqld-exporter:latest
container_name: ppanel-mysql-exporter
restart: always
command:
- --config.my-cnf=/etc/.my.cnf
volumes:
- ./mysql/.my.cnf:/etc/.my.cnf:ro
networks:
- ppanel_net
depends_on:
- mysql
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 11. Jaeger (链路追踪)
# ----------------------------------------------------
jaeger:
image: jaegertracing/all-in-one:latest
container_name: ppanel-jaeger
restart: always
ports:
- "16686:16686" # Jaeger UI
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
environment:
- LOG_LEVEL=debug
- COLLECTOR_OTLP_ENABLED=true
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 12. Node Exporter (宿主机监控)
# ----------------------------------------------------
node-exporter:
image: prom/node-exporter:latest
container_name: ppanel-node-exporter
restart: always
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ----------------------------------------------------
# 13. cAdvisor (容器监控)
# ----------------------------------------------------
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: ppanel-cadvisor
restart: always
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
networks:
- ppanel_net
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
mysql_data:
redis_data:
loki_data:
grafana_data:
prometheus_data:
networks:
ppanel_net:
name: ppanel_net
driver: bridge

View File

@ -0,0 +1,11 @@
apiVersion: 1
providers:
- name: 'Default'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 10
options:
path: /var/lib/grafana/dashboards

View File

@ -0,0 +1,27 @@
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
isDefault: true
version: 1
editable: true
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
version: 1
editable: true
- name: Jaeger
type: jaeger
access: proxy
orgId: 1
url: http://jaeger:16686
version: 1
editable: true

View File

@ -121,6 +121,8 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
userInfo.Commission = req.Commission
}
tool.DeepCopy(userInfo, req)
userInfo.Remark = req.Remark
userInfo.MemberStatus = req.MemberStatus
userInfo.OnlyFirstPurchase = &req.OnlyFirstPurchase
userInfo.ReferralPercentage = req.ReferralPercentage

View File

@ -24,6 +24,8 @@ type User struct {
EnableSubscribeNotify *bool `gorm:"default:false;not null;comment:Enable Subscription Notifications"`
EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"`
LastLoginTime *time.Time `gorm:"comment:Last Login Time"`
MemberStatus string `gorm:"type:varchar(20);default:'';comment:Member Status"` // Member Status
Remark string `gorm:"type:varchar(255);default:'';comment:Remark"` // Remark
AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"`
UserDevices []Device `gorm:"foreignKey:UserId;references:Id"`
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`

View File

@ -2548,6 +2548,8 @@ type UpdateUserBasiceInfoRequest struct {
RefererId int64 `json:"referer_id"`
Enable bool `json:"enable"`
IsAdmin bool `json:"is_admin"`
MemberStatus string `json:"member_status"`
Remark string `json:"remark"`
}
type UpdateUserNotifyRequest struct {

37
nginx_host_config.conf Normal file
View File

@ -0,0 +1,37 @@
server {
listen 80;
server_name localhost; # 请修改为您实际的域名,如 ppanel.example.com
# ----------------------------------------------------
# 1. Nginx Status (探针/监控端点)
# ----------------------------------------------------
# 用于 nginx-exporter 采集 Nginx 自身指标 (连接数、请求数等)
location /nginx_status {
stub_status on;
access_log off;
# 允许 Docker 容器和本地访问
allow 127.0.0.1;
allow 172.16.0.0/12; # Docker bridge 默认网段
allow 192.168.0.0/16; # Docker Desktop for Mac/Windows 网段
allow 10.0.0.0/8; # 其他常见私有网段
deny all;
}
# ----------------------------------------------------
# 2. PPanel Server (后端 API)
# ----------------------------------------------------
# 将请求转发到宿主机 8080 端口 (docker-compose 中暴露的端口)
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket 支持 (如果需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

46
prometheus/prometheus.yml Normal file
View File

@ -0,0 +1,46 @@
# Prometheus 配置文件
global:
scrape_interval: 15s # 默认抓取频率
evaluation_interval: 15s
scrape_configs:
# ----------------------------------------
# 1. Prometheus 自身监控
# ----------------------------------------
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
# ----------------------------------------
# 2. 业务后端 (PPanel Server)
# ----------------------------------------
# 如果您的后端代码暴露了 /metrics 接口,可启用此项
# - job_name: "ppanel-server"
# static_configs:
# - targets: ["ppanel-server:8080"]
# ----------------------------------------
# 3. 基础设施监控 (Redis, MySQL, Nginx)
# ----------------------------------------
- job_name: "redis"
static_configs:
- targets: ["redis-exporter:9121"]
- job_name: "mysql"
static_configs:
- targets: ["mysql-exporter:9104"]
- job_name: "nginx"
static_configs:
- targets: ["nginx-exporter:9113"]
# ----------------------------------------
# 4. 宿主机与容器资源监控
# ----------------------------------------
- job_name: "node-exporter" # 宿主机硬件资源
static_configs:
- targets: ["node-exporter:9100"]
- job_name: "cadvisor" # 容器资源
static_configs:
- targets: ["cadvisor:8080"]