Setting Up MapProxy with Docker and Serving Cached Tiles via Nginx
MapProxy is a powerful open-source proxy for geospatial data that allows for efficient caching and serving of map tiles. Combining MapProxy with Docker and Nginx can provide a scalable and easily manageable solution for serving cached map tiles. This guide will walk you through the process of setting up MapProxy using Docker and configuring Nginx to serve cached tiles.
Prerequisites:
- Docker installed on your system
- Basic understanding of Docker
- Basic understanding of Nginx
If you don't meet this prerequisites yet I recommend to have a look at the following guides first:
Step 1: Set Up MapProxy with Docker
Start by creating a Network in Docker with:
sudo docker create network nginx
By adding the network nginx to the Nginx Container and the Mapproxy container the containers can communicate with each other without exposing ports on the server.
Create a Docker Compose file docker-compose.yml
with the following content:
networks: default: external: true name: nginx services: mapproxy: image: kartoza/mapproxy container_name: mapproxy restart: always environment: PRODUCTION: true PROCESSES: 4 CHEAPER: 2 THREADS: 8 MULTI_MAPPROXY: true MULTI_MAPPROXY_DATA_DIR: /multi_mapproxy/configurations ALLOW_LISTING: true volumes: - /data/containers/mapproxy/data:/multi_mapproxy
Save the file and run:
docker-compose up -d
This will pull the MapProxy Docker image and start a container. MapProxy will be accessible on the container with http://localhost:8080
.
Step 2: Set Up Nginx with Docker
Afterwards you need to create a Docker Compose file docker-compose.yml
for Nginx. Here's a example:
version: '3' networks: default: external: true name: nginx services: nginx: image: nginx:latest container_name: nginx restart: always ports: - "80:80" - "443:443" volumes: ## Config - /data/containers/nginx/config/:/etc/nginx/ ## SSL - /etc/letsencrypt/:/etc/letsencrypt/ - /etc/ssl/:/etc/ssl/ ## Logs - /data/containers/nginx/logs/:/var/log/nginx ## Cache - /data/containers/nginx/cache:/var/cache/nginx
Then you can create a virtual host for mapproxy under /data/containers/nginx/config/sites-available/mapproxy
with:
sudo nano /data/containers/nginx/config/sites-available/mapproxy
Copy and paste the following virtual host configuration for your Mapproxy Container :
upstream mapproxy_upstream { server mapproxy:8080; } server { server_name mapproxy.domain.com; listen 80; ## Mapproxy default location / { proxy_pass http://mapproxy_upstream/; proxy_set_header Host $http_host; } }
After you created your configuration you need to create a symlink to /data/containers/nginx/config/sites-enabled/
with:
sudo ln -S /data/containers/nginx/config/sites-available/mapproxy /data/containers/nginx/config/sites-enabled/
In order that your domain gets resolved you have to create a A-record for your Domain under which you want to publish MapProxy which points to your server ip. Then you need to restart your Nginx Container and now should be able to access http://mapproxy.domain.com where you will be greeted by your MapProxy Instance.
Step 3: Caching the Tiles with MapProxy
So far you have set up Nginx and MapProxy with Docker and MapProxy will cache by default all served tiles with the default configuration. However there are some limitations to the MapProxy caching process because each time a tile gets requested from MapProxy, MapProxy will save the tile to it's cache. But it won't check by default if the tile is old and a newer tile could be served.
E.g. I am serving tiles from MapProxy which visualize my locations where I have ever been to. So I don't want to cache the tiles infinite because they change probably every day
But you can force MapProxy to refresh tiles from the source while serving if they are found to be expired. The validity conditions are the same as for seeding:
#Explanation # absolute as ISO time refresh_before: time: 2010-10-21T12:35:00 # relative from the time of the tile request refresh_before: weeks: 1 days: 7 hours: 4 minutes: 15 # modification time of a given file refresh_before: mtime: path/to/file
So to stay at my example i added:
refresh_before: days 1
This way MapProxy will refresh tiles everyday. This of course only makes sense for data where you want always latest data
So edit your mapproxy.yaml
like this:
services: demo: tms: use_grid_names: true # origin for /tiles service origin: 'nw' kml: use_grid_names: true wmts: wms: md: title: MapProxy WMS Proxy abstract: This is a minimal MapProxy example. layers: - name: osm title: Omniscale OSM WMS - osm.omniscale.net sources: [osm_cache] caches: osm_cache grids: [webmercator] sources: [osm_wms] refresh_before: days: 1 sources: osm_wms: type: wms req: url: https://maps.omniscale.net/v2/demo/style.default/service? layers: osm grids: webmercator: base: GLOBAL_WEBMERCATOR globals:
Save the file and restart your MapProxy Container.
Now MapProxy will always refresh tiles everyday.
Step 4: Access the MapProxy Tiles
Visit http://mapproxy.domain.com
in your browser, and you should see MapProxy serving tiles through Nginx.
By following these steps, you've successfully set up MapProxy with Docker and configured Nginx to serve cached map tiles. This scalable solution allows for efficient geospatial data delivery with the added benefit of easy container management. Adjust the configurations based on your specific requirements and integrate this setup into your mapping projects.
If you decide to to take use of MultiMapProxy(scroll down to MultiMapProxy) you can just create more configuration files for MapProxy in /data/containers/mapproxy/data/configurations
and append the cache path and location blocks like in your existing Nginx configuration for MapProxy.
First published January 28, 2024
Have you published a response to this? Send me a webmention by letting me know the URL.
Found no Webmentions yet. Be the first!
About The Author
Geospatial Developer
Hi, I'm Max (he/him). I am a geospatial developer, author and cyclist from Rosenheim, Germany. Support me