Loading...

文章背景图

PostgREST 保姆级部署教程:给 PostgreSQL 数据库直接生成 RESTful API 服务

2026-11-01
0
- 字
- 分钟
|

一、项目介绍

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=host flag. 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。

八、实操验证

  1. 启动后用 curl 访问根路径,PostgREST 会返回 OpenAPI 描述:
curl http://localhost:3000/

逐段解释:GET 请求到 PostgREST 根端点,服务自动返回 OpenAPI JSON(官方 README「Self-documentation」一节)。预期输出参考: 一段 JSON,包含 openapi、info、paths 等字段。

  1. 在 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 建表。

  1. 通过 PostgREST 插入一条记录:
curl http://localhost:3000/todos -X POST -H "Content-Type: application/json" -d '{"task":"hello postgrest"}'

逐段解释:POST 到 /todos 端点(即表名),JSON body 为行数据。预期输出参考: 返回 201 Created 与插入的行(含自动生成的 id)。

  1. 查询:
curl http://localhost:3000/todos

预期输出参考: [{"id":1,"task":"hello postgrest","done":false}]。

  1. 过滤查询(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 的 role claim 取数据库角色,然后以该角色连库执行 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 并重启;③ 确认表在 public schema(默认暴露)。

案例 3:macOS 下 --net=host 不生效,连接被拒

  • 报错原文:connection refused 连不上 localhost:5432。
  • 报错原因:官方文档原文:"Docker on Mac does not support the --net=host flag."
  • 分步解决:① 按官方文档建 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 镜像均可自由商用。
评论交流

文章目录