一、项目介绍
PostgREST 是一个用 Haskell 编写的独立服务,官方 README 原文:"PostgREST serves a fully RESTful API from any existing PostgreSQL database. It provides a cleaner, more standards-compliant, faster API than you are likely to write from scratch."(PostgREST 从任意一个已存在的 PostgreSQL 数据库直接提供完全 RESTful 的 API,比你自己从零写的 API 更干净、更符合标准、更快。)
它的工作方式是:连接到一个 PostgreSQL 数据库,把表、视图、函数自动暴露为 HTTP 端点;用 JSON Web Token(JWT)做认证,把授权完全委托给数据库中的角色权限——服务端在连接期间以当前认证用户的身份操作数据库,用户自己做不到的事 PostgREST 也做不到。性能方面,官方 README 给出:"subsecond response times for up to 2000 requests/sec on Heroku free tier."(在 Heroku 免费套餐上即可达到每秒 2000 请求、亚秒级响应。)
项目在 GitHub(PostgREST/postgrest)持续活跃维护,官方提供 Docker 镜像 postgrest/postgrest,文档站为 postgrest.org。
二、功能拆解
按官方 README,核心特性如下:
| 功能 | 说明 |
|---|---|
| 自动 REST API | 从已有 PostgreSQL 数据库生成表/视图/函数对应的 HTTP 端点 |
| JWT 认证 | 用 JSON Web Token 处理认证,授权委托给数据库角色 |
| 数据库级授权 | 服务端以当前认证用户身份连接数据库,权限即数据库角色权限 |
| 高性能 | Haskell + Warp 编译型 HTTP 服务器;Hasql 连接池;PostgreSQL 二进制协议;无状态可水平扩展 |
| 下推计算 | JSON 序列化、数据校验、授权、计数+检索、单行 insert(returning *)全部下推到 SQL |
| Schema 版本化 | 通过数据库 schema 做多版本 API,底层表可被视图隐藏 |
| OpenAPI 自文档 | 自动生成 OpenAPI 文档,可用 Swagger-UI 渲染交互式调试页 |
| 范围头 | 用 Range 头报告/限制返回行数 |
| 数据完整性 | 约束直接建在数据库中;API 层强制幂等 PUT |
三、官方/GitHub 链接
- GitHub 仓库:https://github.com/PostgREST/postgrest
- 官方网站/文档:https://postgrest.org (最新文档 https://docs.postgrest.org/en/stable/ )
- 安装文档:https://docs.postgrest.org/en/stable/explanations/install.html
- Docker 镜像:https://hub.docker.com/r/postgrest/postgrest
- API 指南:https://docs.postgrest.org/en/stable/api.html
- 认证文档:https://docs.postgrest.org/en/stable/auth.html
- Patreon 赞助:https://www.patreon.com/postgrest
四、环境要求
官方安装文档给出两种原生部署路径:
- Docker 方式:只需 Docker。官方文档原文:"You can get the official PostgREST Docker image with..."
- 原生包安装:官方文档列出各平台(Linux 各发行版、macOS Homebrew、Windows)的包管理器安装方式;依赖 PostgreSQL 客户端库(
pg_config需在 PATH 中)。 - 端口:默认 3000(官方 docker-compose 示例
ports: - "3000:3000")。 - 数据库:必须是 PostgreSQL(任何现有实例均可)。
- 操作系统:Docker 方式跨平台;原生包按官方文档对应发行版选择。
- 硬件:官方文档未给出最低硬件指标。
五、部署步骤
方式 A:Docker 连接已存在的宿主机 PostgreSQL(官方文档「Containerized PostgREST with native PostgreSQL」)
步骤 1:拉取官方镜像
docker pull postgrest/postgrest
逐段解释:官方文档原文:"# pull the latest version"。如需固定版本:
docker pull postgrest/postgrest:<version>(版本列表见 https://hub.docker.com/r/postgrest/postgrest/tags )。
预期输出参考: Docker 拉取进度条,结束显示 Status: Downloaded newer image for postgrest/postgrest:latest。
步骤 2:以 host 网络模式连接宿主机 PostgreSQL
docker run --rm --net=host \
-e PGRST_DB_URI="postgres://app_user:password@localhost/postgres" \
postgrest/postgrest
逐段解释:
docker run运行容器;--rm退出后自动删除容器;--net=host使用宿主网络栈(Linux 下容器内localhost即宿主);-e PGRST_DB_URI=...通过环境变量传入数据库连接串(app_user/password/postgres需按实际数据库角色替换);镜像名postgrest/postgrest。官方文档原文警告:"The database connection string above is just an example. Adjust the role and password as necessary. You may need to edit PostgreSQL's pg_hba.conf to grant the user local login access."
预期输出参考: PostgREST 启动日志(加载配置、连接数据库、监听 3000 端口)。
macOS 注意(官方文档原文): "Docker on Mac does not support the
--net=hostflag. Instead you'll need to create an IP address alias to the host." macOS 用户应先:
sudo ifconfig lo0 10.0.0.10 alias
然后把连接串中的 host 改为 10.0.0.10,并在 postgresql.conf 的 listen_addresses 加入 10.0.0.10、在 pg_hba.conf 加 host all all 10.0.0.10/32 trust,再用下面的端口映射方式运行:
docker run --rm -p 3000:3000 \
-e PGRST_DB_URI="postgres://app_user:password@10.0.0.10/postgres" \
postgrest/postgrest
方式 B:Docker Compose 同时起 PostgREST 与 PostgreSQL(官方文档「Containerized PostgREST and db with docker-compose」)
步骤 1:创建官方 docker-compose.yml
官方文档原文给出的配置:
# docker-compose.yml
version: '3'
services:
server:
image: postgrest/postgrest
ports:
- "3000:3000"
environment:
PGRST_SERVER_HOST: 0.0.0.0 # necessary for `postgrest --ready` flag to work
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
逐段解释:
server服务用官方postgrest/postgrest镜像,映射宿主 3000 到容器 3000;PGRST_SERVER_HOST: 0.0.0.0让postgrest --ready健康检查标志生效(官方注释原文);PGRST_DB_URI指向 compose 中的db服务(主机名即服务名db);PGRST_OPENAPI_SERVER_PROXY_URI告诉 OpenAPI 文档中对外暴露的地址;depends_on: db先起数据库。db服务用官方postgres镜像,通过POSTGRES_DB/POSTGRES_USER/POSTGRES_PASSWORD初始化数据库与角色。
步骤 2:启动
docker compose up -d
逐段解释:依据 docker-compose.yml 后台启动两个服务。
预期输出参考: 两个容器依次 Started,回到命令行提示符。
六、配置参数详解
PostgREST 支持用环境变量(PGRST_ 前缀)或配置文件(postgrest.conf)配置。官方 compose 示例用到的核心项:
| 变量 | 示例值 | 说明 |
|---|---|---|
PGRST_DB_URI |
postgres://app_user:password@db:5432/app_db |
PostgreSQL 连接串 |
PGRST_SERVER_HOST |
0.0.0.0 |
监听地址;官方注明此值是 postgrest --ready 健康检查标志工作的必要条件 |
PGRST_OPENAPI_SERVER_PROXY_URI |
http://127.0.0.1:3000 |
OpenAPI 文档中对外暴露的服务地址(反向代理后需改) |
其他关键项(见官方 auth/settings 文档):
| 变量 | 说明 |
|---|---|
PGRST_DB_SCHEMAS |
暴露的数据库 schema 列表(默认 public) |
PGRST_DB_ANON_ROLE |
匿名请求使用的数据库角色 |
PGRST_JWT_SECRET |
签发/校验 JWT 用的密钥 |
PGRST_JWT_ROLE_CLAIM |
JWT 中存放角色名的 claim(默认 role) |
PGRST_SERVER_PORT |
监听端口(容器内默认 3000) |
PGRST_MAX_ROWS |
单次响应最大行数(防超大结果集) |
PGRST_DB_POOL |
数据库连接池大小 |
七、启动与运维
- 前台运行: 方式 A 的
docker run --rm ...命令前台占用终端。 - 后台运行: 方式 B 的
docker compose up -d;方式 A 如要后台可把--rm后加-d(Docker 通用参数,官方文档未专门给出)。 - 停止:
docker compose down;前台容器按Ctrl+C(--rm自动清理)。 - 查看日志:
docker compose logs -f server(-f跟踪);Docker 原生docker logs <容器名>。 - 健康检查: 官方注释提到
postgrest --ready标志,需配合PGRST_SERVER_HOST=0.0.0.0。 - 开机自启: 官方 compose 未内置
restart:策略;如需容器随 Docker 自动拉起,可在 compose 中加restart: unless-stopped(Docker 原生能力,非 PostgREST 官方文档内容)。 - 数据持久化: 官方 compose 示例未为 db 服务声明命名卷;生产环境应按 Docker 惯例为
postgres服务加volumes: - pgdata:/var/lib/postgresql/data。 - 修改端口: 改 compose 中
server.ports(如"8080:3000"),容器内仍 3000;同时把PGRST_OPENAPI_SERVER_PROXY_URI改为http://127.0.0.1:8080,再docker compose up -d。
八、实操验证
- 启动后用 curl 访问根路径,PostgREST 会返回 OpenAPI 描述:
curl http://localhost:3000/
逐段解释:GET 请求到 PostgREST 根端点,服务自动返回 OpenAPI JSON(官方 README「Self-documentation」一节)。预期输出参考: 一段 JSON,包含
openapi、info、paths等字段。
- 在 PostgreSQL 中准备一张表(以方式 B 的 db 服务为例):
docker compose exec db psql -U app_user -d app_db -c "create table todos(id serial primary key, task text, done boolean default false);"
逐段解释:
docker compose exec db在运行中的 db 容器内执行命令;psql -U app_user -d app_db连接数据库;-c "..."执行一条 SQL 建表。
- 通过 PostgREST 插入一条记录:
curl http://localhost:3000/todos -X POST -H "Content-Type: application/json" -d '{"task":"hello postgrest"}'
逐段解释:POST 到
/todos端点(即表名),JSON body 为行数据。预期输出参考: 返回201 Created与插入的行(含自动生成的id)。
- 查询:
curl http://localhost:3000/todos
预期输出参考: [{"id":1,"task":"hello postgrest","done":false}]。
- 过滤查询(PostgREST 自动把查询参数翻译成 WHERE):
curl "http://localhost:3000/todos?task=eq.hello%20postgrest"
逐段解释:
task=eq.hello%20postgrest即 PostgREST 的过滤语法(eq= equals)。
登录与安全(重要)
- 官方默认账号密码:PostgREST 本身不设独立账号密码。 它的认证模型是 JWT + 数据库角色:HTTP 请求带
Authorization: Bearer <JWT>,PostgREST 用PGRST_JWT_SECRET校验签名,从 JWT 的roleclaim 取数据库角色,然后以该角色连库执行 SQL。 - 匿名访问: 未带 JWT 的请求使用
PGRST_DB_ANON_ROLE指定的数据库角色;该角色在数据库中拥有什么权限,API 就暴露什么。 - 登录地址: PostgREST 不提供登录页面;登录由你的应用自行实现(验证用户、签发 JWT)。
- JWT 密钥配置: 环境变量
PGRST_JWT_SECRET;安全提醒:公网部署必须设置强随机密钥,并在数据库中用GRANT/REVOKE精确控制app_user与anon角色的表/列权限——官方 README「Security」一节原文:"PostgREST handles authentication (via JSON Web Tokens) and delegates authorization to the role information defined in the database. This ensures there is a single declarative source of truth for security." - 密码存放位置: 数据库角色密码在
PGRST_DB_URI连接串中;JWT 密钥在PGRST_JWT_SECRET环境变量。生产环境用 Docker secrets 注入,勿提交到 git。
九、故障排查
案例 1:容器启动报数据库连接失败
- 报错原文(常见形式):
the database system is starting up或connection refused。 - 报错原因:
server服务在db就绪前启动;或PGRST_DB_URI中的主机名/密码与 db 服务不一致。 - 分步解决:① 确认 compose 中
db.environment.POSTGRES_PASSWORD与PGRST_DB_URI密码一致(默认password);②docker compose restart server;③ 官方 compose 已用depends_on: db,如仍偶发,可加 Docker 原生 healthcheck 等待 Postgres 真正就绪。
案例 2:访问 API 返回 401 Unauthorized 或 404
- 报错原文(常见形式):
{"message":"Missing or invalid access token"}或表查询返回空。 - 报错原因:未配置
PGRST_DB_ANON_ROLE,或该角色未被 GRANT 对应表的 SELECT 权限;或表不在PGRST_DB_SCHEMAS暴露的 schema 中。 - 分步解决:① 在数据库中
CREATE ROLE anon LOGIN; GRANT USAGE ON SCHEMA public TO anon; GRANT SELECT ON todos TO anon;;② 设置PGRST_DB_ANON_ROLE=anon并重启;③ 确认表在publicschema(默认暴露)。
案例 3:macOS 下 --net=host 不生效,连接被拒
- 报错原文:
connection refused连不上localhost:5432。 - 报错原因:官方文档原文:"Docker on Mac does not support the
--net=hostflag." - 分步解决:① 按官方文档建 lo0 别名
sudo ifconfig lo0 10.0.0.10 alias;② 在postgresql.conf的listen_addresses加10.0.0.10;③ 在pg_hba.conf加host all all 10.0.0.10/32 trust;④ 用docker run -p 3000:3000 -e PGRST_DB_URI="postgres://app_user:password@10.0.0.10/postgres" postgrest/postgrest启动。
案例 4:OpenAPI 文档中的 server URL 不对(反向代理后)
- 报错现象:Swagger UI 中 try-it-out 打到错误地址。
- 报错原因:
PGRST_OPENAPI_SERVER_PROXY_URI未设为反向代理后的对外地址。 - 分步解决:① 在 compose 中改
PGRST_OPENAPI_SERVER_PROXY_URI: http://你的域名;②docker compose up -d重建 server。
十、升级、回滚与卸载
升级: 官方未在 README/安装文档中给出专门升级命令;基于 Docker 镜像机制:① docker compose pull;② docker compose up -d(自动用新镜像重建 server 容器)。如需固定版本,把 compose 中 image: postgrest/postgrest 改为 image: postgrest/postgrest:<版本号>(版本列表见 Docker Hub tags 页)。
回滚: 官方未提供一键回滚命令;基于镜像标签机制,把 image 改回旧版本号后 docker compose up -d。PostgREST 无内置元数据库,回滚不涉及数据迁移。
卸载: ① docker compose down 停止并删除容器;② 如在 db 服务上声明了命名卷,删除卷 docker volume rm <项目名>_pgdata(此操作永久删除数据库,先备份——docker compose exec db pg_dump -U app_user app_db > backup.sql);③ 删除镜像 docker rmi postgrest/postgrest postgres。
十一、商用许可合规说明
- 许可证:MIT License(官方仓库 LICENSE 文件首部:"Copyright (c) 2014-2026 The PostgREST contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software...")。
- MIT 许可允许自由使用、修改、分发与商用(包括闭源商业产品),分发时须保留原始版权声明与许可文本。
- 官方 README 顶部徽章同时挂出 Patreon 赞助链接,属社区可持续维护方式,不影响代码的 MIT 许可。
- PostgREST 无商业版/企业版区分,自开源仓库构建与 Docker Hub 镜像均可自由商用。