PostGIS ======= .. raw:: html `PostGIS `_ is a very popular open source extension for PostgreSQL that introduces support for storing GIS (Geographic Information Systems) objects in the database and be queried via SQL. .. Note Important]:: This section assumes you are familiar with PostGIS and provides some basic information about how to create a new PostgreSQL cluster with a PostGIS database in Kubernetes via CloudNativePG. Supported Installation Methods ------------------------------ Depending on your environment (PostgreSQL version, Kubernetes version, and CloudNativePG version), you have two primary ways to provision PostGIS: 1. :ref:`**Image Volume Extensions** <#method-1-image-volume-extensions>` : Mounts extension binaries directly from OCI images as read-only volumes (recommended for PG 18+ and Kubernetes 1.35+). 2. :ref:`**PostGIS Operand Images** ` : Uses a pre-built PostgreSQL image that already contains PostGIS libraries. Once PostGIS is provisioned on the system using one of the methods below, you must still enable and manage it inside the database (see the :ref:`Enabling the Extension ` section below). Method 1: Image Volume Extensions --------------------------------- Starting with **PostgreSQL 18** and **Kubernetes 1.35** (1.33 and 1.34 with the ``ImageVolume`` feature gate enabled), you can leverage :ref:`Image Catalog with Image Volume Extensions ` . This is the modern way to manage extensions, as it allows you to use an official minimal PostgreSQL image and “plug in” PostGIS at runtime, by mounting the content of the extension’s OCI image directly into the Postgres container as a read-only volume. This decouples the extension lifecycle from the base PostgreSQL image, keeping your operand images slim and secure. The CloudNativePG Community distributes standalone extension container images for PostGIS via the `postgres-extensions-containers `_ repository. Via an image catalog (for CloudNativePG 1.29+) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Starting from CloudNativePG 1.29 you can take advantage of :ref:`image catalogs with image volume extensions ` to automate the management of these versions. Refer to the :ref:`image volume extensions page ` for instructions on how to add an extension to a PostgreSQL cluster, making sure you use the ``postgis`` key: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgis spec: # ... imageCatalogRef: apiGroup: postgresql.cnpg.io kind: ClusterImageCatalog name: postgresql-minimal-trixie major: 18 postgresql: extensions: # ... - name: postgis # ... Directly in the ``Cluster`` resource ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following illustrative example shows how to add PostGIS 3.6.2 to a PostgreSQL 18 cluster, by loading the extension directly in the ``Cluster`` resource: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgis spec: imageName: ghcr.io/cloudnative-pg/postgresql:18.3-minimal-trixie instances: 1 storage: size: 1Gi postgresql: extensions: - name: postgis image: reference: ghcr.io/cloudnative-pg/postgis-extension:3.6.2-18-trixie ld_library_path: - system .. Note:: Refer to the `postgres-extensions-containers `_ project for the latest versions and instructions for this extension. Method 2: PostGIS Operand Images -------------------------------- For users who prefer to keep using the dedicated ``postgis-containers`` registry, or for those on older versions of PostgreSQL or Kubernetes that do not support image volume extensions, the community continues to maintain images with PostGIS pre-installed (built on top of the `PostgreSQL Container images `_ ). For more information, please visit: - The `postgis-containers `_ - The `postgis-containers `_ To use this method, point the ``.spec.imageName`` to the desired PostGIS-enabled image: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgis spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgis:18.3-3.6.2-system-trixie storage: size: 1Gi Enabling the Extension ---------------------- Once the binaries are provisioned (via either method above), you must enable the extension in the database. Using the ``Database`` resource allows for declarative management of the extension’s lifecycle, including version upgrades. .. Note:: For more details, see the :ref:`Managing Extensions in a Database ` . .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Database metadata: name: cluster-postgis-app spec: name: app owner: app cluster: name: cluster-postgis extensions: - name: postgis version: 3.6.2 - name: postgis_raster - name: postgis_sfcgal - name: fuzzystrmatch - name: address_standardizer - name: address_standardizer_data_us - name: postgis_tiger_geocoder - name: postgis_topology .. Tip:: Specifying the `version` in the `extensions` stanza is highly recommended. CloudNativePG will compare this version with the one currently installed in the database; if they differ, it will automatically execute the necessary `ALTER EXTENSION ... UPDATE TO ...` command. Verification ------------ You can easily verify the available version of PostGIS that is in the container, by connecting to the ``app`` database and querying the PostgreSQL catalog. For example: .. code:: bash kubectl cnpg psql cluster-postgis -- app -c \ "SELECT * FROM pg_available_extensions WHERE name ~ ^postgis ORDER BY 1" Returning something similar to this (you might obtain different values from the ones in this document): .. code:: console name | default_version | installed_version | comment - -------------------------+-----------------+-------------------+------------------------------------------------------------ postgis | 3.6.2 | 3.6.2 | PostGIS geometry and geography spatial types and functions postgis-3 | 3.6.2 | | PostGIS geometry and geography spatial types and functions postgis_raster | 3.6.2 | 3.6.2 | PostGIS raster types and functions postgis_raster-3 | 3.6.2 | | PostGIS raster types and functions postgis_sfcgal | 3.6.2 | 3.6.2 | PostGIS SFCGAL functions postgis_sfcgal-3 | 3.6.2 | | PostGIS SFCGAL functions postgis_tiger_geocoder | 3.6.2 | 3.6.2 | PostGIS tiger geocoder and reverse geocoder postgis_tiger_geocoder-3 | 3.6.2 | | PostGIS tiger geocoder and reverse geocoder postgis_topology | 3.6.2 | 3.6.2 | PostGIS topology spatial types and functions postgis_topology-3 | 3.6.2 | | PostGIS topology spatial types and functions (10 rows) The next step is to verify that the extensions listed in the ``Database`` resource have been correctly installed in the ``app`` database: .. code:: bash kubectl cnpg psql cluster-postgis -- app -c \dx The command returns something like this: .. code:: console List of installed extensions Name | Version | Default version | Schema | Description - -----------------------------+---------+-----------------+------------+------------------------------------------------ address_standardizer | 3.6.2 | 3.6.2 | public | Used to parse an address into constituent ... address_standardizer_data_us | 3.6.2 | 3.6.2 | public | Address Standardizer US dataset example fuzzystrmatch | 1.2 | 1.2 | public | determine similarities and distance between... plpgsql | 1.0 | 1.0 | pg_catalog | PL/pgSQL procedural language postgis | 3.6.2 | 3.6.2 | public | PostGIS geometry and geography spatial type... postgis_raster | 3.6.2 | 3.6.2 | public | PostGIS raster types and functions postgis_sfcgal | 3.6.2 | 3.6.2 | public | PostGIS SFCGAL functions postgis_tiger_geocoder | 3.6.2 | 3.6.2 | tiger | PostGIS tiger geocoder and reverse geocoder postgis_topology | 3.6.2 | 3.6.2 | topology | PostGIS topology spatial types and functions (9 rows) Finally: .. code:: bash kubectl cnpg psql cluster-postgis -- app -c SELECT postgis_full_version() Returning: .. code:: console postgis_full_version - ----------------------------------------------------------------------------------------------------------------------- POSTGIS="3.6.2 08d9b9f" [EXTENSION] PGSQL="180" GEOS="3.13.1-CAPI-1.19.2" SFCGAL="SFCGAL 2.0.0, CGAL 6.0, BOOST 1.83.0" PROJ="9.6.0 NETWORK_ENABLED=OFF URL_ENDPOINT= USER_WRITABLE_DIRECTORY=/tmp/proj" (compiled against PROJ 9.6.0) GDAL="GDAL 3.10.3, released 2025/04/01 GDAL_DATA not found" LIBXML="2.9.14" LIBJSON="0.18" LIBPROTOBUF="1.5.1" WAGYU="0.5.0 (Internal)" TOPOLOGY RASTER (1 row)