本地部署地图服务全景调研:瓦片、导航与地理编码

1
2
3
$ docker run -d --name valhalla -p 8002:8002 ghcr.io/gis-ops/docker-valhalla/valhalla:latest
$ docker run -d --name nominatim -p 8088:8080 mediagis/nominatim:4.4
$ curl "http://localhost:8088/search?q=北京大学&format=json"

这篇文章整理一套本地部署地图服务的技术选型。目标不是复刻 Google Maps 的完整产品,而是给 Agent 或自托管应用提供稳定的地图 API:路线规划、地理编码、逆地理编码,以及按需可视化的地图底图。

调研时间是 2026-04-21。地图、路由和地理编码生态变化不算特别快,但具体镜像版本、数据大小和第三方项目状态仍然应该在部署前再核对一次。

需求与方案分层

一个完整的本地地图服务需要三层能力,它们是独立的组件,需要分别选型并组合:

  • 🗺️ 瓦片服务 (Tile Server):提供地图底图(向量瓦片或栅格瓦片),让用户看到地图
  • 🧭 路线导航 (Routing Engine):给定起止点,计算路径 + Turn-by-Turn 导航指令
  • 📍 地理编码 (Geocoding):地址 ↔ 坐标转换,搜索地点

此外还需要一个前端渲染库在浏览器中展示地图。所有组件都基于 OpenStreetMap (OSM) 数据。

💡 给 Agent 用:API 优先

给 Agent 装地图服务,最重要的是稳定的 HTTP API:路由查询、地理编码、逆地理编码。

地图瓦片渲染是可视化加分项。推荐优先保证 Routing + Geocoding API 可用,Tile Server 按需加。

瓦片服务 (Tile Server)

Protomaps + PMTiles

最轻量方案 · 单文件 · 瓦片 · ⭐ 推荐

全球向量瓦片打成单个 PMTiles 文件(~120GB 全球 / 区域提取更小),通过 HTTP Range Request 直接读取,无需数据库和专用服务器。

  • 全球文件大小:~115-120 GB(内部去重,比 MBTiles 小 70%+)。

  • 服务方式:任何支持 Range Request 的 HTTP 服务器(Nginx、S3、Caddy),或 pmtiles serve CLI。

  • 区域提取pmtiles extract planet.pmtiles china.pmtiles --bbox=73,18,135,54

  • 前端:MapLibre GL JS + PMTiles protocol,纯浏览器端解析。

  • 样式:自带 protomaps-themes-base(light/dark/grayscale),或用 Maputnik 自定义。

  • 优势:零运维、极低成本、可离线、CDN 友好。

  • 劣势:仅向量瓦片,不含卫星/地形;需配合独立的路由和搜索服务。

tileserver-gl

MapTiler · Docker 一键部署 · 瓦片

Node.js 瓦片服务器,支持 MBTiles 格式的向量瓦片 + 服务端栅格化渲染(通过 MapLibre Native),提供 XYZ/TileJSON/WMTS 标准接口。

  • Dockerdocker run -v $(pwd):/data -p 8080:80 maptiler/tileserver-gl

  • 功能:向量瓦片 + 实时栅格化(生成 PNG/JPEG 瓦片)+ 预览界面。

  • 数据源:MBTiles 文件(OpenMapTiles 生成或下载)。

  • 优势:服务端渲染 → 老旧浏览器兼容;自带 Web UI 预览。

  • 劣势:需要 MBTiles(比 PMTiles 大);全球数据处理需大内存。

tilemaker

无数据库 · 单二进制 · 生成工具

C++ 单二进制,直接从 .osm.pbf 生成向量瓦片(MBTiles/PMTiles),无需 PostgreSQL。Lua 脚本自定义图层。

  • Dockerdocker run -v $(pwd):/data ghcr.io/systemed/tilemaker:master input.osm.pbf --output output.pmtiles

  • 全球处理:需 22GB+ RAM、320GB+ 存储。区域(如中国)几 GB 内存即可。

  • 输出:MBTiles / PMTiles / 独立文件。

  • 优势:无数据库依赖;Lua 灵活自定义;许可宽松。

  • 劣势:仅生成工具,不含服务器;全球数据处理耗时长。

