Lokális gép, openSUSE, szeretnénk PostgreSQL-t használni pgAdmin-nal. Telepítsük a Dockert, ha még nem volt (megj.: a Docker Compose V2-t már nem kell külön telepíteni, a V1-et még kellett).

Csináljunk egy új projektmappát, benne egy compose.yaml konfigfájlt (docker-compose.yml volt a korábbi, V1-es gyakorlat, amely továbbra is működik):

services:

  db:
    container_name: ctr_postgres
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      PGDATA: /var/lib/postgresql/data
    ports:
      - "${DB_PORT}:5432"
    volumes:
      - db-data-pg16:/var/lib/postgresql/data

  pgadmin:
    container_name: ctr_pgadmin4
    image: dpage/pgadmin4
    restart: unless-stopped
    environment:
      - PGADMIN_DEFAULT_EMAIL=${PGADMIN_USER}
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD}
      - PGADMIN_DISABLE_POSTFIX=True
      - PGADMIN_CONFIG_SERVER_MODE=False
      - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False
    ports:
      - "${PGADMIN_PORT}:80"
    configs:
      - source: pgpass
        target: /pgpass
        uid: "5050"
        gid: "5050"
        mode: 0600
      - source: servers.json
        target: /pgadmin4/servers.json
      - source: preferences.json
        target: /pgadmin4/preferences.json
    depends_on:
      - db

configs:
  pgpass:
    content: "db:${DB_PORT}:*:${DB_USER}:${DB_PASSWORD}"
  servers.json:
    content: |
      {"Servers": {"1": {
          "Group": "Servers",
          "Name": "Docker Postgres 16",
          "Host": "db",
          "Port": ${DB_PORT},
          "MaintenanceDB": "${DB_DATABASE}",
          "Username": "${DB_USER}",
          "PassFile": "/pgpass",
          "SSLMode": "disable"
      }}}      
  preferences.json:
    content: |
      {"preferences": {
          "misc:themes:theme": "dark"
      }}      
volumes:
  db-data-pg16:

Majd hozzunk létre egy .env fájlt:

DB_PORT=5678
DB_DATABASE=dbtest
DB_USER=root
DB_PASSWORD=root
DB_URL=postgres://$DB_USER:$DB_PASSWORD@localhost:$DB_PORT/$DB_DATABASE

PGADMIN_PORT=8080
PGADMIN_USER=myemail@address.com
PGADMIN_PASSWORD=root

Megjegyzések:

  • A titkokat .env fájlban adjuk meg változókkal, bár egy dev-környezet beállításáról van szó valódi titkok nélkül. Ez a jó gyakorlat.
  • A restart=unless-stopped azt jelenti, hogy a konténerek kézi leállításig újraindulnak, a docker démon újraindítása után pedig nem indulnak el, ha le voltak állítva (az always ekkor is elindítaná őket).
  • A megőrzendő, osztott adatok itt kötetekre kerülnek, amelyek alapértelmezetten a /var/lib/docker/volumes/ mappában élnek. Kötetnév helyett megadhatnánk helyi mappát is, ezt bind mount néven emlegetik. Az adattárolás egyéb részleteit lásd a Docker-dokumentációban. Kötet vagy osztott mappa nélkül elveszik az adatbázis a konténer leállításakor.
  • A postgres fő verziószámát szándékosan rögzítettük.
  • Ha léptetjük a postgres fő verziószámát, akkor upgrade-elni kell az adatbázist. Ezt a legegyszerűbben így tehetjük meg:
    • dumpoljuk az aktuális adatbázist;
    • átírjuk a postgres verziót és a db volume nevét a compose.yaml konfigban;
    • újraindítjuk a szolgáltatást, ekkor létrejön az új adatbázis egy új köteten;
    • importáljuk a dumpot;
    • végül eldobhatjuk a régi image-et és volume-ot, ha mindent rendben találtunk.
  • A services.pgadmin.environment csak listaként működik (mert a True/False case sensitive Pythonban).
  • Ahhoz, hogy a pgadmin manuális beállítását elkerüljük, szüksége van egy kapcsolati (pgpass) és egy szerverdefiníciós (servers.json) konfigfájlra. A felületi beállítások konfigfájlja (preferences.json) opcionális. E fájlokat a fenti módon inline is megadhatjuk.
  • MaintenanceDB: a default/system adatbázis szokásosan postgres névvel jön létre, nagyjából annyi szerepe van, hogy egyéb adatbázis hiányában is be lehessen jelentkezni a szerverre. Nincs rá szükségünk, így itt megadtuk a saját adatbázisunkat.

Ezután elindíthatjuk a szolgáltatásokat, illetve azok konténereit (megj.: nem ugyanaz a kettő, és itt szándékosan, didaktikus céllal használunk különböző service és container neveket).

$ cd myproject
$ docker compose up -d
$ docker compose ps
$ docker compose down

GUI: pgAdmin

A pgAdmin http://localhost:8080 címen érhető el pár másodperccel az indulás után. Ha nem érjük el, nézzünk rá a logokra:

$ docker compose logs -f -t -n50 pgadmin

Régebben manuálisan konfigoltuk a pgAdmint, és e lépésekre volt szükség a használhatóvá tételéhez:

  • Bejelentkezés után adjunk hozzá új szervert az Object > Register > Server menüpontban.
  • A Name tetszőleges, az jelenik meg majd a bal oldali fában.
  • A Connection fülön a fenti konfigban megadottak szerinti legyen a Host és a Port.

CLI: psql

Használhatjuk a konténerbeli psql klienst:

$ docker compose exec db psql -Uroot mydb

Ez esetben szükség lehet a Docker image bővítésére. Vagy telepíthetünk psql klienst lokálisan.

Init/seeding

Felhasználókat, sémákat, domaineket stb. adhatunk az adatbázishoz létrehozásakor init scriptek (*.sql, *.sql.gz, *.sh) segítségével. Ezek csak akkor futnak le (névsorrendben), ha üres a data mappa, tehát még nem létezik egyetlen adatbázis sem.

services:
  db:
    volumes:
      - ./initdb.d:/docker-entrypoint-initdb.d
# stb...

Dump/export

Adatbázis vagy tábla exportálása SQL-ként lokálból (lásd a pg_dump dokut):

$ docker compose exec db pg_dump -Uroot mydb > localdir/dump.sql
$ docker compose exec db pg_dump -Uroot mydb | gzip > dump_$(date +"%y%m%d%H%M%S").sql.gz
$ docker compose exec db pg_dump -Uroot mydb --schema-only > schema.sql

Tábla exportálása CSV-ként konténerből (itt a /data/ egy távoli bindelt mappa):

$psql> \copy myschema.mytable to '/data/mytable.csv' delimiter ';' csv header;

Import

$ psql -hlocalhost -p5678 -Uroot mydb < dump.sql

Logok

$ docker compose logs -f -t -n10 db