PostGIS
PostgreSQL
Docker
Database Extension
How-To Guide

How to create postgis extension for postgresql in docker?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Creating the PostGIS extension inside PostgreSQL running in Docker is straightforward when you start from a PostGIS-enabled image and initialize the extension in the target database. Problems usually happen when developers use plain PostgreSQL images, run CREATE EXTENSION in the wrong database, or assume init scripts rerun on existing volumes.

This article outlines a reliable Docker workflow for PostGIS with reproducible setup, initialization scripts, and verification steps for local and CI environments.

Core Sections

1. Use an image that includes PostGIS binaries

bash
1docker run -d \
2  --name postgis-db \
3  -e POSTGRES_USER=myuser \
4  -e POSTGRES_PASSWORD=mypassword \
5  -e POSTGRES_DB=geodata \
6  -p 5432:5432 \
7  postgis/postgis:16-3.4

Using postgres:16 alone is not enough unless PostGIS packages are installed manually.

2. Enable extension in target database

bash
docker exec -it postgis-db psql -U myuser -d geodata -c "CREATE EXTENSION IF NOT EXISTS postgis;"
docker exec -it postgis-db psql -U myuser -d geodata -c "SELECT PostGIS_Version();"

Run in the same database your application connects to.

3. Automate setup with init scripts

sql
-- init-scripts/01-postgis.sql
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;

Mount this directory to /docker-entrypoint-initdb.d.

yaml
1services:
2  db:
3    image: postgis/postgis:16-3.4
4    volumes:
5      - ./init-scripts:/docker-entrypoint-initdb.d

4. Understand volume behavior

Init scripts run only on first database initialization. If volume already exists, scripts are skipped.

bash
docker compose down -v
# then docker compose up -d to reinitialize from scripts

Do not expect script changes to apply automatically on existing data volumes.

5. Verify geometry support in schema

sql
1CREATE TABLE places (
2  id SERIAL PRIMARY KEY,
3  name TEXT NOT NULL,
4  geom GEOMETRY(Point, 4326)
5);
6
7CREATE INDEX idx_places_geom ON places USING GIST (geom);

If this succeeds, PostGIS extension is active and usable.

6. Build custom image for extra extensions

dockerfile
FROM postgis/postgis:16-3.4
COPY init-scripts/ /docker-entrypoint-initdb.d/

This pattern keeps CI and dev environments consistent.

Common Pitfalls

  • Starting from plain PostgreSQL image and expecting PostGIS functions to exist.
  • Running CREATE EXTENSION in the wrong database (for example postgres instead of app DB).
  • Forgetting that init scripts do not rerun on existing persistent volumes.
  • Skipping version pinning for PostgreSQL/PostGIS image tags.
  • Not validating extension status before running spatial migrations.

Summary

To create PostGIS in Docker reliably, use a PostGIS-enabled image, enable extension in the correct database, and automate setup through init scripts for first-run initialization. Account for persistent volume behavior and verify functionality with PostGIS_Version() plus sample geometry tables. With pinned versions and scripted setup, spatial database environments remain reproducible and low-friction.

For teams maintaining how to create postgis extension for postgresql in docker in long-lived codebases, reliability improves when implementation guidance is paired with a lightweight verification routine. A practical pattern is to define three test categories up front. First, happy-path tests that validate normal expected inputs. Second, boundary tests that include empty values, minimum and maximum limits, and malformed records from real logs. Third, operational tests that simulate production-like behavior under retries, parallel execution, and partial failure. This combination catches both obvious logic defects and the subtle integration issues that usually appear after deployment.

It is also useful to encode assumptions close to the code rather than leaving them in scattered documentation. Add short comments where invariants matter, keep helper utilities centralized, and avoid repeating slightly different logic in multiple modules. In CI, run a small deterministic suite on every commit and a broader dataset suite on schedule. When incidents occur, convert the failing scenario into a permanent regression test before patching. Over time this creates a strong feedback loop where how to create postgis extension for postgresql in docker behavior remains stable even as dependencies, framework versions, and team ownership change. The result is less firefighting and faster review cycles.


Course illustration
Course illustration

All Rights Reserved.