
Address 架构拆解Astro、Hono、PostgreSQL 与同步服务如何在一个 Docker 文件里协作【免费下载链接】addressA self-hosted address and synthetic test-profile generator for 27 countries and regions, built from real open-data streets, administrative areas, coordinates, and postcodes. Supports multilingual output, IP-nearby generation, map previews, and API access. 基于真实开放数据的自托管地址与合成测试资料生成器覆盖 27 个国家和地区支持多语言地址、IP 附近生成、地图预览与 API 调用项目地址: https://gitcode.com/gh_mirrors/address4/address本文带你完整拆解 Address 自托管地址生成器的技术架构这是一个基于真实开放数据街道、行政区、坐标、邮编构建的地址与合成测试资料生成器覆盖 27 个国家与地区。它最巧妙的设计是——前端 Astro、API 框架 Hono、数据库 PostgreSQL、后台同步服务全部打包进同一个 Docker 镜像再由 docker-compose 拆分成 6 个协作的服务。下面我们就一层层拆开看。一、先看全局一套系统六个角色Address 的架构可以用一句话概括一份代码、一个镜像、六个容器。docker-compose.yml定义了这些服务服务角色一句话说明bootstrap一次性初始化启动前生成并落地所有密钥文件postgres数据底座PostgreSQL 16唯一的持久化存储migrate一次性迁移数据库结构升级跑完即退出api门面Hono 服务对外提供 API 和网页sync数据工厂定时拉取开放数据、跑 ETL、发布地址池credential-broker密钥管家统一管理第三方 API Key 的加密与调用它们通过两条内部网络协作internal内网隔离和egress对外出口。只有api把端口映射到宿主机默认127.0.0.1:8787其余服务全部藏在容器网络里天然安全。二、一个 Dockerfile 如何装下前端 API Python ETL很多自托管项目要么镜像臃肿、要么每个服务单独打包。Address 的 Dockerfile 用多阶段构建解决了两难1. build 阶段只干构建这一件事FROM node:24-bookworm AS build npm ci # 安装依赖 npm run build # 执行 Astro 构建产出 dist/Astro 采用output: static纯静态模式见 astro.config.mjs配合 React 组件渲染页面构建产物就是一堆 HTML/CSS/JS 文件。2. runtime 阶段一个全能运行环境runtime 阶段做了一件不寻常的事——给 Node 项目装 Python 虚拟环境apt-get install python3 python3-pip python3-venv python3 -m venv /srv/address/venv pip install -r server/sync/requirements.txt为什么因为sync同步服务要解析 Geofabrik 的 PBF 地图文件依赖 pyosmium 这类 Python/C 库。把 Python 环境提前烤进镜像同步服务开箱即用。同时它还内置了三个安全细节低权限用户创建非 root 的address用户入口脚本用gosu降权执行密钥不落镜像密码一律通过*_FILE环境变量指向挂载的密钥文件由 ops/container-entrypoint.sh 在启动时读入数据目录预置data/staging同步暂存区、runtime/sync-control调度状态提前创建并授权。build 阶段 ──► 产出 dist/ 静态文件 ──► runtime 阶段 ├─ Python venvsync 用 ├─ gosu 低权限用户 └─ entrypoint 读密钥文件 ──► 降权启动三、Hono一个进程同时当API 网关 静态服务器 反向代理生产环境没有 Nginx——server/api/server.ts 里的 Hono 实例身兼三职路由分发一个 fetch 函数管全部请求启动后按路径前缀把请求分流路径前缀去向认证方式/api/v1/*Hono 主 App公开 APIAPI Token/admin/api/*管理后台 API管理员会话/web-api/v1/*转发到主 AppWeb 登录态/sync-control/*反向代理到 sync 服务默认不公开其他静态文件serveStatic未登录跳转登录页这个设计最妙的地方在于Astro 构建出的静态页面由 Hono 用serveStatic直接吐出未登录用户访问任何页面都会被 302 重定向到多语言登录页。前端、API、鉴权在一个进程里闭环。内置限流生成接口不裸奔地址生成是 CPU 和数据库密集型操作所以代码里用InFlightLimiter给生成类接口加了并发闸——超限直接返回429 Retry-After防止并发风暴打垮数据库连接池。四、PostgreSQL一个库两个分身数据层是 Address 架构的定海神针。server/database/runtime.ts 启动时打开同一个 PostgreSQL 的两个逻辑连接address 库视角地址池、行政目录、位置坐标——生成器真正吐出的数据control 库视角管理员账号、API Token、服务商凭据、同步配置——系统自身的控制面。两者共用一个物理库但职责分明带来两个关键收益① 原子发布sync服务对每个国家维护候选区 → 校验 → 事务替换线上数据的流程。新批次地址先在候选表校验质量通过后在单个国家事务中切换 active 指针中途失败旧数据分毫不动。② 松耦合的后台sync 进程把队列快照写进数据库管理后台直接读库展示状态——即使同步进程正忙于导入日本的全量数据实测峰值 6.5 GB 内存仪表盘依然秒开。五、sync 服务镜像里最重的后台工人sync 服务是整套系统的数据工厂入口在 server/sync/index.mjs它同时干四件事调度器SYNC_SCHEDULER_ENABLEDtrue时自动补跑未完成的国家初始化每天定时重算执行资格ETL 管道通过 DuckDB 读 Overture GeoParquet、用 pyosmium 流式解析 Geofabrik PBF机构过滤、去重、住宅证据校验后写入发布校验publication-validation worker 每秒扫描发布批次不合格的国家自动退役管理 API监听 8791 端口提供手动触发同步POST /api/v1/sync/jobs等接口供管理后台一键同步。它还内置了一套资源护栏磁盘暂存区到 40 GB 停止扩容、可用内存低于 2 GiB 拒绝启动、临时产物定期清理——把大数据 ETL 的稳定性焦虑消化在进程内部。六、六个服务如何启动依赖顺序是灵魂docker-compose.yml里的启动顺序编排值得细品bootstrap生成密钥 └─► postgres健康检查通过 └─► migrate版本化迁移跑完退出 └─► credential-broker密钥代理就绪 ├─► api对外服务 └─► sync后台工厂migrate一次性迁移用restart: on-failure:3兜底跑完即成功退出api和sync都声明了/health或/api/v1/health健康检查Compose 会持续探活每个服务还挂了json-file日志轮转20 MB × 5 份防止磁盘被日志吃光。七、架构小结这套设计好在哪一个镜像 一份代码真相前端、API、ETL 全部同源构建不会出现前端版本和 API 版本对不上的事故静态化前端Astro 纯静态输出让 Hono 单进程就能服务页面省掉一层 Web 服务器数据原子性优先候选区 事务发布保证坏数据永远到不了线上安全默认值内网隔离、低权限运行、密钥文件化、API 限流全部内建而非靠运维自觉。如果你正在寻找一个能自托管、基于真实开放数据的地址生成器这套单镜像多服务的架构本身就是一份不错的参考教材。延伸阅读开发指南架构与目录说明docs/DEVELOPMENT.zh-CN.md部署文档docs/DEPLOYMENT.zh-CN.mdAPI 文档中/英/繁三语docs/API.zh-CN.md同步服务说明server/sync/README.md各国地址生成策略docs/strategies/【免费下载链接】addressA self-hosted address and synthetic test-profile generator for 27 countries and regions, built from real open-data streets, administrative areas, coordinates, and postcodes. Supports multilingual output, IP-nearby generation, map previews, and API access. 基于真实开放数据的自托管地址与合成测试资料生成器覆盖 27 个国家和地区支持多语言地址、IP 附近生成、地图预览与 API 调用项目地址: https://gitcode.com/gh_mirrors/address4/address创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考