OpenFreeMap

全开源生产级 · 瓦片

全开源(非 open-core)的生产级瓦片服务:自动生成 + Nginx 服务 + 每周更新。可公网使用也可自部署。

  • 公共实例:tiles.openfreemap.org,免费使用,无 API key。

  • 自部署:http_host.py 组件,btrfs 镜像 + 周更同步。

  • 优势:生产就绪;真正全开源;自动更新。

  • 劣势:无路由、无搜索、无卫星、无地形;自部署需监控更新。

OpenMapTiles

标准 Schema · 生成+Schema

定义了向量瓦片的标准图层 Schema(landuse、water、transportation 等),绝大多数工具和样式都基于此 schema。

  • 工具链:Docker + Make → 从 OSM 生成 MBTiles。

  • 可用样式:OSM Bright、Positron、Dark Matter 等十余种。

  • 配合:tileserver-gl(服务)或 tilemaker(轻量生成)。

  • 优势:生态最成熟,样式和工具丰富。

  • 劣势:完整生成流程依赖 PostgreSQL;输出较大。

路线导航 (Routing Engine)

Valhalla

最全功能 · C++ · 路由 · ⭐ 推荐

功能最完整的开源路由引擎:路线规划、Turn-by-Turn 导航、距离矩阵、等时圈、地图匹配、海拔、TSP。

  • Dockerdocker run -p 8002:8002 -v $PWD/custom_files:/custom_files ghcr.io/gis-ops/docker-valhalla/valhalla:latest

  • 交通模式:汽车、自行车、步行、卡车、公共交通;支持动态 costing(限高/限重/时间偏好)。

  • API/route/optimized_route(TSP)、/sources_to_targets(矩阵)、/isochrone/trace_route(地图匹配)、/locate

  • 导航输出:Polyline 几何 + 逐步 Turn-by-Turn 指令(含距离、时间、方向)。

  • 内存:分块图结构,按需加载 → 内存效率好。区域级(如中国)数 GB 内存可运行。

  • 优势:API 最丰富(6+ 端点);多模式交通;内存效率好;社区活跃。

  • 劣势:初始 tile 构建耗时;全球数据需大磁盘。

OSRM

极速路由 · C++ · 路由

Open Source Routing Machine,以极致速度著称(欧洲级路线 ms 级返回),使用 Contraction Hierarchies 预处理。

  • Dockerdocker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/map.osm.pbfosrm-contractosrm-routed

  • API/route/table(矩阵)、/match(地图匹配)、/trip(TSP)、/nearest

  • 交通模式:汽车、自行车、步行(预处理时选定,运行时不可切换)。

  • 性能:预处理后路由查询极快(~ms 级),生产环境首选高吞吐场景。

  • 优势:最快的路由速度;生产验证充分。

  • 劣势:无等时圈;profile 预处理后固定,切换需重新构建;预处理消耗大量 RAM。

GraphHopper

Java · 跨平台 · 路由

Java 实现的路由引擎,支持多平台(含 Android 嵌入)。均衡的速度和功能集。

  • 交通模式:汽车、卡车、步行、自行车。

  • API:路由、等时圈、地图匹配、Turn-by-Turn 导航。

  • 特色:可嵌入 Android 应用做本地路由(无需服务器)。

  • 优势:跨平台;多 profile 均衡;活跃社区。

  • 劣势:Java → 内存占用偏大;某些高级功能(矩阵等)在开源版受限。

路由引擎对比

