Docker 一键部署 PostgREST:权限、配置到第一个 REST API 的完整路线
【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrest
PostgREST 做的事很直白:把一个现成的 PostgreSQL 数据库,直接变成一套标准的 REST API。你不用写 controller、不用写路由、不用手写序列化代码——表、视图、函数就是端点,角色和授权规则就是安全边界。它适合三种人:已经用 Postgres 存数据、想给前端或第三方快速开接口的后端;不想维护一套 ORM + 手写 API 的小团队;以及需要把数据库当成"安全真相源"(所有授权落在库内)的架构师。
一句话记住它的分工:PostgREST 管认证(谁来请求),PostgreSQL 管授权(你能碰什么)。整条链路只有一行 SQL 级别的真相。
3 条命令用 Docker 跑起 PostgREST
先跑通,再谈原理。最短路径是 Docker:官方镜像用scratch打底,只塞一个静态二进制,镜像约 14MB,启动是毫秒级的。
第一步,把"数据库 + PostgREST"两个容器一起拉起来。把下面内容存成docker-compose.yml:
# docker-compose.yml version: '3' services: server: image: postgrest/postgrest ports: ["3000:3000"] environment: PGRST_SERVER_HOST: 0.0.0.0 # 让就绪检查能工作 PGRST_DB_URI: postgres://app_user:password@db:5432/app_db 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第二步,启动并观察日志:
docker-compose up✅ 看到API server listening on port 3000就说明服务起来了。第三步,验证一下:
curl http://localhost:3000/返回的是这份 API 的 OpenAPI 描述(Swagger 规范)。到这里,你已经有一个在监听的 PostgREST 实例了。后面所有章节,都是把"它能做什么"拆给你看。
挑一条安装路径:包管理器、二进制还是 Docker
三种官方方式都能装,选哪个取决于你的环境。
| 方式 | 命令示例 | 特点 | 适合 |
|---|---|---|---|
| 包管理器 | brew install postgrest/pacman -S postgrest/pkg install hs-postgrest/nix-env -i postgrest/choco install postgrest | 自动处理依赖,随发行版更新 | 开发机、图省事 |
| 预编译二进制 | 从 release 页下postgrest-<版本>-<平台>,tar Jxf解压后直接跑 | 版本可控、可放任意 Linux 发行版 | 生产、要锁定版本 |
| Docker | docker pull postgrest/postgrest | 环境隔离、镜像 ~14MB、scratch无多余组件 | 容器化、云原生 |
决策建议:开发环境用包管理器最顺;生产要可复现、可灰度,上 Docker;二进制留给"我就要这个版本、又不想引入容器"的场景。
两点容易踩:
- 二进制依赖
libpq。报error while loading shared libraries: libpq.so.5时,Ubuntu/Debian 装libpq-dev,CentOS/RHEL/Fedora 装postgresql-libs,macOS 用brew install postgresql。 - Windows若弹出找不到
pg_config的对话框,把C:\Program Files\PostgreSQL\<版本>\bin加进PATH。
装完统一用postgrest --help验证。
让每个请求都落在对的数据库角色上
PostgREST 的安全模型就一句话:请求进来 → 换成一个数据库角色 → 这个角色能碰什么,你就只能碰什么。整个过程不靠应用层判断,全靠库里的GRANT和行级安全(RLS)。
三种角色各司其职:
- authenticator:负责建连的"门面",必须能
LOGIN,但它本身尽量不给权限,只负责"切换"。 - 匿名角色(
db-anon-role):没带 JWT 的请求走它,通常只给只读。 - 用户角色:带 JWT 的请求按
role声明切到它,不同用户不同权限集。
下面这套 SQL 是最小可用配置,建角色、给授权、再上一道行级安全:
-- 门面角色:能登录、不继承、能切换 create role authenticator noinherit login password 'mysecretpassword'; -- 匿名角色:nologin,只给只读 create role web_anon nologin; grant web_anon to authenticator; -- 让门面能切到它 grant usage on schema api to web_anon; grant select on api.todos to web_anon; -- 最小权限:只读 -- 行级安全:每个用户只看到自己的行 alter table api.todos enable row level security; create policy anon_policy on api.todos for select using (current_setting('request.jwt.claims', true)::json->>'user_id' = user_id);JWT 里的role声明决定切到哪个角色,密钥用jwt-secret校验(至少 32 字符)。它长这样:
改这几个参数,其余塞进速查表
配置有四种来源,优先级从低到高:配置文件 < 环境变量 < 库内配置。配置文件就是键值对,服务器启动时把它当作唯一参数传入:
# postgrest.conf db-uri = "postgres://authenticator:mysecretpassword@localhost:5432/mydb" db-schemas = "api" db-anon-role = "web_anon" jwt-secret = "reallyreallyreallyreallyverysafe" server-port = 3000启动:postgrest /path/to/postgrest.conf;没把握就postgrest -e > postgrest.conf生成一份样例再改。
环境变量规则是PGRST_前缀 + 大写 + 下划线,例如db-uri→PGRST_DB_URI,容器里最常用。库内配置则建一个函数,用set_config写参数,配合db-pre-config = "postgrest.pre_config"启用——好处是改配置不用重启。
🔒 真正会常改的就这几个,先记住它们:
db-uri:连库的字符串。db-anon-role:匿名请求用哪个角色(不设则禁止匿名)。db-schemas:暴露哪些模式,默认public。jwt-secret:校验 JWT 的密钥,至少 32 字符。server-port/server-host:监听端口(默认 3000)与绑定地址(默认!4,任意 IPv4)。
其余高级项,用这张速查表对着查就行:
| 参数 | 默认值 | 作用 |
|---|---|---|
db-pool | 10 | 连接池最大连接数 |
db-pool-acquisition-timeout | 10(秒) | 等连接槽的最长等待 |
db-pool-max-idletime | 30(秒) | 空闲连接回收 |
db-pool-max-lifetime | 1800(秒) | 单条连接最长存活 |
log-level | error | crit/error/warn/info/debug |
db-max-rows | ∞ | 硬限制单次返回行数 |
db-aggregates-enabled | false | 是否允许聚合函数 |
db-plan-enabled | false | 是否允许取执行计划 |
openapi-mode | follow-privileges | follow-privileges / ignore-privileges / disabled |
jwt-role-claim-key | $.role | 从 JWT 取角色的键路径 |
server-cors-allowed-origins | 空=任意 | 允许的跨域来源 |
改完多数参数可以热重载,不用重启:killall -SIGUSR2 postgrest,或库里执行NOTIFY pgrst, 'reload config'。注意环境变量改不了(进程级),Docker 里要么重启要么走库内配置。
搭一个商品+订单的 API 并跑通 CRUD
这次换个例子:shop模式,products和orders两张表,外键相连。先建表:
create schema shop; create table shop.products ( id int primary key generated by default as identity, name text not null, price numeric not null check (price >= 0) ); create table shop.orders ( id int primary key generated by default as identity, product_id int not null references shop.products(id), qty int not null default 1 check (qty > 0) ); insert into shop.products (name, price) values ('机械键盘', 399), ('4K 显示器', 2199); insert into shop.orders (product_id, qty) values (1, 2), (2, 1);这种"带外键的关系模式"是 PostgREST 的核心玩法:表变端点,外键让资源可以互相嵌入。下面这张官方示例模式图,就是"多表 + 外键"长什么样:
授权沿用上一节套路:给匿名角色只读,门面角色能切到它。
create role shop_anon nologin; grant usage on schema shop to shop_anon; grant select on shop.products, shop.orders to shop_anon; -- 匿名只读 create role shop_authenticator noinherit login password 'mysecretpassword'; grant shop_anon to shop_authenticator;写个最小配置并启动:
# shop.conf db-uri = "postgres://shop_authenticator:mysecretpassword@localhost:5432/postgres" db-schemas = "shop" db-anon-role = "shop_anon"postgrest shop.conf然后逐个跑通(开另一个终端):
# 1) 读全部商品 curl "http://localhost:3000/products" # 2) 过滤:价格大于 100 curl "http://localhost:3000/products?price=gt.100" # 3) 过滤 + 布尔:数量恰好为 1(演示 is 操作符) curl "http://localhost:3000/orders?qty=eq.1" # 4) 排序:按订单 id 倒序 curl "http://localhost:3000/orders?order=id.desc" # 5) 选列 + 分页 curl "http://localhost:3000/products?select=id,name&limit=5&offset=0"写操作呢?匿名角色只有SELECT,所以:
curl -X POST "http://localhost:3000/products" \ -H "Content-Type: application/json" \ -d '{"name":"鼠标","price":199}' # 401 / 42501:permission denied for table products返回 401 正是我们想要的——权限在库里,不在应用里。想让某类用户能写,就再建一个角色、给它INSERT/UPDATE,然后在 JWT 里带上role声明即可。
对着报错表自查,别慌
高频报错基本集中在"连不上"和"没权限"两类,按下面逐条对:
error while loading shared libraries: libpq.so.5—— 缺libpq。Ubuntu/Debian 装libpq-dev,CentOS/RHEL 装postgresql-libs,macOSbrew install postgresql。500/ connection refused / 连不上—— 核对db-uri的用户、密码、端口、库名;再看 Postgres 的pg_hba.conf是否允许该用户登录。401 Unauthorized(匿名请求)—— 没配db-anon-role,或该角色对目标表没有SELECT。补GRANT即可。permission denied for table ...(码 42501)—— 角色对这张表缺对应操作权限,按需要补GRANT SELECT/INSERT/UPDATE/DELETE。Bind for 0.0.0.0:5432 failed: port is already allocated—— 本机 5432 被占,把宿主机侧端口改掉,例如5433:5432,并同步改db-uri里的端口。- Windows 弹出
pg_config找不到—— 把C:\Program Files\PostgreSQL\<版本>\bin加入PATH。
三条 SQL 帮你自己定位"到底缺哪一环":
-- 1) 看角色继承链:哪个角色能被授予给谁 select c.rolname AS role, m.rolname AS granted_to from pg_auth_members am join pg_roles c on c.oid = am.roleid join pg_roles m on m.oid = am.member; -- 2) 看 shop 模式下各角色对表的权限 select grantee, privilege_type, table_name from information_schema.role_table_grants where table_schema = 'shop'; -- 3) 看当前会话身份与 JWT 声明(确认切对了角色) select current_user, current_setting('request.jwt.claims', true);第一条验证"门面能切到匿名/用户角色",第二条验证"表权限给够了",第三条在调试 RLS 时尤其有用。
判断该不该上 PostgREST
适合的场景:数据已经在 Postgres 里、要快速给前端/第三方开只读或受控读写接口、希望"安全真相源"落在库里、想要自带 OpenAPI 自文档。它把序列化、授权、行数限制这些活儿都交给数据库,省掉一整层手写 API 代码,支持 PostgreSQL 14 及以上。
不太适合的场景:业务逻辑很重、需要复杂的多步事务编排、或者主要数据并不在 Postgres 里。这些情况下 PostgREST 只会变成一层薄壳,真正的复杂度还是绕不开。
深入阅读从仓库里的文档下手:安装与 Docker 细节见 docs/explanations/install.rst,完整参数、默认值与可热重载项见 docs/references/configuration.rst。把上面这套"先跑通、再拆角色、最后造一个自己的 API"的顺序走完,你就已经能自己维护一套生产级的 PostgREST 了。
【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrest
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考