This Docker container provides Apache Jena Fuseki with built-in GeoSPARQL support, enabling spatial queries on RDF data. It includes:
- Apache Jena Fuseki 5.4.0 - A robust SPARQL server and query engine
- GeoSPARQL Extension - Support for spatial data queries and geometric operations
- Full-text Search - Lucene-based text indexing for enhanced search capabilities
- TDB Storage - High-performance triple store with union default graph
- Security - Apache Shiro authentication with configurable admin access
- 🌍 Spatial Queries: GeoSPARQL 1.0 support for geometric and topological operations
- �️ Coordinate Systems: Apache SIS tools for downloading EPSG datasets
- �🔍 Text Search: Integrated Lucene indexing for SKOS labels and RDF literals
- 📊 High Performance: TDB storage with optimized configurations
- 🔐 Secure: Built-in authentication with configurable admin password
- 🐳 Docker Ready: Production-ready container with proper security settings
- 📡 REST API: Complete SPARQL endpoint with read/write capabilities
- 🔄 Data Loading: Pre-configured tools for efficient data import
More information about the GeoSPARQL implementation of Apache Jena Fuseki can be found in the official documentation.
Note: This container includes Apache SIS command line tools to enable download of EPSG datasets. The SIS_DATA environment variable is configured to a directory inside /fuseki-base (recommended to mount as a docker volume).
Note 2: The GeoSPARQL extension of Apache Jena Fuseki 5.4.0 currently does not support geof:distance with a metric unit from a source EPSG that is not metric. You still need to use the vendor function spatialF:distance for this. Please see the example queries.
A docker image is available on Docker Hub.
# Run with default settings (port 3030)
docker run -p 3030:3030 mathiasvda/apache-jena-fuseki-geosparql
# Run with persistent data storage
docker run -p 3030:3030 -v /path/to/data:/fuseki-base mathiasvda/apache-jena-fuseki-geosparqlOnce running, you can access:
- Fuseki Web UI: http://localhost:3030
version: "3.8"
services:
fuseki-geosparql:
image: mathiasvda/apache-jena-fuseki-geosparql:latest
ports:
- "3030:3030"
volumes:
- fuseki_data:/fuseki-base
restart: unless-stopped
volumes:
fuseki_data:You can load RDF data into the container using several methods:
You can access the Fuseki Web UI at http://localhost:3030 to upload your RDF data files directly.
# Mount your data directory and use tdbloader
docker run -v /path/to/your/data:/data -v fuseki_data:/fuseki-base \
mathiasvda/apache-jena-fuseki-geosparql \
bash -c 'eval $TDBLOADER /data/*.ttl && java -cp "*:/javalibs/*" org.apache.jena.fuseki.main.cmds.FusekiServerCmd'# Upload a file via HTTP
curl -X POST -H "Content-Type: text/turtle" \
--data-binary @your-data.ttl \
http://localhost:3030/ds/data# Insert triples via SPARQL UPDATE (requires ENABLE_UPDATE=true)
curl -X POST -H "Content-Type: application/sparql-update" \
--data "INSERT DATA { <http://example.org/subject> <http://example.org/predicate> <http://example.org/object> }" \
http://localhost:3030/ds/updateExample spatial queries you can run:
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX uom: <http://www.opengis.net/def/uom/OGC/1.0/>
# Test basic GeoSPARQL geometry functions without UOM
SELECT ?test_name ?point ?buffer_geom ?envelope_geom WHERE {
VALUES (?test_name ?lat ?lon ?buffer_distance) {
("Amsterdam Central" 52.3791 4.9003 0.01)
("Rotterdam Port" 51.9225 4.4792 0.02)
("Utrecht Center" 52.0907 5.1214 0.015)
}
# Create point geometry from coordinates
BIND(STRDT(CONCAT("<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(", STR(?lon), " ", STR(?lat), ")"), geo:wktLiteral) AS ?point)
# Create a buffer around the point (simple circular buffer)
BIND(geof:buffer(?point, ?buffer_distance, uom:degree) AS ?buffer_geom)
# Get the envelope (bounding box) of the buffered geometry
BIND(geof:envelope(?buffer_geom) AS ?envelope_geom)
}
ORDER BY ?test_namePREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
# Test GeoSPARQL spatial relationships without UOM namespace
# This query tests contains, intersects, and within relationships
SELECT ?relation ?geometry1_label ?geometry2_label ?result WHERE {
# Define test geometries
VALUES (?geometry1_label ?geometry1 ?geometry2_label ?geometry2 ?relation) {
# Point within polygon test
("City Center" "POINT(4.9041 52.3676)"^^geo:wktLiteral "Amsterdam Bounds" "POLYGON((4.8 52.3, 5.0 52.3, 5.0 52.4, 4.8 52.4, 4.8 52.3))"^^geo:wktLiteral "within")
# Line intersects polygon test
("Highway" "LINESTRING(4.85 52.32, 4.95 52.38)"^^geo:wktLiteral "Amsterdam Bounds" "POLYGON((4.8 52.3, 5.0 52.3, 5.0 52.4, 4.8 52.4, 4.8 52.3))"^^geo:wktLiteral "intersects")
# Polygon contains point test
("Large Area" "POLYGON((4.7 52.2, 5.1 52.2, 5.1 52.5, 4.7 52.5, 4.7 52.2))"^^geo:wktLiteral "Small Point" "POINT(4.9 52.35)"^^geo:wktLiteral "contains")
# Buffer test (point with buffer intersects line)
("Station" "POINT(4.9 52.37)"^^geo:wktLiteral "Train Line" "LINESTRING(4.88 52.36, 4.92 52.38)"^^geo:wktLiteral "intersects")
}
# Test the spatial relationship based on the relation type
BIND(
IF(?relation = "within", geof:sfWithin(?geometry1, ?geometry2),
IF(?relation = "intersects", geof:sfIntersects(?geometry1, ?geometry2),
IF(?relation = "contains", geof:sfContains(?geometry1, ?geometry2),
false))) AS ?result
)
}
ORDER BY ?relation ?geometry1_labelPREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX uom: <http://www.opengis.net/def/uom/OGC/1.0/>
PREFIX spatialf: <http://jena.apache.org/function/spatial#>
# Test GeoSPARQL distance calculation between two cities
SELECT ?city1 ?city2 ?distance_km WHERE {
VALUES (?city1 ?point1 ?city2 ?point2) {
("London" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(-0.1276 51.5074)"^^geo:wktLiteral "Paris" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(2.3522 48.8566)"^^geo:wktLiteral)
("New York" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(-74.0060 40.7128)"^^geo:wktLiteral "Boston" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(-71.0588 42.3601)"^^geo:wktLiteral)
("Amsterdam" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(4.9041 52.3676)"^^geo:wktLiteral "Brussels" "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT(4.3517 50.8503)"^^geo:wktLiteral)
}
# Calculate distance in kilometers
# implementation of geof:distance in v5.4 does not support coordinate transformation to uom:metre for non-metric EPSG, so we use spatialf:distance
BIND(spatialf:distance(?point1, ?point2, uom:metre) / 1000 AS ?distance_km)
}
ORDER BY ?distance_km# Clone the repository
git clone https://github.com/matdata-eu/apache-jena-fuseki-geosparql.git
cd apache-jena-fuseki-geosparql
# Build the Docker image
docker build -t apache-jena-fuseki-geosparql .
# Run your custom build
docker run -p 3030:3030 apache-jena-fuseki-geosparqlor use the provided docker-compose.yml file:
docker-compose up --buildThe container uses several configuration files in the config/ directory:
assembler.ttl- Dataset and service configurationfuseki-config.ttl- Server-wide settings and timeoutsshiro.ini- Security and authentication configurationdocker-entrypoint.sh- Container initialization script
The container includes Apache SIS EPSG datasets for coordinate reference system support:
- SIS_DATA Path:
/fuseki-base/SIS_DATA - EPSG Database: Provides access to thousands of coordinate reference systems
- Automatic Detection: SIS automatically detects and uses the EPSG database for transformations
You can override these by mounting your own configuration files:
docker run -p 3030:3030 \
-v ./my-assembler.ttl:/fuseki-base/configuration/assembler.ttl \
mathiasvda/apache-jena-fuseki-geosparql- Permission Denied: Ensure your data volumes have proper permissions (the container runs as user 9008)
- Memory Issues: Increase Docker memory allocation for large datasets
- Connection Refused: Check that you're using the correct port (3030, not 8080)
# View container logs
docker logs <container-name>
# Follow logs in real-time
docker logs -f <container-name># Check if Fuseki is responding
curl -f http://localhost:3030/$/pingContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.