TileServer GL for self-hosted OpenStreetMap vector tiles (OpenMapTiles). Full, light and S3 variants
543
Vector and raster map tile server with GL styles, built from a vendored and extended fork of maptiler/tileserver-gl (v5.7.0-pre.0). Serves OpenMapTiles-schema MBTiles/PMTiles, for example generated from OpenStreetMap / Geofabrik extracts with Planetiler, to MapLibre GL JS, Android/iOS, Leaflet, OpenLayers and GIS clients via WMTS.
Source, docs and dev stack: https://github.com/tgivslife/openstreetmap-tileserver-gl
All variants live in this repository; the tag suffix selects the build.
| Tag | Dockerfile | What it does |
|---|---|---|
<ver> | Dockerfile | Full build. Everything below, plus server-side rendering with MapLibre GL Native: raster tiles, static map images, WMTS, elevation queries, 3-D terrain preview. |
<ver>-light | Dockerfile_light | Vector only. Vector tiles, styles, fonts and sprites. No GL stack, much smaller image. |
<ver>-light-s3 | Dockerfile_light_s3 | The same light image with a config.json, styles and fonts baked in. A stateless container that reads PMTiles from S3-compatible object storage; retarget it with environment variables, no rebuild needed. |
Current version: 5.7.0-pre.0 → 5.7.0-pre.0, 5.7.0-pre.0-light, 5.7.0-pre.0-light-s3.
s3:// (AWS), s3+https:// / s3+http://
(MinIO, Ceph, R2, …) or plain https:// range reads. Private buckets use the standard AWS
credential chain (env vars, mounted ~/.aws profile, IAM role); credentials are never read from config.json.${VAR} / ${VAR:-default} substitution in any config.json string, so one baked config works across deployments.?key=), propagated automatically into every generated URL,
plus an optional Origin/Referer allowlist for hotlink deterrence.Cache-Control on every successful response (configurable per category)./health endpoint used by the built-in Docker HEALTHCHECK; stays open when auth is enabled.SIGHUP without restarting the container.-dark sibling.# Generate tiles first, e.g. with Planetiler:
docker run -e JAVA_TOOL_OPTIONS="-Xmx1g" -v "$(pwd)/data":/data \
ghcr.io/onthegomap/planetiler:latest --download --area=monaco
docker run --rm -it -v "$(pwd)/data":/data -p 8080:8080 \
stsdockerhub/tileserver-gl:5.7.0-pre.0-light
Open http://localhost:8080/. With no config.json in /data, the server picks up the first
*.mbtiles / *.pmtiles file it finds and, for OpenMapTiles-format data, serves the bundled styles against it.
docker run --rm -it -v "$(pwd)/data":/data -p 8080:8080 \
stsdockerhub/tileserver-gl:5.7.0-pre.0
docker run --rm -it -p 8080:8080 \
-e PMTILES_URL="s3+https://minio.example.com/tiles/planet.pmtiles" \
-e AWS_ACCESS_KEY_ID=... \
-e AWS_SECRET_ACCESS_KEY=... \
stsdockerhub/tileserver-gl:5.7.0-pre.0-light-s3
A complete MinIO example (private bucket, SigV4) is in
tileserver-gl-dev/compose.s3.yml.
Keep the container port at 8080 and remap with
-p. The built-in healthcheck always probes 8080 inside the container, so changing it with--portmakes the container report unhealthy.
-light-s3)osm-openmaptiles, streets-v2, basic-v2, each with a -dark variant and its own sprite sheet,
localized to be served entirely by this server (no external API key). Includes 28 glyph sets
(Noto Sans, Open Sans and variants).
All optional.
| Group | Variables |
|---|---|
| Server | PORT, BIND, PUBLIC_URL, NODE_ENV, UV_THREADPOOL_SIZE |
| Auth / security | TILESERVER_GL_API_KEYS, TILESERVER_GL_TOKEN_SECRET, TILESERVER_GL_TOKEN_MAX_TTL, TILESERVER_GL_ALLOWED_ORIGINS, TILESERVER_GL_ALLOWED_HOSTS |
| Metrics | TILESERVER_GL_METRICS, TILESERVER_GL_METRICS_ZOOM, METRICS_PORT |
| S3 (PMTiles) | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_REGION, AWS_PROFILE, TILESERVER_GL_S3_MAX_SOCKETS, TILESERVER_GL_S3_KEEP_ALIVE, TILESERVER_GL_S3_CONNECTION_TIMEOUT_MS, TILESERVER_GL_S3_REQUEST_TIMEOUT_MS |
Baked S3 config (-light-s3) | PMTILES_URL (tileset location), TILE_CACHE_CONTROL (tile Cache-Control) |
Full descriptions: USAGE.md › Environment variables.
| Port | Purpose |
|---|---|
8080 | HTTP: tiles, styles, fonts, sprites, TileJSON, viewers, /health |
9090 | Prometheus /metrics (when enabled; bound to 127.0.0.1 inside the container) |
Key endpoints: /styles/{id}/style.json, /data/{id}/{z}/{x}/{y}.pbf, /fonts/{fontstack}/{range}.pbf,
/styles/{id}/ (viewer). Full image only: /styles/{id}/{z}/{x}/{y}.png, /styles/{id}/static/…,
/data/{id}/elevation/…, /styles/{id}/wmts.xml.
Light image reading from MinIO over S3 (Romania tileset, z8–14, k6, 0 errors):
| Setup | Throughput | Vector-tile p95 |
|---|---|---|
| 1 container, 50 VUs | ~640 req/s | 632 ms |
| 4 replicas + LB, 200 VUs | ~1,275 req/s | 745 ms |
Containers are stateless. Scale out horizontally and put a CDN in front; the cache headers are already set for it.
docker kill -s HUP <container> # reload config.json without a restart
Install · Usage & endpoints · Configuration · Deployment
Based on TileServer GL by MapTiler and the OpenMapTiles schema. Map data © OpenStreetMap contributors (ODbL). Styles derived from MapTiler / OpenMapTiles styles. Keep the required attributions visible on any map you publish.
Content type
Image
Digest
sha256:129b9ea1b…
Size
219.9 MB
Last updated
about 2 months ago
docker pull stsdockerhub/tileserver-gl:5.7.0-pre.0