NocoDB 生产部署实战:Traefik 自定义 SSL 证书 + 外部 PostgreSQL/Redis 架构解析
本文以 NocoDB 仓库中 traefik-custom-ssl 部署示例为核心,完整讲解「外部托管数据库 + 外部缓存 + Traefik 自有证书终结 TLS」这套生产级部署形态:如何组织证书文件与 certs.yml、如何用 Docker Compose 编排 nocodb 主容器、worker 容器与 Traefik 反向代理,以及配合外部服务实现水平扩容的关键点。读完后你能直接复制该示例改造成自己域名的 HTTPS 生产部署,并理解每个环境变量与标签在 NocoDB 源码中的实际作用。
适用场景:全外置依赖 + 企业证书
该示例的定位(见 examples 总览)是「使用你自己的 SSL 证书进行生产部署」——所有后端服务均外置,Traefik 使用你自己的证书(企业 CA、通配符证书均可)终结 TLS:
- PostgreSQL:外部托管数据库(RDS/Azure/Cloud SQL),启用 SSL;
- Redis:外部托管(ElastiCache、Memorystore、Azure Cache 等);
- Proxy:Traefik + 自定义 SSL 证书。
这套形态的典型价值在于:数据与状态全部落在外部托管服务上,NocoDB 本身是无状态应用容器,可以随意横向扩容和滚动重启。
部署步骤:复制示例、放证书、改三处配置
原文档给出的标准操作流程如下:
cp -r examples/traefik-custom-ssl ./my-deployment
cd my-deployment
# Place your TLS certificate and key
mkdir -p certs
cp /path/to/cert.pem certs/cert.pem
cp /path/to/key.pem certs/key.pem
# Edit docker.env: set NC_REDIS_URL
# Edit nocodb/db.json: set your database host and credentials
# Edit docker-compose.yml: replace nocodb.example.com with your domain
docker compose up -d
需要修改的三处配置分别对应三个文件:
| 文件 | 要改的内容 |
|---|---|
docker.env |
外部 Redis 地址 NC_REDIS_URL(以及 NC_SITE_URL 等) |
nocodb/db.json |
外部 PostgreSQL 的主机、账号密码等连接信息 |
docker-compose.yml |
将 nocodb.example.com 替换为你的真实域名 |
另外注意 examples 总览文档中的通用警告:所有占位符(CHANGE_ME_db_password、your-managed-db-host 等)在启动前必须替换。
证书文件规范:完整证书链 + 私钥
证书必须放在部署目录的 certs/ 下,文件内容要求如下(源自 README):
| 文件 | 内容 |
|---|---|
certs/cert.pem |
完整证书链(服务器证书 + 中间证书) |
certs/key.pem |
对应私钥 |
注意 cert.pem 要求的是完整证书链而非单张叶子证书,即需要把中间证书拼接进去,否则部分客户端会因缺少中间 CA 而报证书错误。
certs.yml 负责告诉 Traefik 证书在哪里。示例中的默认内容(certs.yml):
tls:
certificates:
- certFile: /etc/traefik/certs/cert.pem
keyFile: /etc/traefik/certs/key.pem
如果还需要为额外域名配置多张证书,向 certs.yml 追加条目即可:
tls:
certificates:
- certFile: /etc/traefik/certs/cert.pem
keyFile: /etc/traefik/certs/key.pem
- certFile: /etc/traefik/certs/other-cert.pem
keyFile: /etc/traefik/certs/other-key.pem
编排细节:docker-compose.yml 逐段解析
完整编排文件包含三个服务,逐个拆解如下。
nocodb 主服务
nocodb:
image: nocodb/nocodb:latest
env_file: docker.env
deploy:
mode: replicated
replicas: 1
restart: unless-stopped
volumes:
- nocodb_data:/usr/app/data
- ./nocodb/db.json:/usr/app/data/db.json
networks:
- nocodb-network
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.nocodb.rule=Host(`nocodb.example.com`)'
- 'traefik.http.routers.nocodb.entrypoints=websecure'
- 'traefik.http.routers.nocodb.tls=true'
healthcheck:
test: ['CMD-SHELL', 'wget -q --tries=1 --spider http://localhost:8080/api/v1/health || exit 1']
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
几个关键点:
deploy.mode: replicated+replicas:以声明式副本数管理实例,这是后续水平扩容的基础(见后文「水平扩容」一节)。db.json通过卷注入:./nocodb/db.json:/usr/app/data/db.json,与docker.env中的NC_DB_JSON_FILE=/usr/app/data/db.json指向同一位置——NocoDB 由此读取外部 PostgreSQL 连接配置。- Traefik 标签:
exposedbydefault=false的 Traefik 只暴露带traefik.enable=true标签的服务;路由规则Host(\nocodb.example.com`)绑定域名,且仅挂在websecure(443)入口并强制tls=true`。 - 健康检查:容器内用
wget --spider探测http://localhost:8080/api/v1/health,间隔 30 秒、超时 5 秒、重试 5 次,start_period: 30s给启动留出宽限——该健康检查是 worker 容器启动的前置条件。
worker 服务:把后台任务剥离出来
worker:
image: nocodb/nocodb:latest
env_file: docker.env
environment:
NC_WORKER_CONTAINER: 'true'
depends_on:
nocodb:
condition: service_healthy
restart: unless-stopped
volumes:
- nocodb_data:/usr/app/data
- ./nocodb/db.json:/usr/app/data/db.json
networks:
- nocodb-network
worker 使用同一镜像,通过 NC_WORKER_CONTAINER='true' 切换到 worker 模式,且必须等 nocodb 主容器通过健康检查后才启动(condition: service_healthy)。从源码可以印证这个标志的实际含义(Noco.ts):
if (process.env.NC_WORKER_CONTAINER === 'true') {
if (!getRedisURL()) {
throw new Error('NC_REDIS_URL is required');
}
process.env.NC_DISABLE_TELE = 'true';
}
即:worker 模式强制要求配置 NC_REDIS_URL(任务队列依赖 Redis),未配置时直接抛错退出;同时自动禁用遥测(NC_DISABLE_TELE=true)。这解释了为什么本示例的 docker.env 中 NC_REDIS_URL 是必填项。此外,源码中如 jobs-redis.ts 与 auth.module.ts 等模块都依据该标志决定只挂载 worker 侧逻辑(跳过 AuthController 等 HTTP 路由)。
traefik 服务:文件 + Docker 双 Provider
traefik:
image: traefik:v3.6
command:
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=false'
- '--providers.file.filename=/etc/traefik/certs.yml'
- '--entryPoints.web.address=:80'
- '--entryPoints.websecure.address=:443'
- '--entryPoints.web.http.redirections.entryPoint.to=websecure'
- '--entryPoints.web.http.redirections.entryPoint.scheme=https'
ports:
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/etc/traefik/certs:ro
- ./certs.yml:/etc/traefik/certs.yml:ro
restart: unless-stopped
networks:
- nocodb-network
配置要点:
- 双 Provider:Docker provider(
exposedbydefault=false,配合服务标签使用)+ file provider(加载/etc/traefik/certs.yml中的 TLS 证书)。路由规则来自 Docker 标签,证书配置来自本地文件,两者职责分离。 - 强制 HTTPS:
web(80)入口上配置了redirections.entryPoint,所有 HTTP 流量 301 跳转到websecure(443),用户无法再明文访问。 - 只读挂载:docker.sock 以
:ro挂载(Traefik 只读取容器事件),./certs与./certs.yml同样只读挂载,证书文件与容器内路径的对应关系即/etc/traefik/certs/。
环境变量与数据库配置:docker.env 和 db.json
docker.env
docker.env 共五个变量,含义与源码依据如下:
# Database
NC_DB_JSON_FILE=/usr/app/data/db.json
# Redis
NC_REDIS_URL=redis://your-redis-host:6379
# Public URL (email links, webhooks, OAuth redirects). Set to your public-facing URL.
NC_SITE_URL=https://nocodb.example.com
# Settings
NC_SECURE_ATTACHMENTS=true
NC_DISABLE_MUX=true
NC_DB_JSON_FILE:告诉 NocoDB 去哪里读数据库连接 JSON,与 compose 中卷挂载路径一致。NC_REDIS_URL:外部 Redis 地址,worker 模式与缓存均依赖它。NC_SITE_URL:对外公开 URL,用于邮件链接、Webhook、OAuth 回调。从源码(envs.ts)看,ncSiteUrl取NC_SITE_URL(兼容回退NC_PUBLIC_URL);mail.service.ts 中若该值未配置,系统无法生成安全链接并发出告警邮件,因此生产环境必须设置且与实际访问域名一致。NC_SECURE_ATTACHMENTS:启用附件访问控制。源码中(envs.ts)它与NC_ATTACHMENT_ACCESS_CONTROL_ENABLED共同决定isSecureAttachmentEnabled,并在 noco.module.ts 中据此启用相应安全模块;经由 Traefik 反代暴露公网时建议保持true。
nocodb/db.json:外部 PostgreSQL 连接
db.json 模板如下:
{
"client": "pg",
"connection": {
"host": "your-managed-db-host.rds.amazonaws.com",
"port": "5432",
"user": "nocodb",
"password": "CHANGE_ME_db_password",
"database": "nocodb",
"ssl": {
"rejectUnauthorized": true
}
}
}
client: "pg"声明使用 PostgreSQL 客户端;host/port/user/password/database换成你托管数据库的实际值;ssl.rejectUnauthorized: true表示严格校验数据库服务端证书——连接托管数据库(RDS 等)时通常直接可用;若你的私有 PG 使用自签或内部 CA 证书,需要另行处理 CA 信任问题(可参考仓库中同系列的 postgres-private-ca 示例)。
替换 CHANGE_ME_db_password 等占位符是本示例启动前的硬性要求。
水平扩容:外部服务 + 副本模式
README 最后给出的扩容方式:
deploy:
mode: replicated
replicas: 3
将 nocodb(worker 同理)的 replicas 调大即可水平扩容,前提是状态已全部外置:
- 元数据/数据在外部 PostgreSQL,不依赖容器本地文件系统;
- 缓存与任务队列在外部 Redis,跨副本共享;
- 容器卷
nocodb_data只承载共享的db.json配置(各副本读的是同一个只读模板文件)。
这正是「全外置依赖」架构相对本地 SQLite/内置 Redis 的核心优势:任意副本都可以接收请求与执行任务,扩缩容不需要数据迁移。
自检清单
启动前按顺序核对一遍(均来自本示例的 README 与配置文件要求):
certs/cert.pem为完整证书链、certs/key.pem为对应私钥,且文件名与 certs.yml 一致;docker.env中NC_REDIS_URL、NC_SITE_URL已改为真实值,NC_SITE_URL的域名与 Traefik 路由Host()规则一致;nocodb/db.json的数据库主机与凭据已替换,ssl.rejectUnauthorized与你的 CA 信任策略匹配;- docker-compose.yml 中的
nocodb.example.com已替换为你的域名(出现在traefik.http.routers.nocodb.rule标签里); - 执行
docker compose up -d后,先访问 HTTP 确认 301 跳转到 HTTPS,再用https://你的域名验证证书链是否完整受信。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00