Run a free geocoder with Nominatim Docker

A step by step guide to setting up a free geocoding and reverse geocoding service using Docker.

Run a free geocoder with Nominatim Docker

The fastest way to set up a free geocoding and reverse geocoding service on your local machine is by installing Nominatim using Docker. In this tutorial, I'll walk you through the process and explain what happens at each step along the way. Once Nominatim is up and running, we'll run a quick geocoding example to check that it works.

Part 1: OpenStreetMap OSM Nominatim API tutorial
Part 2: Run a free geocoder with Nominatim Docker (this article)
Part 3: Building a free geocoding and reverse geocoding service with OpenStreetMap
Part 4: How to draw neighborhood and administrative boundaries with OSM (coming soon)

How Nominatim works

Nominatim is a geocoding and reverse geocoding software package that is commonly used to convert addresses into geographic coordinates (latitude and longitude) and vice versa.

You can think of Nominatim as a specialized search engine for OpenStreetMap (OSM) data. OSM organizes data as a graph, with places (e.g. a specific building address) as nodes connected by roads to other places. Each place is annotated with tags describing its name, address, coordinates, function etc.

Nominatim works by extracting place data from OpenStreetMap turning it into a free geocoder
Nominatim works by extracting place data from OpenStreetMap

Nominatim unwraps this graph and stores it in database tables where it can be efficiently queried. For example, each place then becomes a row entry in the places table, with columns for name, address, coordinates etc. Relationships between places are encoded as references to different rows.

So let's say you want to geocode (convert an address name to a latitude, longitude pair) the address, "999 Canada Place". The address string can be found in the name column of the places table which is specifically designed to handle free text search efficiently. This means that when an address is inserted into the database, a separate lookup table that maps words or phrases to the row entries they occur in is also updated, which allows for fast searching based on address names or phrases. Nominatim uses Postgres, but the principles I've described here apply to any relational database.

Install Docker and spin up Nominatim

To run Nominatim, we are going to use Docker, a program that packages software into standardized units called containers that have everything the software needs to run including libraries, system tools, code, and runtime.

Download Docker Desktop and start it so that it runs in the background. Next, in the preferences section, make sure that you configure docker to run with enough memory and disk space because we'll be extracting map data from OSM and using it to populate several database tables, and this consumes disk storage. Set disk image size to at least 8 GB and memory to 20 GB.

Docker memory and disk space configuration for Nominatim Docker set up and install
Docker memory and disk space configuration for Nominatim Docker set up and install

Finally, run the command:

docker run -it \
  -e PBF_URL=http://download.geofabrik.de/north-america/canada/british-columbia-latest.osm.pbf \
  -e REPLICATION_URL=https://download.geofabrik.de/north-america/canada/british-columbia-updates/ \
  -p 8080:8080 \
  --name nominatim \
  mediagis/nominatim:4.3

This sets up a Nominatim container instance (pulled from the mediagis/nominatim v4.3 repository) using OSM data for British Columbia, Canada, allowing you to access a geocoding service via HTTP on port 8080 of your host machine. Additionally, it configures the container to receive incremental updates (via the REPLICATION_URL) to stay synchronized with changes in OSM data.

Nominatim docker progress bar
Nominatim docker progress bar

Once you hit enter, you'll see a progress bar that shows you how much time the download has left.

Extracting map data to Postgres

Once the download is complete, the install script unpacks the OSM map data and saves it into Postgres using the osm2pgsql utility.

osm2pgsql extracts the OSM map data and saves it into Postgres
osm2pgsql extracts the OSM map data and saves it into Postgres

When this is done, you'll get a message saying, "Nominatim is ready to accept requests".

Nominatim Docker is installed and ready to accept API requests
Nominatim Docker is installed and ready to accept API requests

Testing our free geocoder

The final step involves verifying the functionality of the Nominatim API through a basic geocoding example. Assuming you've followed all the previous instructions, our free geocoding service should now be operational at http://localhost:8080. To test it, please open a new browser tab and navigate to the following address: http://localhost:8080/search?q=canada+place.

The Nominatim API free geocoding service returning a query result
The Nominatim API returning a query result

You should get back the following response:

[
    {
        "place_id": 579864,
        "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
        "osm_type": "way",
        "osm_id": 706831744,
        "boundingbox": [
            "49.2877544",
            "49.2881403",
            "-123.115517",
            "-123.114108"
        ],
        "lat": "49.287991",
        "lon": "-123.1149786",
        "display_name": "Canada Place, Gastown, Downtown, Vancouver, Metro Vancouver Regional District, V6C, Canada",
        "place_rank": 26,
        "category": "highway",
        "type": "tertiary",
        "importance": 0.30000999999999994
    },
    // ... removed similar entries
    {
        "place_id": 579858,
        "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
        "osm_type": "node",
        "osm_id": 7515805468,
        "boundingbox": [
            "49.2879188",
            "49.2880188",
            "-123.1147061",
            "-123.1146061"
        ],
        "lat": "49.2879688",
        "lon": "-123.1146561",
        "display_name": "Canada Place, West Waterfront Road, Gastown, Downtown, Vancouver, Metro Vancouver Regional District, V6C, Canada",
        "place_rank": 30,
        "category": "highway",
        "type": "bus_stop",
        "importance": 0.20000999999999997
    }
]

which is an array of all the places that correspond to the search term "Canada Place" (Vancouver's downtown cruise terminal). The lat and lon fields represent the geocoded coordinates of each place.

Now that we've gotten our free geocoder working locally, the next step is to use the Nominatim API to build a free geocoding and reverse geocoding service.

👋 As always, if you have any questions or suggestions for me, please reach out or say hello on LinkedIn.

Next: Part 3: Building a free geocoding and reverse geocoding service with OpenStreetMap