使用 pg 替换 sql
This commit is contained in:
+5
-1
@@ -1,6 +1,9 @@
|
|||||||
PORT=8080
|
PORT=8080
|
||||||
JWT_SECRET=your_very_secure_jwt_secret_here_change_me_in_production
|
JWT_SECRET=your_very_secure_jwt_secret_here_change_me_in_production
|
||||||
DB_PATH=data/app.db
|
POSTGRES_USER=affiliate
|
||||||
|
POSTGRES_PASSWORD=affiliate_dev_password
|
||||||
|
POSTGRES_DB=affiliate_dash
|
||||||
|
DATABASE_URL=postgres://affiliate:affiliate_dev_password@127.0.0.1:5432/affiliate_dash?sslmode=disable
|
||||||
GIN_MODE=release
|
GIN_MODE=release
|
||||||
OPEN_API_KEY=sk_source_dev_key_change_me
|
OPEN_API_KEY=sk_source_dev_key_change_me
|
||||||
OPEN_API_SECRET=sk_source_dev_secret_change_me
|
OPEN_API_SECRET=sk_source_dev_secret_change_me
|
||||||
@@ -9,6 +12,7 @@ OPEN_API_DEBUG=false
|
|||||||
LOG_FILE=logs/app.log
|
LOG_FILE=logs/app.log
|
||||||
|
|
||||||
# Docker 构建基础镜像;如镜像源不可用,可改为官方镜像或你的私有镜像源
|
# Docker 构建基础镜像;如镜像源不可用,可改为官方镜像或你的私有镜像源
|
||||||
|
POSTGRES_IMAGE=docker.m.daocloud.io/library/postgres:16-alpine
|
||||||
GO_BUILDER_IMAGE=docker.m.daocloud.io/library/golang:1.26-alpine
|
GO_BUILDER_IMAGE=docker.m.daocloud.io/library/golang:1.26-alpine
|
||||||
BACKEND_RUNTIME_IMAGE=docker.m.daocloud.io/library/alpine:3.22
|
BACKEND_RUNTIME_IMAGE=docker.m.daocloud.io/library/alpine:3.22
|
||||||
NODE_BUILDER_IMAGE=docker.m.daocloud.io/library/node:22-alpine
|
NODE_BUILDER_IMAGE=docker.m.daocloud.io/library/node:22-alpine
|
||||||
|
|||||||
+1
-6
@@ -8,16 +8,11 @@ FROM ${GO_BUILDER_IMAGE} AS builder
|
|||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ARG GOSUMDB
|
ARG GOSUMDB
|
||||||
ARG ALPINE_MIRROR
|
|
||||||
ENV GOPROXY=${GOPROXY}
|
ENV GOPROXY=${GOPROXY}
|
||||||
ENV GOSUMDB=${GOSUMDB}
|
ENV GOSUMDB=${GOSUMDB}
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# SQLite 驱动依赖 CGO,构建阶段需要 C 编译工具 / SQLite driver needs CGO and a C toolchain
|
|
||||||
RUN sed -i "s|https://dl-cdn.alpinelinux.org/alpine|${ALPINE_MIRROR}|g; s|http://dl-cdn.alpinelinux.org/alpine|${ALPINE_MIRROR}|g" /etc/apk/repositories \
|
|
||||||
&& apk --no-cache add build-base
|
|
||||||
|
|
||||||
# 复制 Go 依赖文件 / Copy Go dependency files
|
# 复制 Go 依赖文件 / Copy Go dependency files
|
||||||
COPY backend/go.mod backend/go.sum ./
|
COPY backend/go.mod backend/go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
@@ -26,7 +21,7 @@ COPY backend ./backend
|
|||||||
WORKDIR /app/backend
|
WORKDIR /app/backend
|
||||||
|
|
||||||
# 构建 Go 二进制文件 / Build Go binary
|
# 构建 Go 二进制文件 / Build Go binary
|
||||||
RUN CGO_ENABLED=1 GOOS=linux go build -ldflags="-linkmode external -extldflags '-static'" -o /server ./cmd/server
|
RUN CGO_ENABLED=0 GOOS=linux go build -o /server ./cmd/server
|
||||||
|
|
||||||
# 最终运行镜像 / Runtime image
|
# 最终运行镜像 / Runtime image
|
||||||
FROM ${BACKEND_RUNTIME_IMAGE}
|
FROM ${BACKEND_RUNTIME_IMAGE}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"affiliate_dash/internal/config"
|
"affiliate_dash/internal/config"
|
||||||
"affiliate_dash/internal/handler"
|
"affiliate_dash/internal/handler"
|
||||||
@@ -15,7 +13,7 @@ import (
|
|||||||
"affiliate_dash/internal/service"
|
"affiliate_dash/internal/service"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,11 +31,7 @@ func main() {
|
|||||||
|
|
||||||
gin.SetMode(cfg.Mode)
|
gin.SetMode(cfg.Mode)
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(cfg.DBPath), 0o755); err != nil {
|
db, err := gorm.Open(postgres.Open(cfg.DatabaseURL), &gorm.Config{
|
||||||
log.Fatalf("create data dir: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := gorm.Open(sqlite.Open(cfg.DBPath), &gorm.Config{
|
|
||||||
Logger: applog.NewGormLogger(cfg.Mode),
|
Logger: applog.NewGormLogger(cfg.Mode),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -79,6 +73,7 @@ func main() {
|
|||||||
r := router.Setup(h)
|
r := router.Setup(h)
|
||||||
addr := ":" + cfg.Port
|
addr := ":" + cfg.Port
|
||||||
log.Printf("游戏皮肤分销系统 API 启动: http://localhost%s", addr)
|
log.Printf("游戏皮肤分销系统 API 启动: http://localhost%s", addr)
|
||||||
|
log.Printf("数据库: PostgreSQL")
|
||||||
log.Printf("默认管理员: admin / admin123")
|
log.Printf("默认管理员: admin / admin123")
|
||||||
log.Printf("开放接口鉴权: X-Api-Key + X-Timestamp + X-Nonce + X-Sign (HMAC-SHA256)")
|
log.Printf("开放接口鉴权: X-Api-Key + X-Timestamp + X-Nonce + X-Sign (HMAC-SHA256)")
|
||||||
if cfg.OpenAPIDebug {
|
if cfg.OpenAPIDebug {
|
||||||
|
|||||||
+7
-3
@@ -6,9 +6,10 @@ require (
|
|||||||
github.com/gin-contrib/cors v1.7.7
|
github.com/gin-contrib/cors v1.7.7
|
||||||
github.com/gin-gonic/gin v1.12.0
|
github.com/gin-gonic/gin v1.12.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
golang.org/x/crypto v0.54.0
|
golang.org/x/crypto v0.54.0
|
||||||
gorm.io/driver/sqlite v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/gorm v1.31.2
|
gorm.io/gorm v1.31.2
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,14 +25,16 @@ require (
|
|||||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
@@ -42,6 +45,7 @@ require (
|
|||||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||||
golang.org/x/arch v0.23.0 // indirect
|
golang.org/x/arch v0.23.0 // indirect
|
||||||
golang.org/x/net v0.56.0 // indirect
|
golang.org/x/net v0.56.0 // indirect
|
||||||
|
golang.org/x/sync v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.47.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/text v0.40.0 // indirect
|
golang.org/x/text v0.40.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.10 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
@@ -70,6 +78,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
|||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
@@ -90,6 +99,8 @@ golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
|||||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||||
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
@@ -101,6 +112,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||||
|
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||||
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||||
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||||
gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
|
gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Port string
|
Port string
|
||||||
JWTSecret string
|
JWTSecret string
|
||||||
DBPath string
|
DatabaseURL string
|
||||||
Mode string // debug / release
|
Mode string // debug / release
|
||||||
// OpenAPIKey 皮肤源头开放接口标识(Header: X-Api-Key,可公开给对接方)
|
// OpenAPIKey 皮肤源头开放接口标识(Header: X-Api-Key,可公开给对接方)
|
||||||
OpenAPIKey string
|
OpenAPIKey string
|
||||||
// OpenAPISecret 签名密钥(仅用于 HMAC,不走 Header)
|
// OpenAPISecret 签名密钥(仅用于 HMAC,不走 Header)
|
||||||
@@ -35,7 +35,7 @@ func Load() *Config {
|
|||||||
return &Config{
|
return &Config{
|
||||||
Port: getEnv("PORT", "8080"),
|
Port: getEnv("PORT", "8080"),
|
||||||
JWTSecret: getEnv("JWT_SECRET", "affiliate-dash-dev-secret-change-me"),
|
JWTSecret: getEnv("JWT_SECRET", "affiliate-dash-dev-secret-change-me"),
|
||||||
DBPath: getEnv("DB_PATH", "data/app.db"),
|
DatabaseURL: getEnv("DATABASE_URL", "postgres://affiliate:affiliate_dev_password@127.0.0.1:5432/affiliate_dash?sslmode=disable"),
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
OpenAPIKey: getEnv("OPEN_API_KEY", "sk_source_dev_key_change_me"),
|
OpenAPIKey: getEnv("OPEN_API_KEY", "sk_source_dev_key_change_me"),
|
||||||
OpenAPISecret: getEnv("OPEN_API_SECRET", "sk_source_dev_secret_change_me"),
|
OpenAPISecret: getEnv("OPEN_API_SECRET", "sk_source_dev_secret_change_me"),
|
||||||
|
|||||||
+20
-1
@@ -1,4 +1,19 @@
|
|||||||
services:
|
services:
|
||||||
|
postgres:
|
||||||
|
image: ${POSTGRES_IMAGE:-docker.m.daocloud.io/library/postgres:16-alpine}
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${POSTGRES_USER:-affiliate}
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-affiliate_dev_password}
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB:-affiliate_dash}
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@@ -15,7 +30,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- JWT_SECRET=${JWT_SECRET}
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
- DB_PATH=/data/app.db
|
- DATABASE_URL=postgres://${POSTGRES_USER:-affiliate}:${POSTGRES_PASSWORD:-affiliate_dev_password}@postgres:5432/${POSTGRES_DB:-affiliate_dash}?sslmode=disable
|
||||||
- GIN_MODE=${GIN_MODE:-release}
|
- GIN_MODE=${GIN_MODE:-release}
|
||||||
- OPEN_API_KEY=${OPEN_API_KEY}
|
- OPEN_API_KEY=${OPEN_API_KEY}
|
||||||
- OPEN_API_SECRET=${OPEN_API_SECRET}
|
- OPEN_API_SECRET=${OPEN_API_SECRET}
|
||||||
@@ -30,6 +45,9 @@ services:
|
|||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
caddy:
|
caddy:
|
||||||
build:
|
build:
|
||||||
@@ -52,6 +70,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
postgres-data:
|
||||||
backend-data:
|
backend-data:
|
||||||
caddy-data:
|
caddy-data:
|
||||||
caddy-config:
|
caddy-config:
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ fi
|
|||||||
|
|
||||||
BACKEND_PORT="${PORT:-8080}"
|
BACKEND_PORT="${PORT:-8080}"
|
||||||
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
|
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
|
||||||
|
POSTGRES_USER="${POSTGRES_USER:-affiliate}"
|
||||||
|
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-affiliate_dev_password}"
|
||||||
|
POSTGRES_DB="${POSTGRES_DB:-affiliate_dash}"
|
||||||
|
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||||
|
POSTGRES_IMAGE="${POSTGRES_IMAGE:-docker.m.daocloud.io/library/postgres:16-alpine}"
|
||||||
|
DEV_DB_CONTAINER="${DEV_DB_CONTAINER:-affiliate_dash_postgres_dev}"
|
||||||
|
DATABASE_URL="${DATABASE_URL:-postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable}"
|
||||||
|
export DATABASE_URL
|
||||||
|
|
||||||
# 结束指定端口上的进程(避免残留占用)
|
# 结束指定端口上的进程(避免残留占用)
|
||||||
free_port() {
|
free_port() {
|
||||||
@@ -39,6 +47,44 @@ free_port() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_postgres() {
|
||||||
|
if (echo >"/dev/tcp/127.0.0.1/${POSTGRES_PORT}") >/dev/null 2>&1; then
|
||||||
|
log "检测到本机 PostgreSQL 端口已可访问: ${POSTGRES_PORT}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
log "未找到 Docker,请确认本机 PostgreSQL 已可通过 DATABASE_URL 访问"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if docker ps --format '{{.Names}}' | grep -qx "$DEV_DB_CONTAINER"; then
|
||||||
|
log "PostgreSQL 开发容器已运行: ${DEV_DB_CONTAINER}"
|
||||||
|
elif docker ps -a --format '{{.Names}}' | grep -qx "$DEV_DB_CONTAINER"; then
|
||||||
|
log "启动 PostgreSQL 开发容器: ${DEV_DB_CONTAINER}"
|
||||||
|
docker start "$DEV_DB_CONTAINER" >/dev/null
|
||||||
|
else
|
||||||
|
log "创建 PostgreSQL 开发容器: ${DEV_DB_CONTAINER}"
|
||||||
|
docker run -d \
|
||||||
|
--name "$DEV_DB_CONTAINER" \
|
||||||
|
-p "${POSTGRES_PORT}:5432" \
|
||||||
|
-e POSTGRES_USER="$POSTGRES_USER" \
|
||||||
|
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
|
||||||
|
-e POSTGRES_DB="$POSTGRES_DB" \
|
||||||
|
-v "${DEV_DB_CONTAINER}-data:/var/lib/postgresql/data" \
|
||||||
|
"$POSTGRES_IMAGE" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in $(seq 1 40); do
|
||||||
|
if docker exec "$DEV_DB_CONTAINER" pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then
|
||||||
|
log "PostgreSQL 已就绪"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
echo "错误: PostgreSQL 启动超时"
|
||||||
|
docker logs "$DEV_DB_CONTAINER" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
trap - INT TERM EXIT
|
trap - INT TERM EXIT
|
||||||
echo ""
|
echo ""
|
||||||
@@ -77,6 +123,7 @@ fi
|
|||||||
|
|
||||||
free_port "$BACKEND_PORT"
|
free_port "$BACKEND_PORT"
|
||||||
free_port "$FRONTEND_PORT"
|
free_port "$FRONTEND_PORT"
|
||||||
|
ensure_postgres
|
||||||
|
|
||||||
log "启动后端 http://localhost:${BACKEND_PORT}"
|
log "启动后端 http://localhost:${BACKEND_PORT}"
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user