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,但国内访问速度较慢,水经注提供的高德、谷歌等源更符合实际项目需求。

结语

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

相关推荐
北暮城南1 小时前
使用 nvm 安装与管理多版本 Node.js(Windows)
windows·npm·node.js·nvm
Copy_Paste_Coder1 小时前
小程序失败后,换个方向,终于成功搞到收益
前端·javascript·后端
Harvy_没救了1 小时前
【容器技术-Docker】Docker镜像
运维·docker·容器
诸葛老刘1 小时前
在PC机上 使用docker vLLM镜像部署Qwen3-1.7B
docker·vllm
蚊子码农1 小时前
某个问题-如何配置一台最小路由器(基于linux操作系统)
linux·网络·智能路由器
Waay1 小时前
Linux Shell 知识点考评(二):sed 流编辑器(附答案)
linux·运维·服务器
Qt程序员1 小时前
从协议到实战:HTTP 反向代理
linux·c++·websocket·nginx·http·反向代理·正向代理
笨笨饿1 小时前
#85_库函数开发
linux·c语言·网络·stm32·单片机·算法·个人开发
请叫我徐先生1 小时前
seafile 在飞牛下 docker 部署重启设备后 seahub 异常无法启动的解决方案
docker·debian·seafile·飞牛·fnos