Skip to content

Instantly share code, notes, and snippets.

@miccferr
Last active December 7, 2017 15:51
Show Gist options
  • Save miccferr/8f6698be06069575eca0333c0c9eec91 to your computer and use it in GitHub Desktop.
Save miccferr/8f6698be06069575eca0333c0c9eec91 to your computer and use it in GitHub Desktop.

Document Scope:

Provide a practical and easy-to-follow tutorial on how to set-up TileServerGL for:

  • [A] Providing background maps
  • [B] Providing Data as vector tiles to be consumed client-side via MapboxGLJs

What is TileServerGL:

TileServerGL is a vector and raster tile server developed by KoklanTechnologies, capable of "server side rendering by Mapbox GL Native. Map tile server for Mapbox GL JS, Android, iOS, Leaflet, OpenLayers, GIS via WMTS, etc."

Problem statement:

While the installation is fairly straightforward (just install docker + run docker run --rm -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl and docker will automatically download the container+test dataset and start it ), the actual customisation proves a bit more tricky due to patchy documentation and banal yet annoying issues such as relative paths, docker volume mounting etc...

In particular, the customisation requires at least:

  • config.json specifying the likes of data sources (both for styling and data provision), fonts, stylying file.
  • style.json such as the famous BrightOSM styling file, Positron etc... NOTE: such files holds a further reference to the data source corresponding data source (in mapboxGLJs every styling is formalised in a json style file decoupled from the actual raw data)

The problem resides in the relative paths


Testing

Let me exemplify:

  1. In the config.json one can specify
  • The relative paths in paths object
"paths": {
      "root": "",
      "fonts": "fonts",
      "sprites": "sprites",
      "styles": "styles",
      "mbtiles": ""
    },

According to the docs

paths defines where to look for the different types of input data. The value of root is used as prefix for all data types.

  • The path to the styling file should then added in the styles option
"styles": {
    "basic": {
      "style": "basic.json",
      "tilejson": {
        "type": "overlay",
        "bounds": [8.44806, 47.32023, 8.62537, 47.43468]
      }
    },
  • Similarly, the data path can be then added in the data option:
"data": {
    "zurich-vector": {
      "mbtiles": "zurich.mbtiles"
    }
  }
  1. Further, in the styling file (e.g. styles/positron-gl-style/style.json), there's a further necessity to explicitly point to the data, fonts and sprite files:
 "sources": {
    "openmaptiles": {
      "type": "vector",
      "url": "mbtiles://data/italy.mbtiles"
    }
  },
  "sprite": "https://openmaptiles.github.io/positron-gl-style/sprite",
  "glyphs": "fonts",
  1. Lastly, the preceding paths should be integrated with docker's volumes when launching the dockerised tileserver instance.

Such command can be for instance the following:

 docker run -it -v $(pwd)/data:/data  -v $(pwd)/styles:/styles -v $(pwd)/fonts:/fonts -p 3001:80 klokantech/tileserver-gl -c config.json --verbose

which in theory should mount local folders to their respective counterparts in the container. The above is assuming the follwing directory structure:

➜  tileserver-gl l
total 24M
drwxr-xr-x  5 root root 4.0K Dec  6 21:39 .
drwxr-xr-x 14 root root 4.0K Dec  6 13:58 ..
-rw-r--r--  1 root root  504 Dec  6 21:40 config.json
drwxr-xr-x  2 root root 4.0K Dec  6 15:26 data
drwxr-xr-x  3 root root 4.0K Dec  6 21:42 fonts
drwxr-xr-x  4 root root 4.0K Dec  6 16:13 styles

The question is thus how to integrate al these moving bits and pieces?

So far in fact TileServer starts, but with varying results:

  • Sometimes it picks up the correct style location , but then crashes when accessing the styled data from the splash page

this is the error log:

ERROR: Font not found: Metropolis Light Italic
ERROR: Font not found: Metropolis Light Italic
/usr/src/app/src/serve_rendered.js:161
            var range = parts[3].split('.')[0];
                                ^

TypeError: Cannot read property 'split' of undefined
    at request (/usr/src/app/src/serve_rendered.js:161:33)
    at Object.request (/usr/src/app/node_modules/@mapbox/mapbox-gl-native/platform/node/index.js:21:13)

Even more weirdly, pointing the browser directly to the stylised map works (i.e. to something like http://YOUR-URL:YOUR-PORT/styles/positron/#7/44.194/12.107)

While this can just be an app bug, it is fairly annoying.

  • A worse problem is due to the misalignment between the folder locations on the host filesystem, and those in teh containers. If for some (yet to be understood) reason Tileserver doesn't pick up the correct styleing location, it produces an on-the-fly config, which styles the data using two default styles residing in the container path.

This is the output log:

Waiting 3 seconds for xvfb to start...
Starting tileserver-gl v2.3.0
No MBTiles specified, using italy.mbtiles
Automatically creating config file for italy.mbtiles
{
  "options": {
    "paths": {
      "root": "/usr/src/app/node_modules/tileserver-gl-styles",
      "fonts": "fonts",
      "styles": "styles",
      "mbtiles": "/data"
    }

 },
  "styles": {
    "klokantech-basic": {
      "style": "klokantech-basic/style.json",
      "tilejson": {
        "bounds": [
          6.5272658,
          35.1889616,
          18.8844746,
          47.1921462
        ]
      }
    },
    "osm-bright": {
      "style": "osm-bright/style.json",
      "tilejson": {
        "bounds": [
          6.5272658,
          35.1889616,
          18.8844746,
          47.1921462
        ]
      }
    }
  },
  "data": {
    "v3": {
      "mbtiles": "italy.mbtiles"
    }
  }
}
Starting server
Listening at http://[::]:80/
Startup complete

this is the command:

sudo docker run -it -v $(pwd)/data:/data  -v $(pwd)/styles:/styles -v $(pwd)/fonts:/fonts -p 3001:80 klokantech/tileserver-gl -c config.json --verbose

NOTE there's now a different mapping regading the data location flag in Docker:

BEFORE NOW
-v $(pwd):/data -v $(pwd)/data:/data

This is the splash page (NOTE again the two different default styles, now available)

While in this configuration the app runs smoothly it - doens't pick up the correct style (although it recognizes the data location!) - doesn't return any other data apart from the one specfified for styling purposes. NOTE this is a crucial problem when trying to serve data no merely for styling (such as the case of background maps) but for data analysis (or any other purpose really).

Conclusion:

Given the mismatch between the paths, the goal is thus to produce a functioning configuration, able to pick up all the components (style, data, fonts...) from the local folder to allow a truly customisable instance of tileserver.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment