Search code examples
dockerdocker-composedocker-volume

Docker volume associated to postgres image empty and not persistent


I have a docker-compose file to build a web server with django and a postgres database. It basically looks like that :

version: '3'

services:
  server:
    build:
      context: .
      dockerfile: ./docker/server/Dockerfile
    image: backend
    volumes:
      - ./api:/app
    ports:
      - 8000:8000
    depends_on:
      - postgres
      - redis
    environment:
      - PYTHONUNBUFFERED=1

  postgres:
    image: kartoza/postgis:11.0-2.5
    volumes:
      - pg_data:/var/lib/postgresql/data:rw
    environment:
      POSTGRES_DB: "gis,backend"
      POSTGRES_PORT: "5432"
      POSTGRES_USER: "user"
      POSTGRES_PASS: "pass"
      POSTGRES_MULTIPLE_EXTENSIONS: "postgis,postgis_topology"
    ports:
      - 5432:5432

  redis:
    image: "redis:alpine"

volumes:
  pg_data:

I'm using a volume to make my data persistent I managed to run my containers and add data to the database. A volume has successfully been created : docker volume ls

DRIVER              VOLUME NAME
local               server_pg_data

But this volume is empty as the output of docker system df -v shows:

Local Volumes space usage:

VOLUME NAME                                                        LINKS               SIZE
server_pg_data                                                     1                   0B

Also, if I want or need to build the containers once again using docker-compose down and docker-compose up, data has been purged from my database. Yet, I thought that volumes were used to make data persistent on disk…

I must be missing something in the way I'm using docker and volumes but I don't get what:

  • why does my volume appears empty while there is some data in my postgres container ?
  • why does my volume does not persist after doing docker-compose down ?

This thread (How to persist data in a dockerized postgres database using volumes) looked similar but the solution does not seem to apply.


Solution

  • The kartoza/postgis image isn't configured the same way as the standard postgres image. Its documentation notes (under "Cluster Initializations"):

    By default, DATADIR will point to /var/lib/postgresql/{major-version}. You can instead mount the parent location like this: -v data-volume:/var/lib/postgresql

    If you look at the Dockerfile in GitHub, you will also see that parent directory named as a VOLUME, which has some interesting semantics here.

    With the setting you show, the actual data will be stored in /var/lib/postgresql/11.0; you're mounting the named volume on a different directory, /var/lib/postgresql/data, which is why it stays empty. Changing the volume mount to just /var/lib/postgresql should address this:

    volumes:
      - pg_data:/var/lib/postgresql:rw # not .../data