设置自托管文档

以 Markdown 格式查看
企业功能

此功能仅适用于企业计划。如需开始使用,请联系 support@buildwithfern.com

前置条件

在设置自托管文档之前,请确保您具备:

  • 在您的系统上安装了 Docker
  • 可以访问您的 Fern 项目的 fern/ 目录
  • 来自 Fern 的 Docker Hub 组织访问令牌(OAT)(用于拉取私有镜像)

设置说明

1

向 Docker Hub 进行身份验证

自托管文档运行在私有 Docker 镜像上:fernenterprise/fern-self-hosted

联系 Fern 支持 以获取 Docker Hub 组织访问令牌(OAT)。

使用 Fern 提供的令牌登录到 Docker Hub:

$docker login --username fernenterprise

当提示输入密码时,输入 Fern 团队提供的 OAT。

在 CI 中,通过 DOCKERHUB_OAT 环境变量传递令牌:

$echo "$DOCKERHUB_OAT" | docker login --username fernenterprise --password-stdin
2

下载 Docker 镜像

拉取镜像:

$docker pull fernenterprise/fern-self-hosted:latest

验证镜像在您的 Docker 守护进程中可用:

$docker images | grep fernenterprise/fern-self-hosted
3

创建 Dockerfile

在包含您的 fern/ 文件夹的同一目录中,创建一个名为 Dockerfile 的文件:

your-project/
├── Dockerfile
└── fern/
├── fern.config.json
├── docs.yml
└── ...

将以下内容添加到 Dockerfile 中:

Dockerfile
1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5RUN fern-generate

fern-generate 是 Docker 镜像内可用的命令,它在构建时处理您的文档,从而实现更快的容器启动、离线部署和更小的攻击面。这不是您在主机上运行的命令。您也可以选择将生成延迟到运行时

4

构建您的 Docker 镜像

从包含您的 Dockerfilefern/ 文件夹的目录构建镜像:

$docker build -t self-hosted-docs .
5

运行文档

启动您的自托管文档:

$docker run -p 3000:3000 self-hosted-docs

文档将在 localhost:3000 可用。

6

部署文档

现在您可以将镜像部署到您自己的基础设施,允许您在自己的域名上托管文档。

部署后,您可以设置预览环境来在每个拉取请求上预览文档更改。

自定义域名

您的文档使用在 docs.yml 文件中指定的域名。例如:

1instances:
2 - url: example-org.docs.buildwithfern.com
3 custom-domain: docs.plantstore.dev

要在运行时覆盖域名(例如,当实际主机名与 docs.yml 中的 custom-domain 不同时),请设置 CUSTOM_DOMAIN 环境变量:

$docker run -p 3000:3000 -e CUSTOM_DOMAIN=docs.plantstore.dev self-hosted-docs

详细信息请参见环境变量

环境变量

通过在您的 Dockerfile 或 Kubernetes 部署中设置环境变量来配置自托管容器的行为。

通用

变量描述默认值
CUSTOM_DOMAIN在运行时覆盖 docs.yml 中的 custom-domain。当文档实际提供服务的主机名与 docs.yml 中的域名不同时很有用。接受纯主机名(例如,docs.plantstore.dev);任何 https://http:// 前缀都会被自动去掉。来自 docs.ymlcustom-domain
FERN_LOG_LEVEL文档生成期间 Fern CLI 的日志级别。选项:debuginfowarnerrordebug
NODE_MEMORY_LIMITNext.js 服务器的 Node.js 堆大小(MB)。对于有许多 API 版本的大型文档站点需要增加。4096
NEXT_PUBLIC_BASE_PATH从子路径而不是根路径提供文档服务。值必须以 / 开头且没有尾部斜杠(例如,/docs)。详细信息请参见基础路径无(从 / 提供服务)

缓存预热

容器可以在启动时预取所有页面,以确保第一个真实用户请求是快速的。

变量描述默认值
WARMUP设置为 true 以在启动时启用缓存预热。在后台运行,不会阻塞容器就绪。false
WARMUP_TIMEOUT预热期间每个页面请求的超时秒数。5

缓存代理

容器包含一个位于 Next.js 服务器前面的缓存代理。

变量描述默认值
CACHE_MAX_ENTRIES要缓存的最大页面数。1000
CACHE_MAX_ENTRY_SIZE每个缓存条目的最大大小(字节)。5242880(5 MB)
CACHE_DEFAULT_TTL默认缓存生存时间(TTL)(秒)。2592000(30 天)
CACHE_CDN_TTL下游 CDN 缓存(例如,CloudFront)的缓存 TTL(秒)。3600(1 小时)
CACHE_DISABLED设置为 true1 以完全禁用缓存。false
CACHE_PROXY_DEBUG设置为 1 以启用详细的缓存代理日志记录。0