维度 Valhalla OSRM GraphHopper
语言 C++ C++ Java
路由速度 快(分块加载) 极快(预处理 CH)
交通模式 汽车/自行车/步行/卡车/公交 汽车/自行车/步行 汽车/卡车/步行/自行车
动态 Costing ✓(限高/限重/时间偏好) ✗(构建时固定) 部分
等时圈
距离矩阵 受限
TSP 优化
海拔数据
地图匹配
内存效率 好(分块 tile) 差(全图预处理)
Docker 部署 ✓ 一键 ✓ 三步
Agent 推荐度 ⭐⭐⭐ 功能最全 ⭐⭐ 速度极致 ⭐ 嵌入式场景

地理编码 (Geocoding)

Nominatim

OSM 官方 · PostgreSQL · 地理编码 · ⭐ 推荐

OpenStreetMap 官方地理编码服务,功能最全的结构化搜索 + 逆地理编码。

  • Dockerdocker run -e PBF_URL=https://download.geofabrik.de/asia/china-latest.osm.pbf -p 8080:8080 mediagis/nominatim:4.4

  • API/search(正向)、/reverse(逆向)、/lookup(OSM ID 查询)。

  • 精度:85-99.5%(配合 wrapper)。支持结构化查询、bounding box、国家代码过滤。

  • 输出:GeoJSON / JSON / XML。

  • 优势:功能最全;OSM 标准;支持高级过滤。

  • 劣势资源需求大(全球导入需数天 + 100GB+ 磁盘 + 64GB+ RAM);不适合模糊搜索。

Photon

Elasticsearch · 轻量 · 地理编码

基于 Elasticsearch 的 OSM 地理编码,专为交互式搜索优化:实时补全、容错拼写、自由文本。

  • 部署:从 Nominatim 数据导出 → 导入 Elasticsearch。预构建索引可直接下载。

  • API/api?q=(正向)、/reverse?lat=&lon=(逆向)。

  • 优势:部署快(数小时);搜即得补全;容错好。

  • 劣势:无结构化搜索;逆地理编码输出简单;依赖 Elasticsearch。

Pelias

多数据源 · 模块化 · 地理编码

模块化地理编码引擎,支持 OSM + OpenAddresses + 自定义数据源。Elasticsearch 后端。

  • 多数据源:OSM + OpenAddresses(更精确的门牌号)+ 自定义 CSV/GeoJSON。

  • 精度:~99% 街道/建筑级别(配合 OpenAddresses)。

  • API:正向 + 逆向 + 自动补全 + 结构化搜索。

  • 优势:数据源灵活;精度最高(多源融合);32GB RAM 可跑全球。

  • 劣势:组件多(Elasticsearch + 多个 importer + API server);配置复杂。

地理编码对比

维度 Nominatim Photon Pelias
数据源 OSM + Wikipedia OSM OSM + OpenAddresses + 自定义
存储后端 PostgreSQL/PostGIS Elasticsearch Elasticsearch
正向编码 ✓ 结构化+全文 ✓ 自由文本/容错 ✓ 全部
逆向编码 ✓ 详细+几何 ✓ 基础 ✓ 精确
实时补全 ✓ 优秀
容错拼写 ✓ 优秀
资源需求 高(天/周级导入) 中(小时/天级) 中(32GB 可全球)
部署复杂度 高(组件多)
Agent 推荐度 ⭐⭐⭐ 功能最全 ⭐⭐ 搜索体验最好 ⭐⭐ 精度最高

前端渲染

MapLibre GL JS

开源 Mapbox GL 分支 · WebGL · 前端 · ⭐ 推荐

Mapbox GL JS 的开源分支,WebGL 渲染向量瓦片。事实上的标准前端库,所有自部署方案都以它为客户端。

  • 渲染:WebGL 2D/3D 向量瓦片、GeoJSON、栅格、视频、3D 建筑。

  • 离线:支持 PMTiles protocol、本地 MBTiles(通过插件)、service worker 缓存。

  • 样式:Mapbox Style Spec 兼容,用 Maputnik 可视化编辑。

  • 插件:导航控件、标注、聚类、3D 地形、路线绘制。

  • 许可:BSD-3-Clause,完全免费无限制。

