PostgREST macht aus einem Postgres-Schema eine REST-API, ganz ohne Glue-Code - du richtest es auf eine Datenbank und es serviert die Tabellen. Ich wollte das kleinste lokale Setup, das es zum Laufen bringt, also bin ich der Doku zu Containerized PostgREST mit Docker Compose gefolgt, habe einen Swagger-UI-Service ergänzt, um die generierte API zu durchstöbern, und die Umgebungsvariablen an Tutorial 0 - Get it Running angeglichen. Das einzige Extra ist eine seed.sql, die in den db-Service eingehängt wird, damit die Rollen, die PostgREST braucht, schon beim Start des Containers existieren.

Docker Compose

Drei Services. server ist PostgREST selbst, spricht als Rolle authenticator mit Postgres und stellt das api-Schema bereit; anonyme Anfragen fallen auf die Rolle web_anon zurück. db ist schlichtes Postgres mit eingehängtem Daten-Volume und Seed-Skript. swagger liefert eine interaktive UI auf 8080, die auf die API zeigt.

docker-compose.yml
services:
server:
image: postgrest/postgrest
ports:
- "3000:3000"
environment:
PGRST_DB_URI: postgres://authenticator:mysecretpassword@db:5432/app_db
PGRST_DB_SCHEMAS: api
PGRST_DB_ANON_ROLE: web_anon
PGRST_OPENAPI_SERVER_PROXY_URI: http://127.0.0.1:3000
depends_on:
- db
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_DB: app_db
POSTGRES_USER: app_user
POSTGRES_PASSWORD: password
volumes:
- ./pgdata:/var/lib/postgresql/data
- ./seed.sql:/docker-entrypoint-initdb.d/seed.sql
swagger:
image: swaggerapi/swagger-ui
ports:
- "8080:8080"
expose:
- "8080"
environment:
API_URL: http://localhost:3000/

Das Seed-Skript

Postgres führt jede .sql-Datei in /docker-entrypoint-initdb.d/ einmalig beim ersten Start aus. Dorthin gehören Schema und Rollen. Das api-Schema ist das, was PostgREST bereitstellt; web_anon ist die lesende Rolle für anonyme Aufrufer; und authenticator ist die Login-Rolle, mit der PostgREST sich verbindet und die in web_anon wechseln kann, weil sie ihr zugewiesen ist. Halte mysecretpassword deckungsgleich mit der PGRST_DB_URI oben, sonst kommt keine Verbindung zur API zustande.

seed.sql
create schema api;
create table api.todos (
id int primary key generated by default as identity,
done boolean not null default false,
task text not null,
due timestamptz
);
insert into api.todos (task) values
('finish tutorial 0'), ('pat self on back');
create role web_anon nologin;
grant usage on schema api to web_anon;
grant select on api.todos to web_anon;
create role authenticator noinherit login password 'mysecretpassword';
grant web_anon to authenticator;

Starten

Mit docker compose up -d hochfahren, dann http://localhost:3000/todos für die laufende API und http://localhost:8080 für die Swagger-UI aufrufen. Keine Controller, keine Serializer, keine Routen-Definitionen - das Schema ist die API.