shouldBindJson 使用错误
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m51s

This commit is contained in:
shanshanzhong 2026-03-06 01:30:39 -08:00
parent 67d2c8cca8
commit 7914b2aa78
5 changed files with 111 additions and 87 deletions

11
.env.example Normal file
View File

@ -0,0 +1,11 @@
# 复制此文件为 .env 并填写真实值
# cp .env.example .env
# MySQL root 密码(同时需要在 configs/ppanel.yaml 的 MySQL.Password 中填写相同的值)
MYSQL_ROOT_PASSWORD=CHANGE_ME_TO_STRONG_PASSWORD
# Grafana 管理员密码
GRAFANA_PASSWORD=CHANGE_ME_TO_STRONG_PASSWORD
# PPanel Server 镜像标签(留空使用 latest
PPANEL_SERVER_TAG=latest

View File

@ -1,9 +1,15 @@
# PPanel 服务部署 (云端/无源码版) # PPanel 服务部署 (云端/无源码版)
# 使用方法: # 使用方法:
# 1. 确保已将 docker-compose.cloud.yml, configs/, loki/, grafana/, prometheus/ 目录上传到服务器同一目录 # 1. 确保已将 docker-compose.cloud.yml, configs/, loki/, grafana/, prometheus/, tempo/ 目录上传到服务器同一目录
# 2. 确保 configs/ 目录下有 ppanel.yaml 配置文件 # 2. 确保 configs/ 目录下有 ppanel.yaml 配置文件(参考 etc/ppanel.yaml
# 3. 确保 logs/ 目录存在 (mkdir logs) # 3. 确保 logs/ 目录存在 (mkdir -p logs tempo_data)
# 4. 运行: docker-compose -f docker-compose.cloud.yml up -d # 4. 运行: docker-compose -f docker-compose.cloud.yml up -d
#
# 网络说明:
# 所有服务均在 ppanel_net bridge 网络中,通过容器名互联
# MySQL / Redis / Tempo 不对外暴露端口(仅内网访问)
# 监控端口Grafana/Prometheus/Loki/Tempo绑定到 127.0.0.1,需通过 SSH 隧道或 Nginx 反代访问
# 对外只暴露 8080 (ppanel API)
services: services:
# ---------------------------------------------------- # ----------------------------------------------------
@ -18,49 +24,22 @@ services:
- ./logs:/app/logs - ./logs:/app/logs
environment: environment:
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
# 链路追踪配置 (OTLP) ports:
- OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317 - "8080:8080"
- OTEL_SERVICE_NAME=ppanel-server networks:
- OTEL_TRACES_EXPORTER=otlp - ppanel_net
- OTEL_METRICS_EXPORTER=prometheus # 指标由 tempo 抓取,不使用 OTLP
network_mode: host
ulimits: ulimits:
nproc: 65535 nproc: 65535
nofile: nofile:
soft: 65535 soft: 65535
hard: 65535 hard: 65535
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
depends_on: depends_on:
- mysql mysql:
- redis condition: service_healthy
- tempo redis:
condition: service_healthy
# ---------------------------------------------------- tempo:
# 14. Tempo (链路追踪存储 - 替代/增强 Jaeger) condition: service_started
# ----------------------------------------------------
tempo:
image: grafana/tempo:2.4.1
container_name: ppanel-tempo
user: root
restart: always
command:
- "-config.file=/etc/tempo.yaml"
- "-target=all"
volumes:
- ./tempo/tempo-config.yaml:/etc/tempo.yaml # - tempo_data:/var/tempo
- ./tempo_data:/var/tempo # 改为映射到当前目录,确保数据彻底干净
ports:
- "3200:3200"
- "4317:4317"
- "4318:4318"
- "9095:9095"
networks:
- ppanel_net
logging: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -74,10 +53,9 @@ services:
image: mysql:8.0 image: mysql:8.0
container_name: ppanel-mysql container_name: ppanel-mysql
restart: always restart: always
ports: # 不对外暴露端口,仅内网访问(容器名: mysql端口: 3306
- "3306:3306" # 临时开放外部访问,用完记得关闭!
environment: environment:
MYSQL_ROOT_PASSWORD: "jpcV41ppanel" # 请修改为强密码 MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?请在 .env 文件中设置 MYSQL_ROOT_PASSWORD}"
MYSQL_DATABASE: "ppanel" MYSQL_DATABASE: "ppanel"
TZ: Asia/Shanghai TZ: Asia/Shanghai
command: command:
@ -97,6 +75,11 @@ services:
hard: 65535 hard: 65535
networks: networks:
- ppanel_net - ppanel_net
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 5
logging: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -110,8 +93,7 @@ services:
image: redis:8.2.1 image: redis:8.2.1
container_name: ppanel-redis container_name: ppanel-redis
restart: always restart: always
ports: # 不对外暴露端口,仅内网访问(容器名: redis端口: 6379
- "6379:6379"
command: command:
- redis-server - redis-server
- --tcp-backlog 65535 - --tcp-backlog 65535
@ -125,6 +107,11 @@ services:
hard: 65535 hard: 65535
networks: networks:
- ppanel_net - ppanel_net
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
logging: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -132,19 +119,21 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 4. Loki (日志存储) # 4. Tempo (链路追踪存储)
# ---------------------------------------------------- # ----------------------------------------------------
loki: tempo:
image: grafana/loki:3.0.0 image: grafana/tempo:2.4.1
container_name: ppanel-loki container_name: ppanel-tempo
user: root
restart: always restart: always
command:
- "-config.file=/etc/tempo.yaml"
- "-target=all"
volumes: volumes:
# 必须上传 loki 目录到服务器 - ./tempo/tempo-config.yaml:/etc/tempo.yaml
- ./loki/loki-config.yaml:/etc/loki/local-config.yaml - ./tempo_data:/var/tempo
- loki_data:/loki # 不对外暴露端口,仅内网访问(容器名: tempo
command: -config.file=/etc/loki/local-config.yaml # ppanel-server 通过容器名 tempo:4317 发送 trace
ports:
- "3100:3100"
networks: networks:
- ppanel_net - ppanel_net
logging: logging:
@ -154,7 +143,27 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 5. Promtail (日志采集) # 5. Loki (日志存储)
# ----------------------------------------------------
loki:
image: grafana/loki:3.0.0
container_name: ppanel-loki
restart: always
volumes:
- ./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"
# ----------------------------------------------------
# 6. Promtail (日志采集)
# ---------------------------------------------------- # ----------------------------------------------------
promtail: promtail:
image: grafana/promtail:3.0.0 image: grafana/promtail:3.0.0
@ -164,9 +173,7 @@ services:
- ./loki/promtail-config.yaml:/etc/promtail/config.yaml - ./loki/promtail-config.yaml:/etc/promtail/config.yaml
- /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 - /var/run/docker.sock:/var/run/docker.sock
# 采集当前目录下的 logs 文件夹
- ./logs:/var/log/ppanel-server:ro - ./logs:/var/log/ppanel-server:ro
# 采集 Nginx 访问日志(用于追踪邀请码来源)
- /var/log/nginx:/var/log/nginx:ro - /var/log/nginx:/var/log/nginx:ro
command: -config.file=/etc/promtail/config.yaml command: -config.file=/etc/promtail/config.yaml
networks: networks:
@ -180,27 +187,29 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 6. Grafana (日志界面) # 7. Grafana (可观测面板)
# 访问: ssh -L 3333:localhost:3333 your-server 后浏览器打开 http://localhost:3333
# 或配置 Nginx 反代(建议加认证)
# ---------------------------------------------------- # ----------------------------------------------------
grafana: grafana:
image: grafana/grafana:latest image: grafana/grafana:latest
container_name: ppanel-grafana container_name: ppanel-grafana
restart: always restart: always
ports: ports:
- "3333:3000" - "127.0.0.1:3333:3000" # 仅本机可访问,需 SSH 隧道或 Nginx 反代
environment: environment:
- GF_SECURITY_ADMIN_PASSWORD=admin - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:?请在 .env 文件中设置 GRAFANA_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false - GF_USERS_ALLOW_SIGN_UP=false
- GF_FEATURE_TOGGLES_ENABLE=appObservability #- GF_INSTALL_PLUGINS=redis-datasource - GF_FEATURE_TOGGLES_ENABLE=appObservability
volumes: volumes:
- grafana_data:/var/lib/grafana - grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning - ./grafana/provisioning:/etc/grafana/provisioning
extra_hosts:
- "host.docker.internal:host-gateway"
networks: networks:
- ppanel_net - ppanel_net
depends_on: depends_on:
- loki - loki
- tempo
- prometheus
logging: logging:
driver: "json-file" driver: "json-file"
options: options:
@ -208,25 +217,22 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 7. Prometheus (指标采集) # 8. Prometheus (指标采集)
# ---------------------------------------------------- # ----------------------------------------------------
prometheus: prometheus:
image: prom/prometheus:latest image: prom/prometheus:latest
container_name: ppanel-prometheus container_name: ppanel-prometheus
restart: always restart: always
ports: ports:
- "9090:9090" # 暴露端口便于调试 - "127.0.0.1:9090:9090" # 仅本机可访问
volumes: volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus - prometheus_data:/prometheus
extra_hosts:
- "host.docker.internal:host-gateway"
command: command:
- '--config.file=/etc/prometheus/prometheus.yml' - '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus' - '--storage.tsdb.path=/prometheus'
- '--web.enable-lifecycle' - '--web.enable-lifecycle'
- '--web.enable-remote-write-receiver' - '--web.enable-remote-write-receiver'
networks: networks:
- ppanel_net - ppanel_net
logging: logging:
@ -236,7 +242,7 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 8. Redis Exporter (Redis指标导出) # 9. Redis Exporter
# ---------------------------------------------------- # ----------------------------------------------------
redis-exporter: redis-exporter:
image: oliver006/redis_exporter:latest image: oliver006/redis_exporter:latest
@ -255,13 +261,12 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 9. Nginx Exporter (监控宿主机 Nginx) # 10. Nginx Exporter (监控宿主机 Nginx)
# ---------------------------------------------------- # ----------------------------------------------------
nginx-exporter: nginx-exporter:
image: nginx/nginx-prometheus-exporter:latest image: nginx/nginx-prometheus-exporter:latest
container_name: ppanel-nginx-exporter container_name: ppanel-nginx-exporter
restart: always restart: always
# 使用 host.docker.internal 访问宿主机
command: command:
- -nginx.scrape-uri=http://host.docker.internal:8090/nginx_status - -nginx.scrape-uri=http://host.docker.internal:8090/nginx_status
extra_hosts: extra_hosts:
@ -275,7 +280,7 @@ services:
max-file: "3" max-file: "3"
# ---------------------------------------------------- # ----------------------------------------------------
# 10. MySQL Exporter (MySQL指标导出) # 11. MySQL Exporter
# ---------------------------------------------------- # ----------------------------------------------------
mysql-exporter: mysql-exporter:
image: prom/mysqld-exporter:latest image: prom/mysqld-exporter:latest
@ -347,7 +352,6 @@ volumes:
prometheus_data: prometheus_data:
tempo_data: tempo_data:
networks: networks:
ppanel_net: ppanel_net:
name: ppanel_net name: ppanel_net

