AML/docker-compose-local-dev/readme.md

198 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# AML_Backend 本地开发docker-compose使用说明
用 docker-compose 在本地一键拉起 `iCON.Abp.FX.HttpApi.Host`,包含 SQL Server 数据库容器,并自动完成数据库迁移与种子数据初始化,用于本地开发调试。
> 适用平台macOS含 Apple Silicon / arm64。相关文件均位于 `AML_Backend/docker-compose-local-dev/` 目录下构建上下文build context是上一级的仓库根目录 `AML_Backend/`。
---
## 1. 架构概览
`docker-compose.local.yml` 定义四个服务:
| 服务 | 作用 | 说明 |
|------|------|------|
| `mssql` | SQL Server 2022 数据库 | arm64 上通过 `platform: linux/amd64`Rosetta 模拟)运行;数据持久化在命名卷 `mssql-data` |
| `rabbitmq` | 消息队列(异步任务中枢) | `rabbitmq:3.13-management`arm64 原生);`host`/`consumer` 靠它跑数据采集、报告生成、AI 检测、门户订单等异步链路。宿主端口错开为 `5673`/`15673`(见第 8 节) |
| `db-migrator` | 数据初始化 | 运行一次:执行 EF Core 迁移 + 种子数据完成后退出exit 0 |
| `httpapi-host` | 后端 API 主机 | 等 `db-migrator` 成功后才启动;对外暴露 `44331`;随宿主启动 `RabbitMQConsumerService` 消费上述队列 |
启动顺序由健康检查与 `depends_on` 保证:`mssql` + `rabbitmq` 健康 → `db-migrator` 跑完 → `httpapi-host` 启动。
配套文件(均在 `docker-compose-local-dev/` 内):
- `Dockerfile.local`:本地多阶段构建镜像(**.NET 6**),产出 `host``migrator` 两个目标。
- `Dockerfile.local.dockerignore`:本地构建专用忽略表(仅排除 `bin/obj/.git`。BuildKit 会优先采用「与 Dockerfile 同目录、同名 + `.dockerignore`」的这个文件,从而**覆盖**仓库根目录的 `.dockerignore`(根目录那个会把 `appsettings.json`、`docker-compose*` 都排除掉,不适用于本地构建)。
- `appsettings.local.json`**本地专用、绕过 Nacos 的完整配置**(见第 1.1 节),构建时会被覆盖进镜像的 `appsettings.json`
> ⚠️ 仓库自带的 CI 用 `src/iCON.Abp.FX.HttpApi.Host/Dockerfile` 已过时(写的是 .NET 5、且 COPY 一个不存在的 `src/access-token.bin`**不要**用它做本地构建,请使用 `Dockerfile.local`。
### 1.1 配置来源:为什么要绕过 Nacos
最新代码已把配置中心切到 **Nacos**`src/iCON.Abp.FX.HttpApi.Host/appsettings.json` 现在只剩一个 `NacosConfig`真正的配置连接串、AuthServer、AppConfig、RabbitMQ、任务开关等都从 Nacos 服务器 `http://192.168.1.120:8848`DataId `aml.dev.json`)拉取。
该 Nacos 地址是公司内网,本机通常不可达;且它指向的是共享 dev 环境(连接串指向远程 dev 库),与「本地自包含隔离栈」的目标冲突。
`Program.cs` 里 Nacos 是**条件加载**的——仅当配置里存在 `NacosConfig` 段才会 `AddNacosV2Configuration`。因此本地方案是:用 `appsettings.local.json`(一份**不含 `NacosConfig`、但包含完整配置**的文件)覆盖镜像里的 `appsettings.json`App 便不再尝试连接 Nacos直接用本地配置启动再由 compose 的环境变量把连接串等指向本地 `mssql` 容器。
> `appsettings.local.json` 取自 Nacos 改造前commit `297d3bb6` 的父提交)那版完整 `appsettings.json`,是目前唯一可自包含运行的完整配置快照。若今后 Nacos 里新增了启动必需的配置项,需要手动同步补进这个文件。
---
## 2. 前置条件
1. **Docker Desktop** 已安装并运行。
2. **内存 ≥ 16 GB**SQL Server 2022 在 Apple Silicon 上是 amd64 模拟运行,内存不足会 SIGSEGVexit 139
- 在 Docker Desktop → Settings → Resources → Memory 调到 16 GB或编辑 `~/Library/Group Containers/group.com.docker/settings-store.json` 加入 `"MemoryMiB": 16384` 后执行 `docker desktop restart`
3. **ABP 商业版授权令牌**(关键,见下一节)。
---
## 3. ABP 授权令牌(必须,否则 API 起不来)
`httpapi-host` 依赖 ABP 商业模块LanguageManagement、Lepton Commercial、Account Pro 等)。
启动时若授权校验失败,进程会直接终止:**exit 214 / `ABP-LIC-0008`**。
appsettings 内置的 `AbpLicenseCode` 是 2021 年的旧授权(已过期),因此需要用 `abp login` 生成的令牌。
> 注:`db-migrator` 不强制校验授权,所以数据迁移/种子在没有令牌时也能成功,只有 `httpapi-host` 需要令牌。
### 生成令牌(一次即可,令牌持久化在 `~/.abp/cli/`
本机若已安装 ABP CLI
```bash
abp login fengruixiang -o JustGroup -p <你的密码>
```
本机未安装 ABP CLI 时,可在容器内执行(令牌通过挂载落到宿主机 `~/.abp/cli/`
```bash
mkdir -p "$HOME/.abp"
docker run --rm -v "$HOME/.abp:/root/.abp" \
--entrypoint /bin/bash mcr.microsoft.com/dotnet/sdk:6.0 -lc '
export PATH="$PATH:/root/.dotnet/tools"
dotnet tool install --global Volo.Abp.Cli --version 6.0.3
abp login fengruixiang -o JustGroup -p <你的密码>
'
```
成功后会生成 `~/.abp/cli/access-token.bin`。`docker-compose.local.yml` 已把它只读挂载进容器:
```yaml
volumes:
- "${HOME}/.abp/cli:/root/.abp/cli:ro"
```
> 该令牌在**运行时联网**向 abp.io 校验授权,因此 `httpapi-host` 启动时需要网络。
---
## 4. 一键启动
```bash
cd AML_Backend/docker-compose-local-dev
docker compose -f docker-compose.local.yml up -d --build
```
> 也可在仓库根目录运行:`cd AML_Backend && docker compose -f docker-compose-local-dev/docker-compose.local.yml up -d --build`。
首次构建较慢(需还原大量 ABP 商业 NuGet 包并编译约 40 个项目,并拉取 SQL Server 镜像)。
构建已做内存优化(`-m:1` 单项目编译 + NuGet 缓存挂载),避免 Roslyn 因内存不足被杀OOM / exit 137
启动后验证:
```bash
docker compose -f docker-compose.local.yml ps
# httpapi-host 为 Up、db-migrator 为 Exited(0)、mssql 为 Up(healthy)
```
---
## 5. 访问信息
| 项目 | 地址 / 凭据 |
|------|------------|
| Swagger | http://localhost:44331/swagger FX API + AMLPortal API |
| OpenID 配置 | http://localhost:44331/.well-known/openid-configuration |
| 数据库 | `localhost,11433`,用户 `sa`,密码 `Aml@Local2026`,库名 `AbpAML` |
| RabbitMQ 管理台 | http://localhost:15673 ,用户 `admin` / 密码 `123456`vhost `bthost` |
| 应用管理员 | `admin@abp.io` / `1q2w3E*` |
种子数据包含管理员账号、249 个国家、155 种货币、转账类型、文本模板、检测阈值等(共约 124 张表)。
---
## 6. 常用操作
```bash
cd AML_Backend/docker-compose-local-dev
# 查看后端日志注意Release 构建日志写文件docker logs 可能为空,见下)
docker compose -f docker-compose.local.yml logs -f httpapi-host
# 停止(保留数据库卷)
docker compose -f docker-compose.local.yml down
# 重新启动
docker compose -f docker-compose.local.yml up -d
# 改了代码后重建并重启
docker compose -f docker-compose.local.yml up -d --build
# 仅重跑数据初始化(迁移+种子,幂等)
docker compose -f docker-compose.local.yml run --rm db-migrator
# 彻底重置数据库(删除数据卷后重来)
docker compose -f docker-compose.local.yml down -v
docker compose -f docker-compose.local.yml up -d --build
# 连接数据库执行 SQL
docker exec aml-mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P "Aml@Local2026" -C -d AbpAML -Q "SELECT COUNT(*) FROM AbpUsers"
```
---
## 7. 本地开发已做的环境覆盖
`httpapi-host` 通过环境变量覆盖了若干配置,让本地能干净启动:
- `ASPNETCORE_URLS=http://+:44331``App__SelfUrl` / `AuthServer__Authority=http://localhost:44331`(保证 IdentityServer 颁发者与浏览器访问地址一致),`AuthServer__RequireHttpsMetadata=false`。
- `ConnectionStrings__Default` 指向 `mssql` 服务(覆盖 appsettings 里的 `localhost`)。
- **RabbitMQ**`AppConfig__RabbitMQConfig__HostName=rabbitmq`(指向 compose 内的 broker、`...__EnableConsumer=true`(开启后台消费)。账号/vhost`admin`/`123456`/`bthost`)沿用 appsettings.local.json`rabbitmq` 服务的 `RABBITMQ_DEFAULT_*` 一致。
- **iCS**`AppConfig__iCS__iCSRootUrl=https://stag-abp-api.iconsz.com/`iCS 服务端不在本仓库,指向共享 stag 实例,让文档/问卷/检测引擎等功能可用。iCS 用的是 ZeroSSL/Sectigo 证书、且服务器只下发部分证书链;`Dockerfile.local` 的 `runtime-base` 阶段刷新了容器 CA 库,否则 HttpClient 会因 `PartialChain` 握手失败(应用自带的证书旁路只作用于旧式 WebClient不管 HttpClient
> 依赖 stag 那边的 iCS 凭证有效;若 stag 不可达或换了证书,相关功能会失败但不影响 host 启动。
- 仍关闭 `SanctionJob`(依赖本地未部署的 Elasticsearch。`EngineListSyncJob` 因 iCS 已指向 stag 而恢复默认启用。
> 仍有部分检测功能依赖 Elasticsearch`192.168.1.120:9200` 等)等远程/局域网服务,本 compose 未包含。如需本地联调,需另行配置对应服务地址。
---
## 8. 故障排查
| 现象 | 原因 | 解决 |
|------|------|------|
| `httpapi-host` 反复重启 / exit 214日志含 `ABP-LIC-0008` | ABP 授权令牌缺失或过期 | 按第 3 节生成 `~/.abp/cli/access-token.bin`,确认 compose 挂载,重启服务 |
| `mssql` exit 139SIGSEGV、状态 unhealthy | Apple Silicon 模拟下内存不足 | 把 Docker 内存调到 ≥16 GB第 2 节),`docker desktop restart` |
| 构建时 `csc.dll exited with code 137` / `cannot allocate memory` | 编译 `DbMigrations` 大项目时 OOM | 已用 `-m:1` 缓解;确保 Docker 内存充足,必要时串行构建 |
| `docker logs httpapi-host` 为空但服务异常 | Release 构建只写文件日志(`#if DEBUG` 才有控制台 sink日志在容器内 `/app/Logs/<级别>/<日期>/` | `docker cp aml-httpapi-host:/app/Logs ./Logs` 后查看,或临时用 `--build-arg BUILD_CONFIGURATION=Debug` 构建以获得控制台日志 |
| 访问 Swagger 401/跳转异常 | `AuthServer:Authority` 与实际访问地址不一致 | 确认仍是 `http://localhost:44331`,端口映射 `44331:44331` 未改 |
| 启动报 `Bind for 0.0.0.0:5672 failed: port is already allocated` | 宿主已有其它 RabbitMQ 占用 5672/15672 | 本 compose 已把宿主端口错开为 `5673`/`15673`;若仍冲突,改 `rabbitmq.ports` 即可(容器间通信走内部 5672不受影响 |
| 日志含 `SSL connection could not be established ... PartialChain` | 容器 CA 库无法补全 iCS(stag) 的 ZeroSSL 证书链,且 HttpClient 不认应用的证书旁路 | 由 `Dockerfile.local``runtime-base` 刷新 CA 库解决;若复现,确认镜像是最新构建(`--build`|
| iCS 功能报 401/token 失败(非 TLS | stag 那边的 iCS 凭证/租户失效 | 与后端确认 `AppConfig:iCS:Credential` 在 stag 是否有效;非致命,不影响 host |
---
## 9. 相关文件清单
```
AML_Backend/ # 构建上下文build context根目录
├─ NuGet.Config # ABP 商业源Dockerfile 会 COPY
├─ src/iCON.Abp.FX.HttpApi.Host/ # API 主机工程
└─ docker-compose-local-dev/ # ← 本地开发相关文件都在这里
├─ docker-compose.local.yml # 本地三服务编排(本说明对应文件)
├─ Dockerfile.local # 本地 .NET 6 多阶段构建host / migrator 两个目标)
├─ Dockerfile.local.dockerignore # 本地构建忽略表(覆盖根目录 .dockerignore
├─ appsettings.local.json # 绕过 Nacos 的完整本地配置(覆盖进镜像)
└─ docker-compose-local-dev.md # 本说明文档
```