跨源资源共享(CORS)代理

容器包含一个 CORS 代理,允许文档前端进行跨源请求(例如,为 API Explorer 的试用功能向您的 API 发送请求)。默认情况下,只允许文档域名本身。使用 CORS_PROXY_ALLOWED_DOMAINS 来将其他域名添加到白名单中。

变量描述默认值
CORS_PROXY_ALLOWED_DOMAINS通过 CORS 代理允许的根域名的逗号分隔列表。子域名会自动匹配。

例如,要允许对 api.plantstore.devauth.plantstore.dev 的请求:

1ENV CORS_PROXY_ALLOWED_DOMAINS="plantstore.dev"

要允许多个域名:

1ENV CORS_PROXY_ALLOWED_DOMAINS="plantstore.dev,partner-api.example.com"

调试

变量描述默认值
ENABLE_JAEGER设置为 true 以启动 Jaeger 进行分布式追踪。Jaeger UI 在端口 16686 上可用。false

页面反馈

在自托管模式下,页面反馈事件作为结构化 JSON 日志输出到容器的 stdout,前缀为 [fern-docs-feedback]。您可以在您的日志基础设施中过滤这些:

$docker logs <container-id> 2>&1 | grep "\[fern-docs-feedback\]"

每个日志行包含一个事件名称、时间戳和一组属性:

1[fern-docs-feedback] {"event":"feedback_submitted","timestamp":"2026-01-15T12:34:56.789Z","properties":{"satisfied":true,"message":"Great docs!","email":"user@example.com","type":"on-page-feedback"}}

跟踪的事件

事件描述
feedback_voted用户点击了赞成或反对按钮。
feedback_submitted用户通过反馈表单提交了书面反馈。
code_block_feedback_submitted用户报告了代码示例的问题。

属性

属性描述
satisfied赞成为 true,反对为 false
message用户的书面反馈消息(在 feedback_submittedcode_block_feedback_submitted 事件中存在)。
email用户的电子邮件地址(如果提供)。
type反馈来源,例如 on-page-feedback

其他配置

以下部分涵盖了特定部署场景的可选配置。

基础路径

默认情况下,自托管容器从根路径(/)提供文档服务。设置 NEXT_PUBLIC_BASE_PATH 以从子路径提供服务,例如 /docs。当您的文档与反向代理后面的其他应用程序共享域名时,这很有用。

值必须以 / 开头,不能以尾部斜杠结尾。

在运行 fern-generate 之前在您的 Dockerfile 中设置 NEXT_PUBLIC_BASE_PATH。这会在构建时将基础路径修补到包中,因此容器可以使用只读文件系统运行。

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5ENV NEXT_PUBLIC_BASE_PATH=/docs
6
7RUN fern-generate

使用 NEXT_PUBLIC_BASE_PATH=/docs,文档可在 http://localhost:3000/docs 而不是 http://localhost:3000/ 访问。

构建时使用 NEXT_PUBLIC_BASE_PATH 的单个 Docker 镜像可以在运行时配置为从任何路径提供服务。这让您可以在可能需要不同基础路径的环境中重用一个镜像。

运行时生成

默认情况下,fern-generate 在 Docker 构建时运行。如果您需要以下功能,可以将生成延迟到运行时:

  • 在运行时传递配置(环境变量、密钥)
  • 在开发期间加速 Docker 构建
  • 在多个文档配置间共享单个镜像

使用 --only-deps 标志将生成延迟到运行时:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5RUN fern-generate --only-deps

这会在构建时启动所需的服务(PostgreSQL、MinIO、FDR),但跳过文档生成。当容器启动时,它会自动运行 fern generate --docs

运行时生成需要在容器启动时访问网络。对于离线部署,请使用默认的构建时生成。

使用 gRPC 的离线部署

如果您的 API 使用 gRPC 并具有来自 Buf Schema Registry(BSR)的依赖项,buf CLI 会在生成期间从 buf.build 获取模块。这在没有网络访问的离线环境中会失败。

1

检查 BSR 依赖项

检查您的项目在任一位置是否有 BSR 依赖项:

buf.yaml 中:

1version: v2
2deps:
3 - buf.build/googleapis/googleapis
4 - buf.build/grpc-ecosystem/grpc-gateway

generators.yml 中:

