跳到导航

预览环境

Beta
以 Markdown 格式查看
企业功能

此功能仅适用于企业计划。如需开始使用,请联系 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-container
on:
pull_request:
jobs:
preview-docs:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build docs container
run: docker build -t self-hosted-docs:${{ github.sha }} .
- name: Push container to registry
run: |
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 preview
run: |
# Deploy the container to your hosting platform
# (e.g. ECS, Cloud Run, Kubernetes, etc.)
# and retrieve the preview URL
echo "Deploy self-hosted-docs:${{ github.sha }} to your platform"

此工作流构建容器,运行静态导出,并将输出上传到 S3。根据您的对象存储调整上传步骤。

.github/workflows/preview-docs-static.yml
name: preview-docs-static
on:
pull_request:
jobs:
preview-docs:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build docs container
run: docker build -t self-hosted-docs .
- name: Start container
run: |
docker run -d \
--name docs-container \
-e WARMUP=true \
self-hosted-docs
- name: Wait for container to be healthy
run: |
echo "Waiting for container to be healthy..."
MAX_ATTEMPTS=60
ATTEMPT=0
while [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; do
ATTEMPT=$((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; then
echo "Container is healthy."
break
fi
echo " Not ready yet... ($ATTEMPT/$MAX_ATTEMPTS)"
sleep 5
done
if [ "$ATTEMPT" -ge "$MAX_ATTEMPTS" ]; then
echo "Error: container did not become healthy."
exit 1
fi
- name: Export static site
run: |
docker exec docs-container /scripts/export.sh
docker cp docs-container:/tmp/fern-static-export.tar.gz ./export.tar.gz
- name: Extract static files
run: |
mkdir -p ./site
tar -xzf export.tar.gz -C ./site
- name: Upload to S3
uses: jakejarvis/s3-sync-action@v0.5.1
with:
args: --delete
env:
SOURCE_DIR: ./site
AWS_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 PR
if: github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v3
with:
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 container
if: always()
run: docker rm -f docs-container