Leaflet

轻量经典 · 栅格优先 · 前端

经典轻量地图库(~42KB),主要面向栅格瓦片。通过插件支持向量瓦片但体验不如 MapLibre。

  • 优势:极轻量;学习曲线低;移动端友好;庞大插件生态。

  • 劣势:向量瓦片支持弱;无 WebGL 3D;性能不如 MapLibre。

一体化方案 (All-in-One Stack)

Corviont

最完整一体化 · Docker Compose · 完整栈 · ⭐ 推荐

唯一真正 all-in-one 的方案:向量瓦片(PMTiles)+ 路线导航(Valhalla)+ 离线地理编码(SQLite from Nominatim)+ MapLibre 前端,全部打在一个 Docker Compose 里

部署

1
2
3
4
git clone https://github.com/corviont/monaco-demo
cd monaco-demo
echo "CORVIONT_PORT=3000" > .env
docker compose up -d

启动后访问 http://localhost:3000

  • 组件:Nginx (反代) + PMTiles (瓦片) + Valhalla (路由) + SQLite geocoding + MapLibre 前端。

  • 目标场景:边缘设备(信息亭、船舶、离线环境)。

  • 优势:真正零外部依赖;数据一致性好(所有组件用同一 OSM 数据)。

  • 劣势:示例默认是小区域(Monaco),扩展到大区域需自己准备数据。

Headway

Google Maps 替代 · 无路由 · 部分栈

Docker Compose 连接 tileserver-gl + Pelias。定位为 Google Maps 开源替代,但不含路由功能

  • 组件:tileserver-gl (瓦片) + Pelias/Elasticsearch (搜索)。

  • 劣势:无路由导航——对 Agent 来说缺了关键组件。

资源需求与数据大小

不同区域规模的资源需求估算:

区域 OSM PBF PMTiles 瓦片 Valhalla tiles Nominatim DB 最低 RAM 磁盘总计
Monaco (测试) ~1 MB ~10 MB ~5 MB ~100 MB 2 GB ~200 MB
北京市 ~150 MB ~200 MB ~100 MB ~2 GB 4 GB ~3 GB
中国 ~1.2 GB ~2 GB ~1 GB ~20 GB 16 GB ~25 GB
亚洲 ~12 GB ~15 GB ~8 GB ~80 GB 32 GB ~120 GB
全球 (Planet) ~75 GB ~120 GB ~50 GB ~500 GB 64 GB ~750 GB

⚠️ Nominatim 是资源大户

全球 Nominatim 导入需要 500GB+ 磁盘、64GB+ RAM 和数天时间。

如果只需区域级服务(如中国),资源需求可控,大约是 20GB 磁盘和 16GB RAM。替代方案是 Photon,或者 Corviont 的 SQLite geocoding。

推荐组合方案

✅ 方案 A:Agent 极简栈(推荐起步)

适合给 Agent 提供地图 API,不需要华丽前端。组件是 Valhalla 和 Nominatim,两个 Docker 容器即可起步。

Agent 可用 API:GET /route 路线规划,GET /isochrone 等时圈,GET /sources_to_targets 距离矩阵,GET /search?q=北京大学 正向地理编码,GET /reverse?lat=39.99&lon=116.31 逆向地理编码。

中国区域大约需要 25GB 磁盘和 16GB RAM。

✅ 方案 B:完整地图栈(带可视化)

适合 Agent 和人类都要用的场景,需要有可视化地图。

组件是 Protomaps/PMTiles、Valhalla、Nominatim 和 MapLibre GL JS。部署形态是三个 Docker 容器加一个静态前端。Agent 可用方案 A 的全部 API,人类可以通过 MapLibre 看路线、POI 和等时圈。