1api:
2 specs:
3 - proto:
4 root: ./protos/
5 dependencies:
6 - buf.build/googleapis/googleapis

如果没有 depsdependencies 部分(或只有本地路径),您可以跳过本节的其余部分。

2

选择解决方案

选项 1:构建时生成(推荐)

在网络访问可用时在构建时运行 fern-generate

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5RUN fern-generate

这会在 Docker 构建期间下载 BSR 依赖项并将其嵌入到镜像中。运行时不需要网络访问。

当您在构建时没有所有信息且需要文档在运行时生成不同的内容时使用此选项,例如在运行时注入环境变量。

要在离线环境中在运行时生成,请在本地供应商 buf 依赖项:

1FROM fernenterprise/fern-self-hosted:latest
2
3# 安装 buf CLI 用于依赖项缓存
4RUN npm install -g @bufbuild/buf
5
6# 复制 fern 配置
7COPY fern/ fern/
8COPY protos/ protos/
9
10# 在构建时预取 buf 依赖项(缓存 googleapis、protovalidate)
11RUN cd protos && buf dep update
12
13# 构建 fern 依赖项
14RUN fern-generate --only-deps

更新 buf.yaml 以引用供应商依赖项:

1# 之前
2deps:
3 - buf.build/googleapis/googleapis
4
5# 之后
6deps:
7 - ./vendor/googleapis

有关更多详细信息,请参见 Buf 依赖项管理文档

如果您没有 buf.yaml 文件,您可以直接在您的 generators.yml 中指定 proto 依赖项。自托管容器在构建过程中会自动从这些依赖项创建临时的 buf.yaml

generators.yml
1api:
2 specs:
3 - proto:
4 root: ./protos/
5 dependencies:
6 - buf.build/googleapis/googleapis
7 - buf.build/bufbuild/protovalidate

这种方法适用于构建时和运行时生成:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5# 对于构建时生成(推荐用于离线部署)
6RUN fern-generate
7
8# 或者对于运行时生成(启动时需要网络)
9# RUN fern-generate --only-deps

容器会解析您的 fern 目录中的所有 generators.yml 文件,找到具有依赖项但没有 buf.yaml 的 proto 规范,并自动创建必要的配置。

Kubernetes 部署

这是一个示例 Deployment 和 Service 配置。将 your-registry/fern-docs:latest 替换为您的镜像名称。

应用配置:

$kubectl apply -f deployment.yaml
$kubectl apply -f service.yaml

deployment.yaml:

deployment.yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: fern-docs
5 labels:
6 app: fern-docs
7spec:
8 replicas: 1
9 selector:
10 matchLabels:
11 app: fern-docs
12 template:
13 metadata:
14 labels:
15 app: fern-docs
16 spec:
17 securityContext:
18 runAsNonRoot: true
19 runAsUser: 65532
20 runAsGroup: 65532
21 fsGroup: 65532
22 fsGroupChangePolicy: OnRootMismatch
23 containers:
24 - name: fern-docs
25 image: your-registry/fern-docs:latest
26 imagePullPolicy: IfNotPresent
27 ports:
28 - name: docs
29 containerPort: 3000
30 protocol: TCP
31 - name: health
32 containerPort: 8081
33 protocol: TCP
34 resources:
35 requests:
36 memory: "2Gi"
37 cpu: "1000m"
38 limits:
39 memory: "4Gi"
40 cpu: "2000m"
41 livenessProbe:
42 httpGet:
43 path: /liveness
44 port: 8081
45 initialDelaySeconds: 120
46 periodSeconds: 10
47 timeoutSeconds: 5
48 failureThreshold: 3
49 readinessProbe:
50 httpGet:
51 path: /readiness
52 port: 8081
53 initialDelaySeconds: 60
54 periodSeconds: 5
55 timeoutSeconds: 5
56 failureThreshold: 6
57 securityContext:
58 allowPrivilegeEscalation: false
59 runAsNonRoot: true
60 runAsUser: 65532
61 runAsGroup: 65532
62 privileged: false
63 readOnlyRootFilesystem: false
64 capabilities:
65 drop:
66 - ALL
67 terminationGracePeriodSeconds: 30

service.yaml:

service.yaml
1apiVersion: v1
2kind: Service
3metadata:
4 name: fern-docs
5 labels:
6 app: fern-docs
7spec:
8 type: NodePort
9 ports:
10 - name: http
11 port: 80
12 targetPort: 3000
13 protocol: TCP
14 nodePort: 30080
15 selector:
16 app: fern-docs

有关健康检查端点的详细信息,请参见健康检查端点