部署到 Node.js

本页内容

EmDash 在 Node.js 22.16 或更高版本上运行。本指南为单服务器使用 SQLite 和本地存储。当多个实例需要共享一个数据库时使用 PostgreSQL 或 libSQL,当媒体需要独立于服务器磁盘存续时使用 S3 兼容存储。

先决条件

  • Node.js v22.16.0 或更高版本
  • Node.js 托管提供商或 VPS

配置站点

为 Node.js 部署配置 EmDash:

import { defineConfig } from "astro/config";
import node from "@astrojs/node";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
	output: "server",
	adapter: node({ mode: "standalone" }),
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data/emdash.db" }),
			storage: local({
				directory: "./data/uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
		}),
	],
});

构建和运行

  1. 构建项目:

    npm run build
  2. 启动服务器:

    node ./dist/server/entry.mjs

服务器默认运行在 http://localhost:4321。使用默认的 auto 迁移模式时,第一个请求会应用待处理的核心迁移。全新数据库还会接收嵌入的种子。管理核心数据库迁移介绍了如何在恢复生产流量之前进行迁移。

计划任务

内置调度器仅在 Node.js 进程运行时工作。它处理计划发布、插件任务和一般维护。

在生产环境中保持至少一个 Node.js 进程持续运行。当所有进程停止或休眠时,计划任务会暂停。

插件沙盒

市场插件和 sandboxed: [] 下列出的插件需要沙盒运行器。在 Node.js 上,运行器是 @emdash-cms/sandbox-workerd,它在 workerd 子进程中运行插件。插件沙盒涵盖了安装、workerd 进程如何运行以及其故障模式。

选择生产数据服务

当数据库保留在持久卷上而媒体移至 S3 兼容存储时,使用以下模式:

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
			emdash({
				database: sqlite({ url: `file:${process.env.DATABASE_PATH}` }),
				storage: s3(),
		}),
	],
});

Docker

添加 .dockerignore 以保持构建上下文较小:

node_modules
dist
.git

创建 Dockerfile

FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

RUN mkdir -p data

ENV HOST=0.0.0.0
ENV PORT=4321

EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]

种子文件在构建时读取并内联到 bundle 中,因此不需要复制到运行时镜像中。迁移在部署后的第一个请求时运行;种子仅在数据库没有集合且设置未完成时应用 — 现有数据永远不会被覆盖。

构建镜像并运行容器:

docker build -t my-emdash-site .
docker run -p 4321:4321 -v emdash-data:/app/data my-emdash-site

Docker Compose 文件使用命名卷管理相同的容器:

services:
  emdash:
    build: .
    ports:
      - "4321:4321"
    volumes:
      - emdash-data:/app/data
    restart: unless-stopped

volumes:
  emdash-data:

在后台启动堆栈:

docker compose up -d

运行时环境

服务器启动时从进程环境读取数据库和存储凭据。以下变量支持上述配置:

加密密钥验证

EMDASH_ENCRYPTION_KEY 目前不加密插件密钥或任何其他存储数据。如果设置了该变量,EmDash 在启动时检查其格式,但插件密钥值在数据库中保持明文。

如果设置该变量,请生成一个有效值并将结果添加到你的环境中:

npx emdash secrets generate  # 将结果添加到环境中

该值由运维人员提供,不存储在数据库中。丢失它对数据恢复没有影响,因为没有存储数据依赖于它。将数据库及其备份视为敏感数据,因为它们包含明文插件密钥。

可选:稳定值覆盖

EmDash 自动生成预览 HMAC 密钥和评论者 IP 哈希盐,并在首次使用时持久化到数据库。以下环境变量将它们固定为你控制的值 — 当单独的进程需要与主站点共享密钥时很有用。

变量描述
EMDASH_PREVIEW_SECRET覆盖自动生成的预览 HMAC 密钥。
EMDASH_IP_SALT覆盖自动生成的评论者 IP 哈希盐。
EMDASH_AUTH_SECRET可选。如果设置,用作 IP 盐源(除非 EMDASH_IP_SALT 也设置了,后者优先),为已依赖它的安装保持评论者 IP 哈希稳定。新部署不要设置。

有关密钥格式、每个支持的密钥以及轮换或丢失的影响,请参见密钥管理

数据库和存储

变量描述示例
DATABASE_PATHSQLite 数据库路径/data/emdash.db
HOST服务器主机0.0.0.0
PORT服务器端口4321
S3_ENDPOINTS3 端点 URLhttps://xxx.r2.cloudflarestorage.com
S3_BUCKETS3 存储桶名称my-media-bucket
S3_ACCESS_KEY_IDS3 访问密钥AKIA...
S3_SECRET_ACCESS_KEYS3 私有密钥...
S3_REGIONS3 区域auto
S3_PUBLIC_URL媒体公共 URLhttps://cdn.example.com

持久化存储

SQLite 需要持久化磁盘存储。确保你的托管平台提供:

  • 挂载卷或持久磁盘
  • 数据库目录的写入权限
  • 数据库文件的备份机制

同时备份 SQLite 文件和上传目录。恢复时替换之前先停止进程。参见备份

健康检查

为负载均衡器添加健康检查端点:

export const GET = () => {
  return new Response("OK", { status: 200 });
};

此端点证明 Node.js 进程可以提供 Astro 路由。它不证明数据库、存储后端、迁移状态或插件沙盒是健康的。在向新版本发送流量之前,请单独验证这些依赖。

发送流量前验证

启动新构建后,验证生产请求使用的相同运行时服务:

  1. 请求 /health 和一个公开内容页面。两者都必须返回成功响应。
  2. 从构建的项目运行 npx emdash migrate --check。它必须报告配置的数据库没有待处理或未知的迁移。
  3. 登录 /_emdash/admin,创建或编辑一个临时草稿并发布。确认公开页面显示了更改。
  4. 上传一个临时媒体文件并打开其返回的 URL。验证后删除该文件。
  5. 如果站点使用沙盒插件,调用一个插件路由或钩子,确认服务器日志没有沙盒不可用或 workerd 启动错误。

在所有适用检查通过之前,不要将新实例加入负载均衡器。