Directus 自托管内容 API:本地 CMS 跑通后,用 cpolar 给前端远程验收接口和后台
前端做官网、活动页、App 配置页时,最怕内容接口还没稳定:字段名今天一个版本,权限明天一个版本,图片上传又要单独找人联调。Directus 适合解决这类问题。它不是简单的数据库管理台,而是把测试库里的内容模型变成可用的后台、REST API、GraphQL API 和媒体库。
这篇从零跑一套本地 Directus:Docker 部署,使用 SQLite 测试库,创建文章内容集合和媒体字段,配置只读角色权限,验证 REST/GraphQL 接口,最后用 cpolar 开一个短时 HTTPS 入口,让前端同事远程验收后台、接口、字段权限和媒体上传。
边界先说清楚:本文只使用测试库和脱敏内容;不暴露数据库端口、Admin 密码、静态密钥和服务器目录;不开放公开注册;cpolar 只短时转发 Directus Web/API;验收结束立即关闭隧道。长期环境请换正式 HTTPS 域名、备份、最小权限角色和审计策略。
1. 准备目录和 docker-compose
Directus 可以连接 PostgreSQL、MySQL、SQLite 等数据库。为了本地验收简单可复现,这里用 SQLite 测试库。它适合 Demo、字段确认和前端接口验收;不要拿生产数据文件直接做公网联调。
新建目录:
mkdir -p ~/demo/directus-content-api cd ~/demo/directus-content-api mkdir -p database uploads extensions创建docker-compose.yml:
services: directus: image: directus/directus:11 container_name: directus-content-demo ports: - "127.0.0.1:8055:8055" volumes: - ./database:/directus/database - ./uploads:/directus/uploads - ./extensions:/directus/extensions environment: KEY: "replace-with-a-long-random-key-for-demo" SECRET: "replace-with-a-long-random-secret-for-demo" ADMIN_EMAIL: "admin@example.local" ADMIN_PASSWORD: "ChangeMe-Directus-2026!" DB_CLIENT: "sqlite3" DB_FILENAME: "/directus/database/data.db" WEBSOCKETS_ENABLED: "true" PUBLIC_URL: "http://127.0.0.1:8055"这里有两个细节:
ports绑定到127.0.0.1:8055,只允许本机访问,不把 Directus 直接监听到局域网或公网。KEY、SECRET、ADMIN_PASSWORD演示时也要换成自己的随机值,不要提交到 Git 仓库,更不要发给前端群。
启动:
docker compose up -d查看日志:
docker compose logs -f directus看到服务运行后,打开后台:
http://127.0.0.1:8055/admin用ADMIN_EMAIL和ADMIN_PASSWORD登录。登录后先进入 Settings,确认没有开放公开注册。这个演示只给前端一个低权限账号,不让外部用户自行注册。
2. 创建内容模型:articles 集合
我们做一个“官网文章/活动页内容”模型,前端验收时能覆盖标题、摘要、富文本、封面、状态和排序这些常见字段。
在 Directus 后台进入Settings → Data Model,新建集合:
Collection Name: articles Display Template: {{title}}字段按下面配置:
| 字段 | 类型 | 用途 |
|---|---|---|
| title | String | 文章标题,必填 |
| slug | String | 前端路由或详情页标识,必填且唯一 |
| summary | Text | 列表摘要 |
| content | Text / WYSIWYG | 正文内容 |
| cover | File | 封面图,关联 Directus Files |
| status | String | draft / published |
| sort | Integer | 首页排序 |
| published_at | DateTime | 发布时间 |
cover字段选择 File 类型,Directus 会使用内置的directus_files媒体库。这样前端既能拿文章 JSON,也能拿文件 ID,再通过 Directus 的 assets 地址显示图片。
保存后进入Content → articles,新增两条脱敏测试内容:
标题:暑期活动页上线说明 slug:summer-campaign summary:用于前端远程验收的测试内容 status:published sort:10再新增一条草稿:
标题:未发布内容测试 slug:draft-demo summary:用于验证角色权限是否能过滤草稿 status:draft sort:99封面图片使用无敏感信息的测试图。不要上传客户合同、真实用户头像、生产素材原图或带 EXIF 定位信息的照片。
3. 配置前端验收角色和权限
Directus 的关键价值不只是“生成接口”,而是能把字段权限和角色权限一起交给前端验证。这里创建一个专门的验收角色,避免把 Admin 账号发出去。
进入Settings → Roles & Permissions,新建角色:
Role Name: frontend_reviewer Description: 前端远程验收 Directus 内容 API,只读 articles,可上传测试媒体给这个角色配置权限:
articles 权限
- Read:允许
- Create:不允许
- Update:不允许
- Delete:不允许
Read 的过滤条件设置为:
{ "status": { "_eq": "published" } }这样前端用验收账号只能看到已发布内容,看不到草稿。
字段权限建议开放:
id, title, slug, summary, content, cover, status, sort, published_at如果内部还有cost_price、internal_note、owner_phone这类敏感字段,就不要给该角色读取权限。前端验收时要专门检查这些字段是否从接口响应里消失。
directus_files 权限
为了验收媒体上传,给directus_files配置:
- Read:允许
- Create:允许
- Update:不允许
- Delete:不允许
这代表前端同事可以上传测试图片,能读取自己上传和文章关联的图片,但不能删除媒体库文件。正式环境还要进一步限制文件大小、MIME 类型、存储后端和生命周期。
创建验收用户
进入User Directory,创建用户:
Email: reviewer@example.local Role: frontend_reviewer Status: Active Password: Review-Only-2026!这个密码只用于本次短时验收。验收结束后禁用用户或重置密码。
4. 本机验证 REST API
Directus 默认提供 REST API。先用 Admin 登录后台确认有内容,再开一个终端测试匿名或验收用户访问。
如果 articles 集合允许公开读取,可以直接请求:
curl "http://127.0.0.1:8055/items/articles?fields=id,title,slug,summary,cover,status&filter[status][_eq]=published"更推荐使用验收账号登录拿 token:
curl -s -X POST "http://127.0.0.1:8055/auth/login" \ -H "Content-Type: application/json" \ -d '{"email":"reviewer@example.local","password":"Review-Only-2026!"}'返回里会有access_token。为了演示方便,保存到变量:
TOKEN="粘贴上一步返回的 access_token"请求文章列表:
curl "http://127.0.0.1:8055/items/articles?fields=id,title,slug,summary,cover,status,published_at&sort=sort" \ -H "Authorization: Bearer $TOKEN"检查点有三个:
- 返回结果只包含
status=published的内容。 - 响应字段只包含前端需要的字段。
- 草稿
draft-demo不出现在列表里。
如果上传过封面,REST 响应里会有文件 ID。访问图片资源:
curl -I "http://127.0.0.1:8055/assets/文件ID"前端页面里可使用:
http://127.0.0.1:8055/assets/文件ID远程验收时把域名换成 cpolar 的 HTTPS 地址即可。
5. 验证 GraphQL API
Directus 也内置 GraphQL,前端如果使用 Apollo、urql 或其他 GraphQL 客户端,可以直接验收查询结构。
请求示例:
curl -X POST "http://127.0.0.1:8055/graphql" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "query": "query { articles(filter: { status: { _eq: \"published\" } }, sort: [\"sort\"]) { id title slug summary status published_at cover { id filename_disk type } } }" }'这一步要让前端确认两件事:
- GraphQL schema 里的字段名和页面组件需要的一致。
- 角色权限仍然生效,不能因为换成 GraphQL 就读到草稿或敏感字段。
如果 GraphQL 返回权限错误,不要急着把角色权限全开。先看报错字段,再逐个补齐需要读取的字段权限。权限调试的原则是“前端需要什么给什么”,不要为了省事直接给 Admin。
6. 用 cpolar 开短时 HTTPS 验收入口
本机确认 Directus 可用后,再给前端同事远程验收。这里 cpolar 的作用很明确:只把本机8055上的 Directus Web/API 临时映射成 HTTPS 地址。不要转发数据库端口,不要转发 Docker socket,不要转发服务器文件目录。
确认 Directus 仍在本机运行:
curl -I http://127.0.0.1:8055/server/health启动 cpolar 隧道:
cpolar http 8055终端会显示一个 HTTPS 地址,形如:
https://xxxx.cpolar.top把 Directus 的公开地址临时改成这个 HTTPS 地址,有助于媒体资源、回调地址和前端请求保持一致。编辑docker-compose.yml:
PUBLIC_URL: "https://xxxx.cpolar.top"重启 Directus:
docker compose up -d远程访问后台地址:
https://xxxx.cpolar.top/admin发给前端同事的信息只需要包含:
Directus 后台:https://xxxx.cpolar.top/admin REST 列表:https://xxxx.cpolar.top/items/articles?fields=id,title,slug,summary,cover,status,published_at&sort=sort GraphQL:https://xxxx.cpolar.top/graphql 验收账号:reviewer@example.local 验收密码:单独私信发送,本次验收结束后失效密码不要和链接放在同一条群消息里,也不要截图展示 Admin 控制台。
7. 前端验收清单
我会让前端同事按这个清单验收,而不是只说“你打开看看”:
- 能打开
https://xxxx.cpolar.top/admin,使用frontend_reviewer用户登录。 - 在 Content 里只能看到
articles和允许读取的媒体内容。 - 文章列表只出现
published内容,草稿内容不可见。 - REST 接口能返回页面需要的字段,字段名稳定。
- GraphQL 查询能跑通,schema 与组件数据结构匹配。
- 上传一张测试封面图,确认
assets/文件ID能通过 HTTPS 打开。 - 尝试新增、修改、删除文章,应被权限拦截。
- 尝试读取未授权字段,应不出现在响应中或返回权限错误。
这个清单能把“后台能看”“接口能调”“字段权限生效”“媒体上传可用”一次性确认完。对于官网、活动页、内容运营后台,这比发几张截图可靠得多。
8. 验收结束后的收尾
验收完成后,先停 cpolar:
# 在运行 cpolar 的终端按 Ctrl+C再禁用验收用户或重置密码:
Settings → User Directory → reviewer@example.local → Status: Suspended如果这套 Directus 只是临时 Demo,可以停止容器:
docker compose down测试库和上传目录还在本机:
~/demo/directus-content-api/database ~/demo/directus-content-api/uploads保留它们前,确认里面没有真实客户数据、真实用户手机号、内部文档附件或不可公开图片。要删除演示环境,可以执行:
cd ~ rm -rf ~/demo/directus-content-api删除前再次确认路径,避免误删其他项目目录。
9. 长期使用时要换正式方案
cpolar 很适合短时验收,但不要把临时隧道当长期生产入口。Directus 一旦用于正式内容后台,至少要补齐这些配置:
- 使用正式 HTTPS 域名和反向代理,例如 Nginx、Caddy 或云负载均衡。
- 数据库使用可备份、可监控的 PostgreSQL/MySQL,并建立备份恢复流程。
- Admin 开启强密码和成员最小权限,不共享账号。
- 前端只使用低权限角色或服务端代理,不把 Admin token 写进浏览器代码。
- 媒体文件限制大小和类型,接入对象存储时配置私有桶与访问策略。
- 定期查看 Directus 活动日志,审计内容修改、登录和文件上传记录。
- 分离开发、测试、生产环境,测试库只放脱敏内容。
这也是我推荐先用 SQLite 本地跑通的原因:字段、权限、接口和媒体流程先让前端验收清楚,再决定生产库、域名、对象存储和部署架构。Directus 的优势在于内容模型能快速变成 API,但权限边界必须从第一天就按真实项目去配置。
小结
这套流程的重点不是“把本地服务暴露出去”,而是把 Directus 作为自托管内容 API 跑完整:Docker 启动、SQLite 测试库、articles 内容模型、媒体上传、角色权限、REST/GraphQL 查询,再用 cpolar 的临时 HTTPS 地址完成远程验收。
前端拿到的不是截图,而是能登录的后台、能请求的接口、能验证的字段权限和能打开的媒体资源。验收结束关掉 cpolar、禁用验收账号,环境就回到本机。等要长期使用时,再上正式域名、数据库备份、对象存储、审计和更细的角色权限。