一、引言
近期在实验性质的做自己的一个地图项目,由于很多关于OSM部署的文章过于远古,以及一些内容不是很详细,并且随着OSM的内容变更,一些文章的时效性也有了问题,期间遇到了无数的坑,因此写文记录下来。
需要注意的是,由于OSM地图的国界存在很大问题,且在国内没有审图号等资质,因此不建议公开使用。
本文主要是用的是生成mbtiles文件,直接启动瓦片服务的方式。至于为什么不用postgis+geoserver...一开始本文确实尝试过将osm数据导入postgis,然后通过geoserver渲染。但是在最后渲染矢量瓦片的时候遇到了麻烦,对于全球数据这样的大数据量,如果用png或者jpg瓦片,geoserver应该是个好选择,但是矢量瓦片,对于低缩放等级需要控制数据规模,为了瓦片体积考虑,最好不需要渲染的图层就不添加到这个层级的数据里,但是geoserver实现起来困难重重,加上切片本身也要大量的时间,按照预期,如果渲染0-14级瓦片出来的话,需要的存储瓦片的空间大概要超过500g,因此最终放弃了数据库方案,转而投向了可操作性更强的轻量化方案。
本文写于2024.5.22。目前的技术选型分别是:
| 类型 | 工具 | 版本 | 官方链接 |
|---|---|---|---|
| 地图 | OpenStreetMap | 2024-02-28 | www.openstreetmap.org/ |
| 地图处理工具 | Arcgis Pro | -- | --- |
| 地图处理工具 | QGis | 3.34.6 | github.com/qgis/QGIS |
| 生成切片数据工具 | tilemaker | 2024-04-28 | github.com/systemed/ti… |
| 瓦片服务器 | tileserver-gl | 4.11.0 | github.com/maptiler/ti… |
| 前端地图库 | maptalks | 1.0.0.rc-33 | github.com/maptalks/ma… |
| 前端地图库 | maplibre-gl | 9.1.0 | github.com/maplibre/ma… |
机器配置参考(实际所需远低于本机配置就行,只是速度问题,内存不够可以用硬盘空间弥补,但是一定得是ssd,机械硬盘除非是raid,不然不适合干这个活):
| 配置 | 参数 | 备注 |
|---|---|---|
| CPU | E5 2666V3 | --- |
| 内存 | 64G | --- |
| 硬盘空间 | SSD 2T | 如果需要导入全球数据,最好有个1T以上的剩余空间,生成的数据文件大概在100g以上 |
| 显卡 | 4060 | 其实用不着 |
| 操作系统 | Ubuntu 20.04 | 主要是用docker,windows开虚拟机也不是不行,就是效率堪忧 |
这里给出一个调色完成后的最终效果图参考,如果觉得对您有帮助,还望点个赞支持一下。

二、数据准备
一开始要做的自然是把工具环境都准备齐了,不过我们可以一步一步来。首先准备地图数据。
1.下载OSM镜像
对于全球数据,这边推荐OSM星球,下载pbf的格式数据,目前总大小是75g左右。
如果你只想要某个地区或国家的数据,比如,亚洲,中国,美国等,则可以通过Geofabrik下载想要的地区的pbf数据文件。
当然,以上网站的访问可能需要一些科学上网。
2.海岸线数据、植被覆盖数据和海洋深度数据
如果你想让最终的地图能够像mapbox或者google map那样,有丰富的细节信息,使地图较为美观,那你需要额外下载这部分数据。数据来源都是自然地球数据网站。当然,文末的网盘会一并提供此数据。
3.国界线及十段线
如果有需要标注我国南海边界以及我国对藏南地区等边界的归属,此处提供一个根据审图号2019地图做了国界修正的数据,但是请注意,这个数据本身没有通过审图,且由于参考的审图地图的国界精度有限,必定与真实国界存在出入,因此请酌情使用,本人不对此数据负责。
三、安装docker以及打包镜像
1.安装docker
对于ubuntu来说 其实安装docker挺简单的,如果不需要最新版本的docker,可以切换到root用户,直接执行:
apt-get install docker.io
执行完就安装结束了,如果需要最新版本的docker,请自行百度安装,这边不多介绍了。 对于windows用户,这边不建议使用wsl,win11的wsl下 我安装的docker总会在打包镜像的时候卡死,所以很无奈,请尝试vmware之类的虚拟机方案吧,或者尝试用docker desktop。
2.打包tilemaker和tileserver-gl的docker镜像
打包镜像其实也很简单,在某个目录下执行git clone去下载最新的git代码,然后cd到目录内执行打包即可,大致如下:
//克隆分支
git clone https://github.com/systemed/tilemaker.git
//进入文件夹
cd tilemaker
//打包镜像
docker build . -t tilemaker
2024.11.20补充:由于国内镜像不通畅等问题,如果打包镜像卡在包含如下内容的输出docker.io/library/debian:bookworm-slim,比如timeout之类的情况,请科学上网后,提前拉取镜像。
即执行docker pull debian:bookworm-slim,之后再执行build命令打包即可。
对于tileserver-gl也是一样的打包方式。
//克隆分支
git clone https://github.com/maptiler/tileserver-gl.git
//进入文件夹
cd tileserver-gl
//打包镜像
docker build . -t tileserver-gl
tileserver-gl内置了basic-preview样式,并可以用maplibre加载看看效果。如果你想要自己进行配色,则后续可以使用maputnik/editor工具去进行配色。因为这里不是本文的重点,因此不再详细阐述。
至此,顺利的话,我们就得到了两个主要工具的镜像,如果你不想用docker,也可以在release里查看是否有提供发行版,可能会有二进制可执行文件。不过由于切片数据的时间很长,而docker可以后台执行,所以我更青睐docker。
四、切片数据
1.配置文件
在开始切片前,我们还得编辑一些tilemaker数据配置。
在项目的resources目录下有几个标准配置文件,即config-openmaptiles.json和process-openmaptiles.lua。如果只需要默认样式,可以直接指定此文件为配置文件。但是,如果需要一些额外的图层,比如海洋深度、植被覆盖等就需要自己作出一些修改。
配置图层是无序的,所以随自己喜好排列都行,如果某个图层你只想让他在某几个缩放层级的瓦片中出现,那就可以通过minzoom和maxzoom去调整,source则是指定数据来源,可以是shp格式 也可以是geojson,对于shp格式,有要求文件坐标系必须是WGS84也就是EPSG:4326,所以如果不是,请通过arcgis,qgis之类的软件自行转换下。
图层还提供了一些简化多边形的选项和配置,请参考工具文档。不过简化对于部分切片数据会出现一些渲染问题,这个需要自行取舍。举个例子,渲染water-polygons.shp的时候,在广州附近的3级瓦片就可能出现一个小三角,虽然这个不是数据本身的问题,疑似和maplibre使用的切分三角形的库有关,但是解决方式却可以通过处理瓦片解决,把有问题的地点附近的要素用arcgis之类的工具合并即可。
另外,海洋深度图层以及冰盖等来自自然地球的shp文件数据本身进行了分块处理,如下例图。

