Setting Up MapProxy with Docker and Serving Cached Tiles via Nginx

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:

  1. Docker installed on your system
  2. Basic understanding of Docker
  3. 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.ymlfor 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.

Screenshot_2024_01_25_154515_63e86fb113.png

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

  1. 0 Webmentions

    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

    Max
    Max

    Geospatial Developer

    Hi, I'm Max (he/him). I am a geospatial developer, author and cyclist from Rosenheim, Germany. Support me

    0 Virtual Thanks Sent.

    Continue Reading