中国区域大约需要 30GB 磁盘和 16GB RAM。

✅ 方案 C:一键全栈(快速验证)

适合快速 POC,不想自己组合多个组件。

Corviont Docker Compose 内含完整组件,三条命令能启动 demo。限制是默认小区域 Monaco,扩展到中国需要自己准备数据并修改配置。测试 2GB RAM 可用,生产资源按数据量定。

🏆 推荐方案 B 的架构流程

1
2
3
OSM PBF 数据 -> tilemaker -> PMTiles -> Nginx (瓦片服务) -> MapLibre GL JS
OSM PBF 数据 -> Valhalla (Docker) -> /route /isochrone /matrix
OSM PBF 数据 -> Nominatim (Docker) -> /search /reverse

快速部署指南

以中国区域为例,部署方案 B 的关键命令:

Step 1:下载 OSM 数据

1
2
# 从 Geofabrik 下载中国 OSM 数据
wget https://download.geofabrik.de/asia/china-latest.osm.pbf

Step 2:生成瓦片

1
2
3
# 用 tilemaker 生成 PMTiles(无需数据库)
docker run -v $(pwd):/data ghcr.io/systemed/tilemaker:master \
/data/china-latest.osm.pbf --output /data/china.pmtiles

Step 3:启动 Valhalla 路由

1
2
3
4
5
# Valhalla 自动处理 PBF → 生成路由 tiles → 启动 API
mkdir -p valhalla_data && cp china-latest.osm.pbf valhalla_data/
docker run -d --name valhalla -p 8002:8002 \
-v $(pwd)/valhalla_data:/custom_files \
ghcr.io/gis-ops/docker-valhalla/valhalla:latest

Step 4:启动 Nominatim 地理编码

1
2
3
4
5
# Nominatim 导入 PBF(首次需要较长时间)
docker run -d --name nominatim -p 8088:8080 \
-e PBF_URL=https://download.geofabrik.de/asia/china-latest.osm.pbf \
-v nominatim-data:/var/lib/postgresql/14/main \
mediagis/nominatim:4.4

Step 5:服务瓦片 + 前端

1
2
3
# Nginx 直接服务 PMTiles(配置 Range Request + CORS)
# 前端用 MapLibre GL JS + PMTiles protocol 加载
# 参考 Protomaps 文档配置样式

💡 验证 API

1
2
3
curl "http://localhost:8002/route?json={...}"
curl "http://localhost:8088/search?q=北京大学&format=json"
curl "http://localhost:8088/reverse?lat=39.99&lon=116.31&format=json"

第一条验证 Valhalla 路由,第二条验证 Nominatim 搜索,第三条验证逆向地理编码。

总结

层级 推荐方案 替代方案 核心理由
🗺️ 瓦片 Protomaps/PMTiles tileserver-gl 单文件、零运维、CDN 友好
🧭 路由 Valhalla OSRM (极速场景) API 最全、多模式交通、内存效率好
📍 编码 Nominatim Photon (轻量) / Pelias (多源) OSM 标准、功能最全
🎨 前端 MapLibre GL JS Leaflet (轻量) 事实标准、WebGL、向量瓦片
📦 一体化 Corviont 自组合 唯一真正 all-in-one Docker Compose

💡 给 Agent 用的关键结论

最小可用栈是 Valhalla + Nominatim。中国区域大约需要 25GB 磁盘和 16GB RAM,Agent 通过 HTTP API 调用路由和地理编码。

完整体验栈再加 PMTiles + MapLibre,用来可视化路线和 POI。快速验证可以先用 Corviont Docker Compose 启动 demo。所有组件都是开源组件,数据来自 OSM,不需要 API key。


本地部署地图服务全景调研:瓦片、导航与地理编码
https://jeremyguo.space/2026/04/21/selfhost-map-survey/
作者
郭俊毅 / JeremyGuo
发布于
2026年4月21日
许可协议