预览环境
企业功能
此功能仅适用于企业计划。如需开始使用,请联系 support@buildwithfern.com。
有两种方式为自托管文档设置预览环境:
- 基于容器 — 部署与生产环境中使用的相同自托管 Docker 容器,为您提供具有搜索、API Explorer 和身份验证的完整预览。
- 静态导出 — 将文档渲染为静态 HTML 和资源文件,可从任何对象存储(S3、GCS、R2)提供服务,无需运行容器。
两种方法都会渲染与生产环境中完全相同的内容。
选择方法
对于大多数团队来说,静态导出是最佳起点,因为它的基础设施和设置要求最少。如果您需要在预览中使用搜索、API Explorer 或身份验证,请选择基于容器的方法。
| 基于容器 | 静态导出 Beta | |
|---|---|---|
| 内容渲染 | 与生产环境相同 | 与生产环境相同 |
| 搜索 | 是 | 否 |
| API Explorer(试用功能) | 是 | 否 |
| 身份验证 | 是 | 否 |
| 基础设施 | 需要容器托管、负载均衡器、DNS | 可从任何对象存储提供服务(S3、GCS、R2) |
| 扩展性 | 每个预览一个容器 | 无需服务器即可支持数千个预览 |
| 成本 | 较高 | 较低 |
| 清理 | 必须拆除容器和资源 | 简单 — 删除静态文件 |
GitHub Actions 工作流
可以将以下工作流添加到您的代码库中,以在每个拉取请求上自动构建和部署预览环境。
基于容器的预览工作流
此工作流在每个拉取请求上构建 Docker 镜像并将其部署到您的容器托管平台。
.github/workflows/preview-docs-container.yml
name: preview-docs-containeron:pull_request:jobs:preview-docs:runs-on: ubuntu-latestpermissions: write-allsteps:- name: Checkout repositoryuses: actions/checkout@v4- name: Log in to Docker Hubuses: docker/login-action@v3with:username: ${{ secrets.DOCKERHUB_USERNAME }}password: ${{ secrets.DOCKERHUB_TOKEN }}- name: Build docs containerrun: docker build -t self-hosted-docs:${{ github.sha }} .- name: Push container to registryrun: |docker tag self-hosted-docs:${{ github.sha }} ${{ secrets.REGISTRY }}/self-hosted-docs:${{ github.sha }}docker push ${{ secrets.REGISTRY }}/self-hosted-docs:${{ github.sha }}- name: Deploy previewrun: |# Deploy the container to your hosting platform# (e.g. ECS, Cloud Run, Kubernetes, etc.)# and retrieve the preview URLecho "Deploy self-hosted-docs:${{ github.sha }} to your platform"
静态导出预览工作流
此工作流构建容器,运行静态导出,并将输出上传到 S3。根据您的对象存储调整上传步骤。
.github/workflows/preview-docs-static.yml
name: preview-docs-staticon:pull_request:jobs:preview-docs:runs-on: ubuntu-latestpermissions: write-allsteps:- name: Checkout repositoryuses: actions/checkout@v4- name: Log in to Docker Hubuses: docker/login-action@v3with:username: ${{ secrets.DOCKERHUB_USERNAME }}password: ${{ secrets.DOCKERHUB_TOKEN }}- name: Build docs containerrun: docker build -t self-hosted-docs .- name: Start containerrun: |docker run -d \--name docs-container \-e WARMUP=true \self-hosted-docs- name: Wait for container to be healthyrun: |echo "Waiting for container to be healthy..."MAX_ATTEMPTS=60ATTEMPT=0while [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; doATTEMPT=$((ATTEMPT + 1))if docker exec docs-container sh -c \'TOKEN=$(cat /tmp/.cache-admin-token 2>/dev/null); \curl -f -s --max-time 5 \-H "Authorization: Bearer $TOKEN" \http://localhost:3000/__cache/stats' > /dev/null 2>&1; thenecho "Container is healthy."breakfiecho " Not ready yet... ($ATTEMPT/$MAX_ATTEMPTS)"sleep 5doneif [ "$ATTEMPT" -ge "$MAX_ATTEMPTS" ]; thenecho "Error: container did not become healthy."exit 1fi- name: Export static siterun: |docker exec docs-container /scripts/export.shdocker cp docs-container:/tmp/fern-static-export.tar.gz ./export.tar.gz- name: Extract static filesrun: |mkdir -p ./sitetar -xzf export.tar.gz -C ./site- name: Upload to S3uses: jakejarvis/s3-sync-action@v0.5.1with:args: --deleteenv:SOURCE_DIR: ./siteAWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}AWS_REGION: ${{ secrets.AWS_REGION }}DEST_DIR: pr-${{ github.event.pull_request.number }}- name: Comment preview URL on PRif: github.event_name == 'pull_request'uses: thollander/actions-comment-pull-request@v3with:message: |Preview: http://${{ secrets.AWS_S3_BUCKET }}.s3-website.${{ secrets.AWS_REGION }}.amazonaws.com/pr-${{ github.event.pull_request.number }}pr-number: ${{ github.event.pull_request.number }}- name: Stop containerif: always()run: docker rm -f docs-container