View File

@ -15,19 +15,19 @@ Logger: # 日志配置
Level: debug # 日志级别: debug, info, warn, error, panic, fatal Level: debug # 日志级别: debug, info, warn, error, panic, fatal
MySQL: MySQL:
Addr: 127.0.0.1:3306 # MySQL地址 Addr: mysql:3306 # Docker 容器名; 本地开发改为 127.0.0.1:3306
Username: root # MySQL用户名 (与创建的用户一致) Username: root # MySQL用户名
Password: rootpassword # MySQL密码 (换成之前生成的随机密码) Password: CHANGE_ME_MYSQL_PASSWORD # MySQL密码与 .env MYSQL_ROOT_PASSWORD 一致
Dbname: ppanel # MySQL数据库名 (与脚本创建的数据库一致) Dbname: ppanel # MySQL数据库名
Config: charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai Config: charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
MaxIdleConns: 10 MaxIdleConns: 10
MaxOpenConns: 100 MaxOpenConns: 100
LogMode: debug LogMode: info # 生产建议 info开发用 debug
LogZap: true LogZap: true
SlowThreshold: 1000 SlowThreshold: 1000
Redis: Redis:
Host: 127.0.0.1:6379 # Redis地址格式host:port Host: redis:6379 # Docker 容器名; 本地开发改为 127.0.0.1:6379
Pass: # Redis密码如果没有设置密码可以留空 Pass: # Redis密码如果没有设置密码可以留空
DB: 0 # Redis数据库编号默认0 DB: 0 # Redis数据库编号默认0
PoolSize: 100 # 连接池大小最大连接数根据应用并发量调整建议小流量50-100中流量100-300大流量300-500 PoolSize: 100 # 连接池大小最大连接数根据应用并发量调整建议小流量50-100中流量100-300大流量300-500
@ -55,6 +55,12 @@ AppSignature:
Signature: Signature:
EnableSignature: false # 系统签名开关(实际运行会以数据库 system.signature.EnableSignature 为准) EnableSignature: false # 系统签名开关(实际运行会以数据库 system.signature.EnableSignature 为准)
Trace: # 链路追踪配置 (OpenTelemetry)
Name: ppanel # 服务名
Sampler: 1.0 # 采样率 0.0-1.0,生产建议 0.1
Batcher: otlpgrpc # 本地开发留空""; 生产填 otlpgrpc
Endpoint: "tempo:4317" # Docker 容器名; 本地开发留空""
Administrator: Administrator:
Email: admin@ppanel.dev # 后台登录邮箱,请修改 Email: admin@ppanel.dev # 后台登录邮箱,请修改
Password: CHANGE_ME_TO_STRONG_PASSWORD # 后台登录密码,请修改为强密码 Password: CHANGE_ME_TO_STRONG_PASSWORD # 后台登录密码,请修改为强密码

View File

@ -12,7 +12,7 @@ import (
func UnbindDeviceHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { func UnbindDeviceHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) { return func(c *gin.Context) {
var req types.UnbindDeviceRequest var req types.UnbindDeviceRequest
_ = c.ShouldBindJSON(&req) _ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req) validateErr := svcCtx.Validate(&req)
if validateErr != nil { if validateErr != nil {
result.ParamErrorResult(c, validateErr) result.ParamErrorResult(c, validateErr)

View File

@ -107,11 +107,14 @@ func (m *Service) Start() {
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
}, },
} }
trace.StartAgent(trace.Config{ traceCfg := m.svc.Config.Trace
Name: "ppanel", if traceCfg.Name == "" {
Sampler: 1.0, traceCfg.Name = "ppanel"
Batcher: "", }
}) if traceCfg.Sampler == 0 {
traceCfg.Sampler = 1.0
}
trace.StartAgent(traceCfg)
proc.AddShutdownListener(func() { proc.AddShutdownListener(func() {
trace.StopAgent() trace.StopAgent()
}) })