diff --git a/docs/AML_Backend/docker-compose本地开发.md b/docs/AML_Backend/docker-compose本地开发.md new file mode 100644 index 0000000..f0c9bbd --- /dev/null +++ b/docs/AML_Backend/docker-compose本地开发.md @@ -0,0 +1,172 @@ +# AML_Backend 本地开发(docker-compose)使用说明 + +用 docker-compose 在本地一键拉起 `iCON.Abp.FX.HttpApi.Host`,包含 SQL Server 数据库容器,并自动完成数据库迁移与种子数据初始化,用于本地开发调试。 + +> 适用平台:macOS(含 Apple Silicon / arm64)。相关文件均位于 `AML_Backend/` 目录下。 + +--- + +## 1. 架构概览 + +`docker-compose.local.yml` 定义三个服务: + +| 服务 | 作用 | 说明 | +|------|------|------| +| `mssql` | SQL Server 2022 数据库 | arm64 上通过 `platform: linux/amd64`(Rosetta 模拟)运行;数据持久化在命名卷 `mssql-data` | +| `db-migrator` | 数据初始化 | 运行一次:执行 EF Core 迁移 + 种子数据,完成后退出(exit 0) | +| `httpapi-host` | 后端 API 主机 | 等 `db-migrator` 成功后才启动;对外暴露 `44331` | + +启动顺序由健康检查与 `depends_on` 保证:`mssql` 健康 → `db-migrator` 跑完 → `httpapi-host` 启动。 + +配套文件: +- `Dockerfile.local`:本地多阶段构建镜像(**.NET 6**),产出 `host` 与 `migrator` 两个目标。 +- `Dockerfile.local.dockerignore`:本地构建专用忽略表(保留 `appsettings.json`,仅排除 `bin/obj/.git` 等)。 + +> ⚠️ 仓库自带的 CI 用 `src/iCON.Abp.FX.HttpApi.Host/Dockerfile` 已过时(写的是 .NET 5、且 COPY 一个不存在的 `src/access-token.bin`),**不要**用它做本地构建,请使用 `Dockerfile.local`。 + +--- + +## 2. 前置条件 + +1. **Docker Desktop** 已安装并运行。 +2. **内存 ≥ 16 GB**:SQL Server 2022 在 Apple Silicon 上是 amd64 模拟运行,内存不足会 SIGSEGV(exit 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 -f 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` | +| 应用管理员 | `admin@abp.io` / `1q2w3E*` | + +种子数据包含:管理员账号、249 个国家、155 种货币、转账类型、文本模板、检测阈值等(共约 124 张表)。 + +--- + +## 6. 常用操作 + +```bash +cd AML_Backend + +# 查看后端日志(注意: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`)。 +- 屏蔽不可达的外部集成:`AppConfig__RabbitMQConfig__HostName=127.0.0.1`(快速失败)、`...__EnableConsumer=false`;关闭 `SanctionJob`、`EngineListSyncJob`。 + +> 仍有部分检测功能依赖 Elasticsearch / iCS 等远程或局域网服务,本 compose 未包含。如需本地联调这些功能,需另行配置对应服务地址。 + +--- + +## 8. 故障排查 + +| 现象 | 原因 | 解决 | +|------|------|------| +| `httpapi-host` 反复重启 / exit 214,日志含 `ABP-LIC-0008` | ABP 授权令牌缺失或过期 | 按第 3 节生成 `~/.abp/cli/access-token.bin`,确认 compose 挂载,重启服务 | +| `mssql` exit 139(SIGSEGV)、状态 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` 未改 | + +--- + +## 9. 相关文件清单 + +``` +AML_Backend/ +├─ docker-compose.local.yml # 本地三服务编排(本说明对应文件) +├─ Dockerfile.local # 本地 .NET 6 多阶段构建(host / migrator 两个目标) +├─ Dockerfile.local.dockerignore # 本地构建忽略表(保留 appsettings.json) +└─ src/iCON.Abp.FX.HttpApi.Host/ # API 主机工程 +```