Docker 离线地图服务器搭建实战:Node.js + OpenLayers + MBTiles

Docker 离线地图服务器搭建实战:Node.js + OpenLayers + MBTiles

摘要:本文记录了一次从零搭建离线地图服务器的完整过程。选用 Node.js + OpenLayers + MBTiles 技术栈,利用 Docker 将服务容器化并上传至 Docker Hub。文中详细说明了瓦片数据的获取方法(如水经注下载 MBTiles)、镜像的使用步骤以及前端集成示例,帮助有离线地图需求的项目快速落地。


一、项目背景

公司内部项目需要集成离线地图功能。此前我曾成功将百度地图离线化,但版本较老,且百度 API 封闭性强,很多功能难以深度定制。于是决定自研一套离线地图服务,最终确定了以下技术组合:

  • OpenLayers:专为 Web GIS 客户端开发的 JavaScript 类库,支持标准格式的地图数据访问,灵活可扩展。
  • MBTiles:基于 SQLite 的地图瓦片存储格式,单文件便于分发和挂载。
  • Node.js:轻量服务端,提供瓦片读取和静态文件托管。

整套服务已打包为 Docker 镜像 914423503/linemap:latest,做到开箱即用。


二、准备工作

2.1 安装 Docker

请确保已安装 Docker 并配置镜像加速(如阿里云、网易等)。若未安装,可参考:

bash 复制代码
# Ubuntu 示例
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

2.2 获取 MBTiles 瓦片文件

MBTiles 是地图离线化的关键,这里推荐使用 水经注 软件进行下载。

下载步骤(以水经注为例):

bash 复制代码
下载并安装"水经注万能地图下载器"(收费软件,也可申请试用)。

选择目标区域(如北京市),设置瓦片级别(建议 1-19 级)。

导出格式选择 MBTiles,并指定输出路径。

等待下载完成,得到一个 .mbtiles 文件,例如 beijing_e_19.mbtiles。

将文件移动至宿主机的 /App/map/ 目录下,命名为 beijing_e_19.mbtiles。

注意:也可通过其他工具生成 MBTiles(如 QGIS + QTiles 插件),但水经注图形化操作更为便捷,覆盖数据源丰富。

2.3 下载前端 GIS 配置文件

我已将必需的 gis.js 和 CntenLomap.js 上传至 GitHub:

bash 复制代码
git clone https://github.com/914423503/linemap.git

将仓库中的 gis.js 和 CntenLomap.js 复制到宿主机的 /App/map/ 目录下。

修改 gis.js 中的 IP 地址为您的服务器 IP(例如 192.168.1.79):

javascript 复制代码
// gis.js 中定位到地图服务地址
var mapServer = 'http://192.168.1.79:3000';

最终宿主机目录结构大致如下:

text 复制代码
/App/map/
├── beijing_e_19.mbtiles
├── gis.js
└── CntenLomap.js

三、启动离线地图服务

3.1 拉取 Docker 镜像

bash 复制代码
docker pull 914423503/linemap:latest

3.2 运行容器

将宿主机的 /App/map 目录挂载进容器,让服务读取 MBTiles 和 JS 文件:

bash 复制代码
docker run -d -p 3000:3000 \
  -v /App/map:/map \
  -v /App/map/gis.js:/app/public/javascripts/gis.js \
  914423503/linemap:latest

参数说明:

-p 3000:3000:映射容器 3000 端口到宿主机。

-v /App/map:/map:挂载宿主机瓦片和脚本目录。

-v ...gis.js:单独挂载前端配置文件,确保使用修改后的 IP。

3.3 访问地图页面

打开浏览器,输入 http://your-ip:3000/gis,即可看到北京市的离线地图。效果如下图

​​​​​​

四、前端项目集成

在您的 Web 项目中,只需引入 OpenLayers 并指向该服务即可。以下是一个简单示例:

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <title>离线地图集成</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/css/ol.css">
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/build/ol.js"></script>
</head>
<body>
  <div id="map" style="width: 100%; height: 600px;"></div>
  <script>
    // 将 gis.js 中的配置动态引入,或直接使用以下方式
    var map = new ol.Map({
      target: 'map',
      layers: [
        new ol.layer.Tile({
          source: new ol.source.XYZ({
            url: 'http://your-ip:3000/tiles/{z}/{x}/{y}.png' // 根据实际服务路径调整
          })
        })
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([116.397428, 39.90923]),
        zoom: 12
      })
    });
  </script>
</body>
</html>

实际路径请参考 gis.js 中的瓦片地址定义,我的镜像内置了瓦片读取接口,URL 规范可参考仓库说明。

五、常见问题

Q:页面空白或无法加载瓦片?

检查挂载路径是否正确,/App/map/beijing_e_19.mbtiles 是否存在。

确认容器日志:docker logs 容器ID 查看 Node 报错。

确保 gis.js 中的 IP 地址与当前宿主机一致,且端口 3000 未被防火墙拦截。

Q:如何制作其他城市的 MBTiles?

使用水经注重新下载目标区域,或者将多个 .mbtiles 文件合并(需编写脚本)。建议一个区域一个容器实例,通过不同端口区分。

Q:能否使用免费瓦片源?

OpenStreetMap 导出工具也可生成 MBTiles,但国内访问速度较慢,水经注提供的高德、谷歌等源更符合实际项目需求。

结语

本文提供了一套轻量、可控的离线地图容器化方案,从瓦片获取到服务部署再到前端接入一应俱全。希望能帮助到同样受困于离线地图集成的朋友。如果有更好的改进思路,欢迎交流!

相关推荐
码艺-Alimjan7 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_8 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
DYWorker0019 小时前
Linux驱动:RK3568 GMAC + YT8531C 千兆以太网全流程解剖
linux
yivifu9 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
niyongsheng9 小时前
后端零改动,给若依换一套现代化前端
vue.js·开源·node.js
weixin_4482902510 小时前
书庐开发实战教学
javascript·css·html
默_笙10 小时前
🛴 从散件到整机:DeepAgents 与 Agent 身上预留的那些"插槽"(前置介绍)
前端·javascript
一木 之林10 小时前
DeepSeek Agent 开发(一)
开发语言·前端·javascript
lisanmengmeng10 小时前
NRPE 添加命令(一)
linux·运维·服务器
树下水月11 小时前
Typora破解
linux·服务器·前端