Servir du WMS caché avec MapProxy - partie 1#
Date de publication initiale : 16 avril 2026
Dans certains contextes qu'il est possible de rencontrer, des utilisateurs de QGIS peuvent être amenés à consommer du WMS et des tuiles, avec des enjeux et défis de connectivité et performances, compte-tenu du fait que les serveurs sont parfois distants des utilisateurs finaux. Aussi, la bande passante des réseaux dans lesquels les postes QGIS demandent des flux n'est pas toujours garantie, alors il faut parfois se creuser la tête pour rendre un usage fluide de ces flux, dans notre logiciel SIG Desktop préféré.
MapProxy : quèsaco ?#
Une brique existe pour cela, MapProxy : opensource, léger et svelte, écrit en Python et qui porte plutôt bien son nom : un proxy de cartes, qui va servir à mettre en cache des flux générés par d'autres serveurs cartographiques. L'avantage est déjà que MapProxy possède, à l'instar d'autres serveurs géographiques la possibilité de mettre en cache les tuiles servies, et ce de différentes manières : fichiers classiques, mbtiles, geopackage, redis, s3... Aussi, MapProxy permet comme son nom l'indique de servir de proxy, c'est-à-dire de relai de flux entre un serveur carto et d'autres clients, qui peuvent être par ex. QGIS, du WebGIS, d'autres serveurs carto...
La configuration est basée sur des fichiers YAML, ce qui peut faciliter des automatisations et des déploiements d'instances iso.
À noter qu'Arnaud en parlait déjà en 2010, au travers de cet article qui explique comment installer un serveur local, avec environnement virtuel Python.
Cas d'usage de MapProxy#
Le site de MapProxy présente un premier cas d'usage, où un serveur MapProxy cache et sert à des clients finaux des flux générés par plusieurs autres serveurs :
On note déjà que les flux en entrée du MapProxy peuvent être du WMS ou de la tuile (par exemple les couches XYZ dans QGIS), fournies par exemple par MapServer, GeoServer, QGIS Server...
Les clients qui consomment ce WMS en provenance du MapProxy peuvent être des clients Desktop comme QGIS, ou des librairies web style OpenLayers, MapLibre, Leaflet, ou encore des app mobiles comme QField / Mergin Maps, ou bien même d'autres serveurs cartographiques ! C'est la beauté des protocoles.
Un autre cas d'usage pourrait être le suivant :
-
des clients éparpillés et/ou à l'autre bout du monde, avec des latences très lentes en visant un unique serveur cartographique.
-
un super serveur cartographique, quelque part, qui calcule et sert tout le nécessaire, par exemple QGIS server. Nous n'avons pas envie de répliquer et manipuler plusieurs instances de QGIS server ayant vocation à servir strictement les mêmes flux, alors nous allons préférer instancier différentes instances de MapProxy.
-
des instances de MapProxy plus proches des clients, permettant ainsi de cacher et fournir les flux aux clients de manière plus fluide et performante.
La logique pourrait se traduire par le schéma suivant :
graph TD
subgraph Col1[ ]
direction TB
ClientZ11[👩 Alicia<br>sur QGIS]
ClientZ12[👨 Boby<br>sur MapLibre]
end
subgraph Col2[ ]
direction LR
mapproxyZ1[🤖 MapProxy zone 1]
end
subgraph Col3[ ]
direction TB
ServeurCentral[💾 Serveur Central]
end
ClientZ11 --> |1: ✉️ Demande le flux| mapproxyZ1
mapproxyZ1 ---> D1{2: 🌀 Ressource<br>en cache ?}
D1 --> |✅ Oui<br>📦 Retourne la ressource| ClientZ11
D1 --> |❌ Non| R1Z1[3: ✉️ Demande la ressource]
R1Z1 --> ServeurCentral
ServeurCentral --> |4: 👷 Calcule la ressource| ServeurCentral
ServeurCentral --> |5: 📦 Retourne la ressource| mapproxyZ1
mapproxyZ1 --> |6: 🌀 Met en cache<br>la ressource| mapproxyZ1
mapproxyZ1 --> |7: 📦 Retourne la ressource| ClientZ11 Mise en route avec un exemple#
Afin d'illustrer et mettre en route une stack avec MapProxy au centre, entre un serveur carto et un client, faisons un petit exemple en mettant en cache des données sur le 19e arrondissement de Paris. En bout de chaîne, notre MapProxy va donc servir des couches WMS pour cette zone, pour laquelle nous auront besoin de la bounding box.
Concernant les sources "centrales", étant donné qu'on n'a pas vraiment de serveur carto qui tourne avec des "vraies" données, on va utiliser les tuiles d'OpenStreetMap, du WMS de la Géoplateforme ainsi que des tuiles d'imagerie satellite de Google et Bing.
Warning
Ici on est dans un tuto à but pédagogique, si vous souhaitez utiliser et mettre en cache ces sources de données en production, et/ou pour des usages commerciaux, allez d'abord lire attentivement les conditions générales d'utilisation de ces datasources.
Pour rappel, il est déjà possible d'ajouter ces couches à QGIS, en ajoutant par exemple une nouvelle source XYZ, ou bien via une connexion WMS :
- OpenStreetMap:
https://tile.openstreetmap.org/{z}/{x}/{y}.png, qui propose d'ailleurs un guide pour configurer MapProxy avec OSM. - Géoplateforme: on va utiliser la couche
BU.buildingdu service WMS-Vecteur. Ce service est limité à 50 requêtes par seconde. - Googly Hybrid:
https://mt.google.com/vt/lyrs=y&hl=en&x={x}&y={y}&z={z} - Bing Aerial:
http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g=1- ici on n'utilise pas dex/y/zmais un paramètreq, pour quadkey. Rien à voir avec un véhicule de kéké des forêts, c'est plutôt une manière d'indexer spatialement des tuiles carrées. Plus d'infos ici.
Info
À noter que lors de la création d'une connexion de type XYZ, le bas de l'interface montre des niveaux de zoom min et max à demander (respectivement 0 et 19). Gardez ces valeurs en tête, nous pourrions les ressortir plus tard lorsque nous jouerons à cache-cache
Installation de MapProxy sur un serveur debian / ubuntu#
Entrons maintenant dans le vif du sujet, et la partie geek : l'installation de MapProxy sur une machine linux. Ici on se limitera aux distributions basées sur debian et ubuntu.
Une fois n'est pas coutume - j'ai plutôt l'habitude de déployer des MapProxy avec systemd, étant donné qu'on va utiliser docker pour lancer l'applicatif, il est déjà nécessaire d'installer cet outil en suivant la doc officielle.
Une fois docker installé, attardons-nous sur le léger fichier docker-compose.yaml pour lancer le service :
services:
mapproxy:
image: kartoza/mapproxy:6.0.1
restart: unless-stopped
environment:
- PRODUCTION=true
- PROCESSES=4
- CHEAPER=2
- THREADS=10
- MULTI_MAPPROXY=false
- ALLOW_LISTING=true
- LOGGING=true
volumes:
- ./config:/mapproxy
- ./cache:/cache_data
ports:
- 8765:8080
- On redirige vers le port 8765 en sortie, qu'on configurera dans nginx, notre serveur agissant comme reverse-proxy devant notre map proxy
...
- On désactive le mode
MULTI_MAPPROXYpour ce tuto. - Les deux entrées dans la partie
volumesreprésentent les dossiers locaux montés dans le container :- Il doit y avoir un répertoire
configlà où vous vous trouvez (où créez-le viamkdir -p config). Ce répertoire contiendra notamment la configuration et la déclaration des couches servies par le MapProxy. - Il doit y avoir un répertoire
cachelà où vous vous trouvez (où créez-le viamkdir -p cache). Ce répertoire accueillera les tuiles cachées, étant donné qu'ici on va rester sur du cache simple de type file. Notez qu'il est possible d'enregistrer les tuiles cachées dans du geopackage, dans des mbtiles, dans du redis, dans du s3, et d'autres trucs comme nous le savons, à nous l'savon !
- Il doit y avoir un répertoire
Une fois ce docker-compose.yaml créé de même que les deux dossiers nécessaires, jettons un coup d'oeil au fichier de configuration (unique) de MapProxy !
Configuration du MapProxy#
Il s'agit donc d'un fichier unique mapproxy.yaml, qui doit se trouver dans votre dossier config là où vous vous trouvez.
Abordons le contenu d'un tel fichier de conf, pour un seul layer - OpenStreetMap caché sur Paris 19.
Il y a plusieurs sections :
- la partie services qui déclare du WMS uniquement ici (WMTS, TMS possibles etc.)
- un layer pointe vers un cache, qui lui-même se réfère à une source et une grid.
- ici on délimite la source avec une bbox, qui représente l'emprise du 19e arrondissement de Paris. Plusieurs types de coverages sont disponibles.
Ce qui donne un fichier mapproxy.yaml qui ressemble à ça :
Voyons maintenant comment configurer les différentes sources de données qu'on définissait plus haut.
- Source OpenStreetMap :
paris19_osm_source:
type: tile
url: https://tile.openstreetmap.org/%(z)s/%(x)s/%(y)s.png
grid: osm_grid
coverage:
bbox:
- 2.3646858891194782
- 48.8720621793437502
- 2.4108388540828618
- 48.9021619064262865
srs: EPSG:4326
Source WMS-Vecteur Géoplateforme :
paris19_bu_building_source:
type: wms
req:
url: https://data.geopf.fr/wms-v/ows
layers: BU.Building
transparent: true
grid: osm_grid
coverage:
bbox:
- 2.3646858891194782
- 48.8720621793437502
- 2.4108388540828618
- 48.9021619064262865
srs: EPSG:4326
wms_opts:
legendurl: https://data.geopf.fr/wms-v/ows?service=WMS&version=1.3.0&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=BU.Building
image:
transparent_color: "#ffffff"
transparent_color_tolerance: 0
Source Imagerie Google Hybrid :
paris19_googlehybrid_source:
type: tile
url: https://mt.google.com/vt/lyrs=y&hl=en&x=%(x)s&y=%(y)s&z=%(z)s
grid: osm_grid
coverage:
bbox:
- 2.3646858891194782
- 48.8720621793437502
- 2.4108388540828618
- 48.9021619064262865
srs: EPSG:4326
Source Imagerie Bing Aerial :
paris19_bing_aerial_source:
type: tile
url: https://ecn.t3.tiles.virtualearth.net/tiles/a%(quadkey)s.jpeg?g=1
grid: osm_grid
coverage:
bbox:
- 2.3646858891194782
- 48.8720621793437502
- 2.4108388540828618
- 48.9021619064262865
srs: EPSG:4326
Les caches et layers sont sensiblement les mêmes, adaptés pour pointer sur la bonne source.
Configuration du serveur web nginx#
Maintenant, configurons notre serveur web nginx, qui va directement recevoir les requêtes en provenance des clients avant de les dispatcher à l'instance MapProxy.
Pour cela créer un nouveau "site", dans /etc/nginx/sites-available/ :
upstream mapproxy_upstream {
server 127.0.0.1:8765;
}
server {
listen 80;
server_name mapproxy.geotribu.xyz;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mapproxy.geotribu.xyz;
ssl_certificate /etc/letsencrypt/live/mapproxy.geotribu.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mapproxy.geotribu.xyz/privkey.pem;
error_log /var/log/nginx/mapproxy.error.log;
access_log /var/log/nginx/mapproxy.access.log combined;
location /mapproxy {
proxy_pass http://mapproxy_upstream;
proxy_set_header Host $http_host;
proxy_set_header X-Script-Name /mapproxy;
}
}
Créer ensuite un lien symbolique vers /etc/nginx/sites-enabled/ :
Récupérer ensuite des certificats Let's Encrypt, soit en éteignant nginx avec systemctl stop nginx puis sudo certbot certonly --standalone -d mapproxy.geotribu.xyz, soit avec le plugin nginx pour certbot via sudo certbot certonly --nginx -d mapproxy.geotribu.xyz.
Retourner maintenant à l'emplacement où vous avez mis le docker-compose.yaml ainsi que le dossier de config de MapProxy. Démarrer l'instance via docker compose up -d.
Regarder les logs avec docker compose logs -f -n 200, si tout est ok, on a maintenant un MapProxy fonctionnel !
Auteur·ice#
Guilhem ALLAMAN#
Je suis ingénieur informaticien. J'aime les ordinateurs. Mais ce que j'aime par-dessus tout (oh oui !), c'est itérer, et ce de manière agile, transverse et langoureuse, de bon matin, dès l'aube, à l'heure où blanchit le dashboard du sprint backlog.
Basé à Paris, j'ai commencé par le développement Java avant de découvrir les joies des SIG et de m'y spécialiser. Mon parcours m'a amené à travailler un certain temps dans les télécommunications au sens large, et avec des boîtes comme Oslandia, une filiale de Canal+ Afrique et OPENGIS.ch avec qui j'évolue désormais.
Je participe à Geotribu depuis début 2024, et mes contributions ici n'engagent que moi, me, myself and I.
Licence #
Ce contenu est sous licence Creative Commons International 4.0 BY-NC-SA, avec attribution et partage dans les mêmes conditions, sauf dans le cadre d'une utilisation commerciale.
Les médias d'illustration sont potentiellement soumis à d'autres conditions d'utilisation.
Réutiliser, citer l'article
Vous êtes autorisé(e) à :
- Partager : copier, distribuer et communiquer le matériel par tous moyens et sous tous formats
- Adapter : remixer, transformer et créer à partir du matériel pour toute utilisation, exceptée commerciale.
Citer cet article :
"Servir du WMS caché avec MapProxy - partie 1" publié par Guilhem ALLAMAN sur Geotribu PREVIEW - PR 1399 sous CC BY-NC-SA - Source : https://preview-pullrequest-1399--geotribu-preprod.netlify.app/articles/2026/2026-04-16_cacher_wms_avec_mapproxy_1/
Commentaires
Une version minimale de la syntaxe markdown est acceptée pour la mise en forme des commentaires.
Propulsé par Isso.
Ce contenu est sous licence Beerware


