Files
asset_helper/prompt/v1.md
2026-03-28 18:01:45 +08:00

589 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 资产管理系统后端骨架 - 技术需求 V1Docker 全环境版)
> 执行目标:基于纯 Docker 环境构建可编译、可运行的最小化后端骨架,无宿主机依赖(无全局 Go/Protoc/Postgres/Redis 环境)
> 技术栈锁定golang:1.26.1-alpine3.23、postgres:18.3-alpine3.23、redis:8.6.2-alpine、Docker/Docker Compose
## 一、核心调整说明
1. **基础镜像版本统一**:所有 Go 构建/运行、数据库、缓存镜像均替换为指定版本
2. **纯 Docker 环境闭环**
- 宿主机无依赖(无需安装 Go/Protoc/Make 等)
- 所有构建/编译/运行操作均通过 Docker 容器完成
- 新增 Protoc 构建容器(解决 proto 文件编译依赖)
3. **路径与权限优化**:适配 Alpine 3.23 镜像特性,调整文件权限和执行逻辑
## 二、完整目录结构(./backend/ 根)
```
./backend/
├── gateway/
│ ├── cmd/
│ │ └── main.go
│ ├── internal/
│ │ ├── config/
│ │ │ └── config.go
│ │ ├── ws/
│ │ │ ├── hub.go
│ │ │ ├── client.go
│ │ │ └── message.go
│ │ └── router/
│ │ └── router.go
│ ├── go.mod
│ └── Dockerfile
├── services/
│ └── user-svc/
│ ├── cmd/
│ │ └── main.go
│ ├── internal/
│ │ ├── config/
│ │ │ └── config.go
│ │ ├── domain/
│ │ │ └── user.go
│ │ ├── repository/
│ │ │ └── repo.go
│ │ ├── service/
│ │ │ └── service.go
│ │ └── grpcserver/
│ │ └── server.go
│ ├── proto/
│ │ └── user.proto
│ ├── migrations/
│ │ └── 001_init.sql
│ ├── go.mod
│ └── Dockerfile
├── shared/
│ ├── proto/
│ │ ├── common/
│ │ │ └── common.proto
│ │ └── generate.go
│ └── pkg/
│ ├── logger/
│ │ └── logger.go
│ ├── errors/
│ │ └── errors.go
│ ├── database/
│ │ └── postgres.go
│ └── cache/
│ └── redis.go
├── scripts/
│ ├── dev-start.sh # 纯 Docker 启动脚本
│ ├── gen-proto.sh # Docker 内编译 proto
│ └── docker-proto-builder/ # Protoc 编译容器配置
│ └── Dockerfile
├── docker-compose.yml # 全服务编排(含 proto 编译、Go 构建)
├── docker-compose.dev.yml # 开发模式编排(挂载源码、热更新)
├── Makefile # 封装 Docker 命令(兼容无宿主机 Make 环境)
└── README.md # 纯 Docker 环境使用说明
```
## 三、核心文件调整(适配指定技术栈 + 纯 Docker 环境)
### 3.1 基础镜像统一替换
所有 Dockerfile/Compose 文件中的基础镜像替换为指定版本:
- Go 构建/运行:`golang:1.26.1-alpine3.23`
- PostgreSQL`postgres:18.3-alpine3.23`
- Redis`redis:8.6.2-alpine`
- 基础运行镜像:`alpine:3.23`
### 3.2 ./backend/gateway/Dockerfile
```dockerfile
# 构建阶段:使用指定 Go 版本
FROM golang:1.26.1-alpine3.23 AS builder
WORKDIR /build
# 安装依赖Alpine 3.23 适配)
RUN apk add --no-cache git ca-certificates tzdata
ENV TZ=Asia/Shanghai
# 复制共享代码和网关代码
COPY ../shared /shared
COPY . /build
# 替换模块路径并构建(关闭 CGO 适配 Alpine
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o gateway ./cmd
# 运行阶段:轻量 Alpine
FROM alpine:3.23
RUN apk add --no-cache ca-certificates tzdata
ENV TZ=Asia/Shanghai
WORKDIR /app
# 复制构建产物
COPY --from=builder /build/gateway .
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# 权限优化(非 root 运行)
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 8080
# 优雅退出配置
STOPSIGNAL SIGTERM
CMD ["./gateway"]
```
### 3.3 ./backend/services/user-svc/Dockerfile
```dockerfile
# 构建阶段
FROM golang:1.26.1-alpine3.23 AS builder
WORKDIR /build
RUN apk add --no-cache git ca-certificates tzdata
ENV TZ=Asia/Shanghai
# 复制共享代码和用户服务代码
COPY ../../shared /shared
COPY . /build
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o user-svc ./cmd
# 运行阶段
FROM alpine:3.23
RUN apk add --no-cache ca-certificates tzdata
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=builder /build/user-svc .
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# 非 root 运行
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 50051
STOPSIGNAL SIGTERM
CMD ["./user-svc"]
```
### 3.4 ./backend/scripts/docker-proto-builder/Dockerfile
```dockerfile
# Protoc 编译专用容器(解决宿主机无 Protoc 依赖)
FROM golang:1.26.1-alpine3.23
# 安装 Protoc 及 Go 插件
RUN apk add --no-cache protobuf git
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.0
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1
# 配置环境变量
ENV PATH="$PATH:/go/bin"
ENV GOPATH="/go"
WORKDIR /proto
CMD ["protoc", "--version"]
```
### 3.5 ./backend/scripts/gen-proto.sh
```bash
#!/bin/sh
# 纯 Docker 环境编译 Proto 文件(无宿主机 Protoc 依赖)
set -e
# 进入项目根目录
SCRIPT_DIR=$(cd $(dirname $0)/.. && pwd)
cd $SCRIPT_DIR
# 构建 Protoc 编译容器并执行编译
docker build -t proto-builder:latest ./scripts/docker-proto-builder/
# 运行编译容器(挂载 proto 目录)
docker run --rm \
-v $SCRIPT_DIR/shared/proto:/proto \
-w /proto \
proto-builder:latest \
sh -c "for f in */*.proto; do \
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
\$f; \
done"
echo "✅ Proto 文件编译完成Docker 环境)"
```
### 3.6 ./backend/docker-compose.yml
```yaml
version: '3.8'
services:
# Proto 编译服务(一次性执行)
proto-builder:
build: ./scripts/docker-proto-builder/
volumes:
- ./shared/proto:/proto
command: sh -c "/proto/../scripts/gen-proto.sh"
profiles: ["proto"]
# 网关服务
gateway:
build: ./gateway
ports:
- "8080:8080"
environment:
- WS_ADDR=:8080
- REDIS_ADDR=redis:6379
depends_on:
- redis
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- backend-network
# 用户服务
user-svc:
build: ./services/user-svc
ports:
- "50051:50051"
environment:
- DB_HOST=user-db
- DB_PORT=5432
- DB_USER=postgres
- DB_PASSWORD=postgres
- DB_NAME=user_db
- GRPC_ADDR=:50051
depends_on:
- user-db
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- backend-network
# PostgreSQL 数据库(指定版本)
user-db:
image: postgres:18.3-alpine3.23
ports:
- "5432:5432"
environment:
- POSTGRES_DB=user_db
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --lc-collate=C --lc-ctype=C
volumes:
- user_data:/var/lib/postgresql/data
- ./services/user-svc/migrations:/docker-entrypoint-initdb.d
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d user_db"]
interval: 5s
timeout: 3s
retries: 5
networks:
- backend-network
# Redis 缓存(指定版本)
redis:
image: redis:8.6.2-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes --requirepass ""
volumes:
- redis_data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
networks:
- backend-network
volumes:
user_data:
redis_data:
networks:
backend-network:
driver: bridge
```
### 3.7 ./backend/docker-compose.dev.yml开发模式挂载源码
```yaml
version: '3.8'
services:
gateway:
build: ./gateway
ports:
- "8080:8080"
environment:
- WS_ADDR=:8080
- REDIS_ADDR=redis:6379
depends_on:
- redis
volumes:
- ./gateway:/build
- ./shared:/shared
command: sh -c "go run cmd/main.go"
restart: on-failure
networks:
- backend-network
user-svc:
build: ./services/user-svc
ports:
- "50051:50051"
environment:
- DB_HOST=user-db
- DB_PORT=5432
- DB_USER=postgres
- DB_PASSWORD=postgres
- DB_NAME=user_db
- GRPC_ADDR=:50051
depends_on:
- user-db
volumes:
- ./services/user-svc:/build
- ./shared:/shared
command: sh -c "go run cmd/main.go"
restart: on-failure
networks:
- backend-network
# 复用主 Compose 的数据库/缓存服务
user-db:
extends:
file: docker-compose.yml
service: user-db
redis:
extends:
file: docker-compose.yml
service: redis
volumes:
user_data:
redis_data:
networks:
backend-network:
driver: bridge
```
### 3.8 ./backend/scripts/dev-start.sh
```bash
#!/bin/sh
set -e
# 纯 Docker 环境启动脚本(无宿主机依赖)
SCRIPT_DIR=$(cd $(dirname $0)/.. && pwd)
cd $SCRIPT_DIR
echo "======================================"
echo " Asset Helper Backend (Docker 环境) "
echo "======================================"
# 停止旧容器
echo "🔄 停止旧容器..."
docker-compose -f docker-compose.yml down -v 2>/dev/null || true
# 编译 Proto 文件Docker 内执行)
echo "📝 编译 Proto 文件..."
./scripts/gen-proto.sh
# 启动开发环境
echo "🚀 启动开发容器..."
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d
# 等待服务就绪
echo "⌛ 等待服务初始化..."
sleep 10
# 检查服务状态
echo "✅ 服务状态检查:"
docker-compose -f docker-compose.yml ps
# 健康检查
echo "\n📊 健康检查:"
docker run --rm --network backend_backend-network curlimages/curl:8.7.1 -s http://gateway:8080/health || echo "⚠️ Gateway 服务未就绪"
# 输出访问信息
echo "\n📌 访问信息:"
echo "Gateway WebSocket: ws://localhost:8080/ws"
echo "Health Check: http://localhost:8080/health"
echo "User gRPC: localhost:50051"
echo "PostgreSQL: localhost:5432 (user: postgres, pass: postgres, db: user_db)"
echo "Redis: localhost:6379"
echo "\n💡 查看日志docker-compose -f docker-compose.yml logs -f"
echo "💡 停止服务docker-compose -f docker-compose.yml down -v"
```
### 3.9 ./backend/Makefile兼容无宿主机 Make 环境)
```makefile
.PHONY: dev build proto test down logs clean
# 兼容无宿主机 Make 环境:通过 Docker 执行核心操作
dev:
@echo "启动开发环境(纯 Docker..."
@./scripts/dev-start.sh
build:
@echo "构建生产镜像..."
@docker-compose -f docker-compose.yml build
proto:
@echo "编译 Proto 文件Docker 内)..."
@./scripts/gen-proto.sh
test:
@echo "执行健康检查..."
@docker run --rm --network backend_backend-network curlimages/curl:8.7.1 -s http://gateway:8080/health || echo "Gateway 服务未运行"
down:
@echo "停止并清理容器..."
@docker-compose -f docker-compose.yml -f docker-compose.dev.yml down -v
logs:
@echo "实时查看日志..."
@docker-compose -f docker-compose.yml -f docker-compose.dev.yml logs -f
clean: down
@echo "清理镜像和数据卷..."
@docker system prune -f
@docker volume rm backend_user_data backend_redis_data 2>/dev/null || true
```
### 3.10 ./backend/README.md纯 Docker 环境说明)
```markdown
# Asset Helper Backend
资产管理系统后端服务(纯 Docker 环境版)
## 核心特性
- 📦 全 Docker 环境:无需宿主机安装 Go/Protoc/Postgres/Redis 等依赖
- 🔒 安全配置:非 root 用户运行容器、权限最小化
- 🚀 开发/生产双模式:开发模式挂载源码,生产模式构建镜像
- 🛡️ 健康检查:自动检测服务状态,快速定位问题
## 环境要求
- Docker 20.10+
- Docker Compose 2.0+
- 无其他宿主机依赖(无需 Go/Protoc/Make/Postgres/Redis
## 快速开始
```bash
# 进入后端目录
cd ./backend
# 启动开发环境(自动编译 Proto + 启动所有服务)
make dev
# 检查服务状态
make test
# 查看实时日志
make logs
# 停止并清理环境
make down
# 清理所有镜像/数据卷(彻底重置)
make clean
```
## 服务端口
| 服务 | 端口 | 说明 |
|--------------|---------|-----------------------|
| gateway | 8080 | WebSocket + HTTP 入口 |
| user-svc | 50051 | gRPC 用户服务 |
| user-db | 5432 | PostgreSQL 数据库 |
| redis | 6379 | Redis 缓存 |
## 开发模式 vs 生产模式
### 开发模式(默认)
- 挂载本地源码到容器,支持实时修改
- 使用 `docker-compose.dev.yml` 扩展配置
- 自动重启 Go 服务(代码修改后需手动重启)
### 生产模式
```bash
# 构建生产镜像
make build
# 启动生产环境(无源码挂载)
docker-compose -f docker-compose.yml up -d
```
## 关键操作
### 编译 Proto 文件
```bash
make proto
```
### 健康检查
```bash
make test
# 或直接执行
curl http://localhost:8080/health
```
### 测试 WebSocket
```bash
# 安装 wscat或使用 Docker 版)
docker run --rm -it --network backend_backend-network jmalloc/websocket-client wss://gateway:8080/ws
> {"id":"1","type":"test","service":"user","action":"health"}
```
## 目录结构
```
./backend/ # 后端服务根目录
├── gateway/ # 网关服务WebSocket + HTTP
├── services/ # 微服务目录user-svc 示例)
├── shared/ # 共享代码/Proto/工具包
├── scripts/ # 自动化脚本Docker 环境适配)
├── docker-compose.yml # 生产环境编排
├── docker-compose.dev.yml # 开发环境编排
└── Makefile # 快捷命令封装
```
## 技术栈版本
- Go: 1.26.1-alpine3.23
- PostgreSQL: 18.3-alpine3.23
- Redis: 8.6.2-alpine
- Docker: 20.10+
- Docker Compose: 2.0+
```
## 四、验证标准(纯 Docker 环境)
### 4.1 执行命令
```bash
cd ./backend
make dev
```
### 4.2 预期结果
1. 容器启动:`gateway`/`user-svc`/`user-db`/`redis` 4 个容器状态为 `Up`
2. Proto 编译:无报错,`shared/proto/common/` 生成 `common.pb.go``common_grpc.pb.go`
3. 健康检查:`make test` 返回 `{"status":"ok"}`
4. 端口可访问:
- `ws://localhost:8080/ws` 可建立 WebSocket 连接
- `localhost:5432` 可连接 PostgreSQL
- `localhost:6379` 可连接 Redis
### 4.3 生产环境验证
```bash
# 构建生产镜像
make build
# 启动生产环境
docker-compose up -d
# 验证无源码挂载,服务正常运行
docker-compose ps
curl http://localhost:8080/health
```
## 五、关键优化点(适配纯 Docker 环境)
1. **Protoc 编译容器化**:无需宿主机安装 Protoc通过专用容器完成 proto 编译
2. **依赖全内置**:所有 Go 模块、系统依赖均在 Docker 内安装,无宿主机依赖
3. **权限安全**:容器内使用非 root 用户运行服务,降低安全风险
4. **健康检查**PostgreSQL/Redis 增加健康检查,确保服务就绪后启动应用
5. **日志与重启策略**:配置合理的重启策略和日志输出,便于问题排查
6. **网络隔离**:使用自定义网络,避免端口冲突和网络安全问题
## 六、执行说明(给 Trae 的指令)
1. 确保目标机器已安装 Docker 和 Docker Compose
2. 将上述目录结构和文件完整生成到 `./backend/` 目录
3. 执行 `cd ./backend && make dev` 启动环境
4. 验证 `make test` 返回 `{"status":"ok"}` 即完成基础架构搭建
5. 后续业务逻辑开发可基于此骨架,通过挂载源码的开发模式迭代