- Shell 75.1%
- Dockerfile 24.9%
| 文件名 | 最新提交消息 | 最新提交日期 |
|---|---|---|
| config | ||
| deploy/nginx | ||
| scripts | ||
| vendor | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
cntms
地图瓦片纠偏反向代理的部署包。以 gumblex/cntms 为运行时, 按图源类型对瓦片执行坐标纠偏与重切,输出标准 EPSG:3857,供接受 XYZ 模板地址的地图客户端使用。
本仓库为部署与配置封装,上游源码锁定于 vendor/,不含自研业务逻辑。
特性
- 坐标纠偏:将 GCJ-02 / BD-09 等偏移坐标系图源重切为标准 EPSG:3857,与以 WGS-84 存储的
坐标对齐。图源类型由
config/tmsapi.ini的type指定,可选值为xyz、tms、gcj、qq、bd/baidu、arcgis、arcgis_gcj、tianditu、shtdt、shtdt_shcors; 本仓库默认启用高德。 - 瓦片缓存:SQLite(WAL),默认有效期 7 天,并以下发
Cache-Control: max-age的形式生效。
项目结构
cntms/
├── README.md 本文档
├── Dockerfile 多阶段构建;源码取自 vendor/,依赖版本已锁定
├── docker-compose.yml 服务定义;本地目录绑定挂载缓存
├── config/
│ ├── config.ini 服务全局配置
│ └── tmsapi.ini 图源配置
├── deploy/
│ └── nginx/cntms.conf 反向代理站点配置
├── scripts/
│ ├── verify.sh 部署自检
│ └── fetch-upstream.sh 重新拉取上游源码至 vendor/
└── vendor/ 上游源码副本,版本锁定,请勿修改
├── PROVENANCE.md 来源与版本
├── LICENSE
├── tms.py
├── prcoords.py
├── demo.html
└── requirements.txt
环境要求
| 项目 | 要求 |
|---|---|
| Docker Engine | 20.10 或更高,含 Compose v2(docker compose) |
| CPU / 内存 | 1 核 512 MB 可用 |
| 磁盘 | 缓存按 cache_size 估算,20000 条约 300–350 MB |
| 网络 | 部署主机须能访问所配置图源的域名 |
| 反向代理 | 必需。客户端以 HTTPS 提供服务时,瓦片地址亦须为 HTTPS,否则浏览器将按混合内容策略拒绝加载 |
部署
# 取得代码
git clone <仓库地址> cntms
cd cntms
# 创建缓存目录并设置属主:须与镜像内服务账户一致,说明见下
mkdir -p cache
sudo chown -R 10001:10001 cache
# 构建并启动
docker compose up -d --build
docker compose ps
# 自检
bash scripts/verify.sh
容器以非 root 用户 cntms(uid/gid 10001)运行,根文件系统只读,运行期唯一可写路径是绑定挂载
的 ./cache。该账户由 Dockerfile 的 useradd --uid 10001 创建,是镜像内的固定 uid,对所有
部署者一致,与宿主机的用户体系无关;宿主机须以同一数字设置该目录属主,容器方可写入。该目录不
存在时 Docker 会以 root 身份创建,容器随即因无法写入 SQLite 缓存而反复重启,故 chown 为前提
步骤;清空缓存后亦须以同一属主重建:
docker compose down
sudo rm -rf cache && mkdir -p cache && sudo chown -R 10001:10001 cache
docker compose up -d
macOS / Windows 的 Docker Desktop 文件共享层不校验属主,该步骤可跳过;Linux 宿主机上为必需。
配置
| 文件 | 内容 |
|---|---|
config/config.ini |
监听地址与端口、缓存路径与容量、缓存有效期、可选出网代理 |
config/tmsapi.ini |
图源清单。小节名即 URL 路径段,type 决定坐标处理方式 |
两个文件均在构建时并入镜像,未挂载为卷,改动后须重建:docker compose up -d --build。
反向代理
站点配置见 deploy/nginx/cntms.conf,包含 HTTP 跳转、TLS 与请求约束
三部分。启用前将其中的 tiles.example.com 替换为实际域名,并确认证书路径:
sudo cp deploy/nginx/cntms.conf /etc/nginx/conf.d/cntms.conf
sudo nginx -t && sudo systemctl reload nginx
请求约束
上游对瓦片层级执行 2 ** zoom 的无上界整数幂运算,且该运算同步执行于其单线程事件循环。层级
过大时服务不再响应,进程亦不退出,restart 策略不会触发,须人工重启。cntms.conf 因此约束
三处:
| 载体 | 规则 | 越界响应 |
|---|---|---|
| 路径字符集 | 仅接受 ASCII 字母、数字与 - . _ / @ |
400 |
| 路径层级段 | 图层段之后至多两位数字 | 400 |
| WMTS 端点 | 其层级由查询参数提供,无法由路径规则约束;本项目仅使用 XYZ 瓦片,故关闭该端点 | 404 |
非 ASCII 数字(如阿拉伯-印度数字)可被上游的数字解析接受,故字符集规则一并排除。合法的
@2x 后缀不受影响。
对外地址
上游路由为 /<图层名>/<z>/<x>/<y>,图层名即 config/tmsapi.ini 的小节名,用于选择图源。
该段为上游所必需,不可省略,故对外地址一律包含图层名(下以 tiles.example.com 为例):
| 地址 | 说明 |
|---|---|
https://tiles.example.com/gaode-normal/{z}/{x}/{y}.png |
矢量底图 |
https://tiles.example.com/gaode-street/{z}/{x}/{y}.png |
路网加注 |
https://tiles.example.com/gaode-satellite/{z}/{x}/{y}.jpg |
卫星影像 |
https://tiles.example.com/map |
内置预览页 |
内置的 /map 与 /test 页面同样使用带图层名的地址,无需额外配置。
模板中不可包含 {s} 占位符:Leaflet 的栅格图层仅在调用方传入 subdomains 时才展开 {s},
否则会展开为 a/b/c 并请求不存在的域名。子域轮询由服务端完成,见 config/tmsapi.ini
的 s 字段。
其他事项
- 不要在 nginx 层叠加瓦片缓存。cntms 已有 SQLite 缓存并下发
Cache-Control,双层缓存会使 失效操作复杂化。 - 瓦片域名与客户端站点不同域。客户端若配置了 CSP,须将瓦片域名加入
img-src。 - nginx 与 cntms 同以容器运行时,把
127.0.0.1:6700改为cntms:6700,并移除docker-compose.yml的ports段、改用expose: ["6700"]。
运维
| 操作 | 命令 |
|---|---|
| 查看状态 | docker compose ps |
| 跟踪日志 | docker compose logs -f cntms |
改动 config/ 或 vendor/ 后生效 |
docker compose up -d --build |
| 停止并移除容器 | docker compose down |
| 自检 | bash scripts/verify.sh [公开地址] |
| 备份 | 仅需备份 config/;cache/ 为可重建的瓦片缓存 |
scripts/fetch-upstream.sh 用于重新拉取上游源码至 vendor/;升级后须同步更新 Dockerfile
中的 ARG CNTMS_COMMIT 与依赖版本。
已知限制
以下为上游 vendor/tms.py 的固有行为。本部署包不改动上游代码,仅此记录:
- 缓存写入伴随整表扫描。
DBTileCache.save()每次写入都调用expire(),后者为DELETE ... WHERE key NOT IN (SELECT ... ORDER BY updated DESC LIMIT ?),updated上无 索引;z >= 8时单次请求写入 4 条,再放大 4 倍。cache_size默认 20000、规模有界,实测 影响可接受;显著调大cache_size将抬高写入延迟。 - 深层级瓦片只缓存上游原始瓦片。
z >= 8时每个请求都重新执行 MESH 重切(CPU 开销), 其依赖的上游瓦片命中缓存,一般无需回源。 - 层级位数受限,见「反向代理」一节的请求约束;正常地图客户端的缩放层级在两位数字以内。
- 上游请求超时固定为 10 秒,固化于
vendor/tms.py,不可配置。冷请求偶发超时,重试即可。