0

I'm super new to postgres extensions and docker, and I have some questions regarding how to set them up on a postgres container running on Docker. I have to create a table which will need the geometry type provided by postgis. I have a docker-compose file:

version: '3.8'
services:
  test-db:
    image: postgres
    restart: always
    ports:
      - '5434:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: testdb
    volumes:
      - ./database/postgres:/data

My Dockerfile looks like this currently:

# Development Build
FROM node:12.18.3-alpine3.12 as builder
LABEL maintainer="person <person@person.com>"

RUN apk update && apk add --no-cache make git

WORKDIR /usr/src/app

ARG NPM_TOKEN

COPY package*.json ./
RUN true
COPY package-lock.json ./
RUN true
COPY .npmrc /root/.npmrc

RUN npm i && rm /root/.npmrc && npm run postinstall; exit 0

COPY . .

RUN npm run build:all

I also tried following this tutorial but when ran into errors on step 5.

I also tried following the second answer from this Stackoverflow question. But when I tried to run docker pull kartoza/postgis:image_version, I got an error Error response from daemon: manifest for kartoza/postgis:image_version not found: manifest unknown: manifest unknown.

If i install postgis and define it on dockerfile and docker compose and someone else runs my code, will they also need to download postgis?

Kaisin Li
  • 514
  • 3
  • 7
  • 21
  • There is an [official postgis image](https://registry.hub.docker.com/r/postgis/postgis/). Using that would be the simplest solution. – larsks Jun 23 '23 at 21:55

1 Answers1

0

Here's my recommendation.

For just PostgreSQL with Postgis

Assuming you are on Linux or Mac, create a directory called gis using mkdir gis and go into the directory by doing cd gis.

Create a file called Dockerfile.pg.

from postgres
run apt-get update
run apt-get upgrade -y
run apt-get install postgis -y

Create a file called gis.sh that contains:

#!/bin/bash

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    create extension postgis;
EOSQL

Create a file called docker-compose.yml

version: '3.8'
services:
  gis:
    build:
      context: .
      dockerfile: Dockerfile.pg
    container_name: gis
    image: gis
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: test
      POSTGRES_DB: postgres
    volumes:
      - pg:/var/lib/postgresql/data
      - ./gis.sh:/docker-entrypoint-initdb.d/gis.sh
volumes:
  pg:

Then, do docker compose up -d.

That'll use your Dockerfile.pg to:

  • build the postgres image and call it gis
  • run apt-get update
  • run apt-get upgrade -y
  • run apt-get install postgis

It'll create a container and call it gis

It'll mount a named volume called pg so you can identify the volume easily.

It'll run gis.sh, which will create an extension called postgis after logging into PostgreSQL.

When you do docker image ls, you will see a gis image.

When you do docker container ls, it'll show you the running container name.

You can log on to the container usingi docker exec -it gis /bin/bash and you'll see

% docker exec -it gis /bin/bash
root@d3bdba37a76b:/# 

You can verify that the extension has been added by doing:

root@d3bdba37a76b:/# psql postgres postgres
psql (15.3 (Debian 15.3-1.pgdg120+1))
Type "help" for help.

postgres=# SELECT oid, extname, extversion FROM pg_extension;
  oid  | extname | extversion
-------+---------+------------
 13561 | plpgsql | 1.0
 16384 | postgis | 3.3.3
(2 rows)

postgres=# exit

Once you are done using the container, you can bring remove the container using docker compose down -v. The -v will remove the volume as well.


Hint about your app, if you want to run it along with PostgreSQL

While I don't know how your app works, you might want to try something like this to bring up your database and app. Tweak as you deem fit.

In the gis directory, you now have 3 files:

  • Dockerfile.pg
  • gis.sh
  • docker-compose.yml

Add another file called Dockerfile - that's your app's Dockerfile.

FROM node:12.18.3-alpine3.12 as builder
RUN apk update && apk add --no-cache make git
WORKDIR /usr/src/app
ARG NPM_TOKEN
COPY package*.json ./
RUN true
COPY package-lock.json ./
RUN true
COPY .npmrc /root/.npmrc
RUN npm i && rm /root/.npmrc && npm run postinstall; exit 0
COPY . .
RUN npm run build:all

Change the docker-compose.yml to:

version: '3.8'
services:
  gis:
    build:
      context: .
      dockerfile: Dockerfile.pg
    image: gis
    container_name: gis
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: test
      POSTGRES_DB: postgres
    volumes:
      - pg:/var/lib/postgresql/data
      - ./gis.sh:/docker-entrypoint-initdb.d/gis.sh
    ports:
      - "5434:5432"

  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: nodeapp
    container_name: nodeapp
    depends_on:
      - gis
    ports:
      - "4000:4000"

volumes:
  pg:

Then you can run docker compose up -d and see the output.

Here's a blog that could also help you: https://michalzalecki.com/docker-compose-for-nodejs-and-postgresql/

zedfoxus
  • 35,121
  • 5
  • 64
  • 63
  • Thanks for the detailed response! already have a database container configured in docker-compose.ymal in the root layer of my app. do i need to somehow specify the order of running both compose files? When then i ran docker compose up, it never stops running – Kaisin Li Jun 24 '23 at 02:20
  • You’ll have one docker-compose.yml file and 2 Dockerfiles. The dockerfiles will have info about how to build an image with your app and postgis. The single compose file will have 2 sections. The order of sections within the compose file won’t matter as long as you use depends_on. – zedfoxus Jun 24 '23 at 15:31