Software is hard
Software is hard

Enterprise Geospatial Solutions with QGIS and Angular

8 minutes read

It’s been more than a decade since I last worked with geospatial data such as coordinates, geofences, asset tracking, and related topics. Back in 2011–2013, I was part of a team that built a cloud-native solution for asset tracking and logistics. We had to build almost everything from scratch because there wasn’t much we could (re)use. “Cloud” as a term was fairly new, at least in Germany, and I remember managing Microsoft Azure Cloud through a “Web Interface” based on Silverlight, while simultaneously figuring out how to control “worker nodes” properly. There was no Docker, no Kubernetes, and I had no idea how to use JavaScript in the frontend. But we still managed to build a decent solution. Luckily, we had highly skilled JavaScript devs, so I and a few others on the team could focus on the backend (.NET, C#, Entity Framework, etc.).

Writing a software solution for things that move in physical space is very different from most solutions you might develop. The inherent instability and stochastic nature of the real world demands a certain way of thinking. One must always assume that data might be damaged, missing, or simply wrong. A tracking device might be sending good data one moment and then disappear for no apparent reason the next. A lot of unexpected things can happen. All in all, I learned a lot but didn’t reuse most of that knowledge in my later endeavors. This article is an attempt to revisit those experiences and combine them with powerful solutions like Kubernetes, Docker, and Angular, which I wish had been available back then.

You can find the article’s repository here.

QGIS Desktop / Server

QGIS is an open-source project and part of the Open Source Geospatial Foundation (OSGeo) ecosystem. It is a “geographic information system” (GIS) that allows us to display, edit, print, and analyze geospatial data. It supports a broad range of vector, raster, and database formats and can handle both 2D and 3D data. Many professionals worldwide rely on QGIS for tasks like mapping, geospatial analysis, and data visualization.

The data can come from various sources, such as shapefiles, vector layers, geospatial tables in databases (like PostGIS), or OpenStreetMap data. QGIS allows you to set up multiple layers of this data so that you can derive new insights from them. You can also share your own layers with other users who can consume them via their own GIS systems. Because QGIS comes in both a desktop version and a server version, you can work on your data locally in QGIS Desktop, then push the final result to the server to be consumed by external clients. For the server to be useful, you must follow certain protocols of which there are several:

  • WMS (Web Map Service) for serving georeferenced map images.
  • WMTS (Web Map Tile Service) for providing pre-rendered, cached map tiles.
  • WFS (Web Feature Service) for requesting raw geographic features (vector data).
  • OAPIF (OGC API Features) a modern REST-based evolution of WFS.
  • WCS (Web Coverage Service) for accessing raster data (coverages) representing phenomena that vary continuously in space.

In this article, we will be using WMS / WMTS, but the others can be enabled easily if needed. However, we don’t just want to push our raw geospatial data through the server. Instead, we want to serve a user interface based on Angular (plus a framework-less variant using only JavaScript) that processes that data and generates various maps. All of this should be deployed using Kubernetes or Docker Compose. The goal is to have a solution that deploys these components in one go. Their internal structures are as follows:

Docker Compose Deployment

Before we attempt to use Kubernetes to deploy the system, Docker Compose is a good option for learning what is needed for a QGIS deployment to function properly. This approach is simpler and very suitable for local testing, though it’s not as scalable as a full orchestration platform.

QGIS Server needs access to the project file we created in QGIS Desktop. In our case, the file is called world_map.qgs and can be found in the folder projects in the repository. We therefore map it to its proper volume in docker-compose.yaml as shown above. The same applies to the geospatial data our project will need to access. It must also be mapped as a volume and is located under data in the repository. One thing you’ll almost certainly encounter is that the paths in QGIS projects can be absolute or relative. In many cases, you’ll need to adapt them to the folder structure inside the QGIS Server container. If you skip this step, expect to see HTTP 500 or 404 Errors.

You can change the original paths inside the container in various ways. In this project, for example, the adaptation is done in the init container of the Kubernetes deployment, ensuring that the *.qgs file references match the internal container paths.

You can also do this manually if you prefer, as *.qgs files are just XML. The QGIS Server itself relies on NGINX to handle communication between the QGIS Viewer (the web app) and the QGIS Server Engine, which only understands protocols like WMS/WFS/WMTS. For that, we use an FCGI Wrapper.

The QGIS Viewer uses a small web server that serves static files and acts as a proxy between the web clients and the actual QGIS Server Engine on the backend.

Here as well, we configure volumes to make the simple web app available. The app includes a small amount of JavaScript to access the QGIS Server’s APIs. Inside index.html, we load OpenLayers, which handles the rendering of map data.

To run this setup with Docker Compose, go into the deployment-docker folder and execute:

docker compose up --build --remove-orphans --force-recreate -d

To check the deployment, run docker logs qgis-server. You should see output similar to this:

Awesome! Now you can open the QGIS Client at http://localhost:8081 and play with the maps.

Kubernetes Deployment

Although Docker Compose is fine for local testing and experimentation, it is not designed for massive scalability. We need a container orchestration solution like Kubernetes for that. However, I didn’t want to only deploy QGIS Server with its basic web app; I also wanted a scalable frontend solution. Because Angular is my web framework of choice, I used the latest Angular v19.2 to create a more advanced web client. (For those who don’t want to use Angular, there’s an alternative Kubernetes deployment that uses the basic web app from our Docker Compose example.)

The Angular variant can be found under the frontend-angular folder, while the simple variant is under frontend-simple. The key part of the Angular app is map.component.ts, which uses OpenLayers to create the initial map layer powered by OpenStreetMap. Here’s a snippet:

Later, map.component.ts handles the incoming tiles from QGIS Server and updates the base map accordingly.

The deployment YAML files are all located under deployment-k8s. Specifically, the server manifests are in kubernetes-k8s/qgis-server, and the viewer (both Angular and the simple one) is in kubernetes-k8s/viewer. You won’t have to manually type kubectl apply -f FILE.yaml because there are two scripts, deploy.sh and deploy.simple.sh, that handle it for you. Just run them and you should see this:

  • Start

  • Finish

You can now open the URLs shown in the console. The QGIS Server deployment is similar to the Docker Compose version, except that we use ConfigMaps to store the many configuration files. In other scenarios, you might want to rely on Persistent Volumes instead of ConfigMaps. Because I’m running Kubernetes on Docker Desktop for macOS, I ran into some volume-binding issues that I didn’t want to solve with hacks, so I opted for ConfigMaps instead. In different environments, you might prefer using PVs/PVCs.

Conclusion

Of course, a more polished solution would package everything into a proper Helm Chart. Since this project is already fairly complex, I might provide that later. In the meantime, I hope this project proves useful and maybe sparks new ideas on how to expose geospatial APIs and data to external clients in a scalable manner. QGIS, in combination with modern orchestration solutions, can be a powerful tool for a wide range of geospatial applications.

Have fun with QGIS!

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.