为了避免简化多边形属性造成切片后的分块之间出现间隙,这里建议将多边形合并,消除缝隙。当然你也可以直接用我网盘里处理好的shp文件。
此外,如果你看得懂同名的lua脚本在做什么,也可以自行修改内容,扩展查询内容和合并图层等。
2.切片数据
在准备完数据和修改完配置文件后,就可以进行数据切片了。虽然说是切片,但其实是工具把瓦片需要渲染的数据存到了一个sqlite数据库文件里,格式为mbtiles,需要的时候,直接去读区对应层级zxy的瓦片数据,不需要执行复杂的查询,所以很快。
我们把需要用到的文件,丢进同一个目录下,之后我们会通过docker的-v去映射工作目录。 最后,我们修改config.json里,按照docker映射的虚拟目录,修改需要使用的shp文件对应的路径,我这边是把工作目录映射成了docker内的/srv目录。
常规的生成切片文件的命令如下:
docker run -d -v /工作目录/:/srv -i -t --rm tilemaker /srv/workspace/planet-240226.osm.pbf --store /srv/tmp --output=/srv/out/planet.mbtiles --config /srv/workspace/config.json
如果你的内存较“小”(128g以下),则可以使用硬盘空间去缓存数据,但是必须是ssd,机械硬盘的读写太慢可能会起反效果。可以添加例如我使用的--store /srv/tmp的参数去指定一个目录作为存储缓存文件的目录,如果你对内存大小比较自信,可以把这个参数删掉。
全球数据全部解压出来,大约是接近600g。而生成的mbtiles文件大约100g以上,加上原始的pbf文件本身也有75g,所以,最好留出1T空间去跑这个操作。总时间消耗视服务器配置而论,保守估计大约12-18小时左右,各位可以对比我的服务器配置做个参考。
特别注明:
如果你用了默认的样式,那么可以直接无视这个注明。如果你使用了自定义的shp文件,或者调整了简化参数,那么最好下载一个澳大利亚的pbf文件,进行切片测试,经查验,太平洋的岛国这里很容易出现多边形有拉丝的情况,这个问题在低缩放等级(0-4)很容易出现,高等级一般问题不大,所以,请酌情处理。
3.瓦片部署
在生成mbtiles之后,离成功基本只差最后一步了,接下来要进行的就是瓦片部署和样式处理。
这边先说一下瓦片部署吧,样式涉及的东西不少,放到下期。
部署本身其实可以在本机安装tileserver-gl,也可以用docker,我懒得写服务,再加上为了稳定起见,还是选择了用docker去运行。
启动指令如下:
docker run -d --restart=always -it -v /工作目录/:/srv -p 9527:8080 tileserver-gl --file /srv/out/planet.mbtiles
在这里我对端口做了个映射,把tileserver-gl的服务端口映射到了宿主机的9527端口,这里可以自由指定,毕竟默认的8080很容易和其他应用冲突。
最后,我们浏览器访问http://localhost:9527 直接访问地图服务,可以看到如图的服务器界面。

其中STYLES里有一个配置好了的默认携带的样式,点击Viewer按钮,可以通过maplibre库预览默认的配色效果,而下边的data,则是数据源,点击Inspect可以看到右侧图例,是我们划分的图层,而页面上,会分色显示出所有数据,方便我们后续配图。

最后,我们点击DATA中services的TileJSON链接,打开一个json配置文件。

我用红框括起来的tiles参数,就是您可以直接在maptalks、leaflet、maplibre等地图库中使用的瓦片地址了。我这里因为是在一台ubuntu实体机部署的地图服务,所以ip是一个内网地址,对你来说,域名应该是localhost或者127.0.0.1。
如果需要从外网访问,则可以通过nginx做个域名代理,或者用frp之类的内网穿透工具。
五、总结
本文通过配合docker,使用了tilemaker和tileserver-gl两个开源项目实现了osm全球数据的矢量瓦片渲染。当然这只是一部分,下篇文档,我会继续介绍如何使用maptalks库和maplibre库加载矢量瓦片以及仿照mapbox现有的样式修改渲染效果。
这里是文中提及的部分数据的网盘地址:百度网盘,提取密码是9527。