Node.jsへのデプロイ
このページで分かること
- Node.js 22.16以上での設定(SQLiteとローカルのストレージ)、ビルドと起動、予約公開などの処理のためにプロセスを動かし続ける必要があること
- プラグインのサンドボックス、本番用のデータサービス(S3互換のストレージなど)、Dockerでの動かし方
- 実行時の環境変数、永続的なディスクが必要な理由、ヘルスチェック、本番の通信を流す前の確認
このページの目次
EmDashはNode.js 22.16以上で動作します。このガイドでは、1台のサーバーでSQLiteとローカルのストレージを使います。複数のインスタンスで1つのデータベースを共有する必要がある場合は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",
}),
}),
],
});
ビルドと起動
-
プロジェクトをビルドします。
npm run build -
サーバーを起動します。
node ./dist/server/entry.mjs
サーバーは、既定では http://localhost:4321 で動きます。マイグレーションのモードが既定の auto の場合、最初のリクエストで未適用のコアマイグレーションが適用されます。新しいデータベースには、埋め込まれたシードも適用されます。本番の通信を再開する前にマイグレーションする方法は、コアDBマイグレーションで説明しています。
やさしい解説
WordPressは、PHPが動くWebサーバー(ApacheやNginxなど)にファイルを置けば動きます。EmDashをNode.jsで動かす場合は、npm run build でサイトをビルドし、node ./dist/server/entry.mjs でサイトそのものをサーバーのプログラムとして起動します。このプログラムが動いている間だけサイトが表示されます。データベースは、この例ではサーバーのディスク上のSQLiteのファイル(./data/emdash.db)で、アップロードしたファイルは ./data/uploads に保存されます。
予約処理
組み込みのスケジューラーは、Node.jsのプロセスが動いている間だけ動作します。予約公開、プラグインのタスク、一般的なメンテナンスを処理します。
本番では、少なくとも1つのNode.jsのプロセスを常に動かしておきます。すべてのプロセスが停止またはスリープすると、予約処理は止まります。
やさしい解説
WordPressの予約投稿は、WP-Cronという仕組みで、サイトへのアクセスをきっかけに実行されます。EmDashを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"]
シードファイルはビルド時に読み込まれてバンドルに埋め込まれるため、実行用のイメージにコピーする必要はありません。マイグレーションはデプロイ後の最初のリクエストで実行されます。シードは、データベースにコレクションがなく、初期設定が完了していない場合にだけ適用されます。既存のデータが上書きされることはありません。
イメージをビルドし、コンテナを実行します。
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 # add the result to your environment
この値は運用者が用意するもので、データベースには保存されません。この値に依存する保存データはないため、現時点では値を失ってもデータの復旧に影響はありません。データベースとそのバックアップには平文のプラグインの秘密情報が含まれるため、機密情報として扱ってください。
省略可能:固定値による上書き
EmDashは、プレビューのHMACシークレットと、コメント投稿者のIPのハッシュに使うソルトを自動で生成し、最初に使うときにデータベースに保存します。次の環境変数を使うと、これらを自分で管理する値に固定できます。別のプロセスがメインのサイトとシークレットを共有する必要がある場合に役立ちます。
| 変数 | 説明 |
|---|---|
EMDASH_PREVIEW_SECRET |
自動生成されるプレビューのHMACシークレットを上書きします。 |
EMDASH_IP_SALT |
自動生成されるコメント投稿者のIPのハッシュのソルトを上書きします。 |
EMDASH_AUTH_SECRET |
省略可能です。設定されている場合、IPのソルトの元として使われます(EMDASH_IP_SALT も設定されている場合は、そちらが優先されます)。これにより、すでにこの値に依存しているインストールで、コメント投稿者のIPのハッシュが変わらないようにします。新しいデプロイでは設定しないでください。 |
キーの形式、対応しているすべてのシークレット、ローテーションや紛失の影響については、シークレットとキーの管理を参照してください。
データベースとストレージ
| 変数 | 説明 | 例 |
|---|---|---|
DATABASE_PATH |
SQLiteデータベースのパス | /data/emdash.db |
HOST |
サーバーのホスト | 0.0.0.0 |
PORT |
サーバーのポート | 4321 |
S3_ENDPOINT |
S3のエンドポイントのURL | https://xxx.r2.cloudflarestorage.com |
S3_BUCKET |
S3のバケット名 | my-media-bucket |
S3_ACCESS_KEY_ID |
S3のアクセスキー | AKIA... |
S3_SECRET_ACCESS_KEY |
S3のシークレットキー | ... |
S3_REGION |
S3のリージョン | auto |
S3_PUBLIC_URL |
メディアの公開URL | https://cdn.example.com |
やさしい解説
WordPressでは、データベースの接続情報を wp-config.php に書きます。EmDashをNode.jsで動かす場合は、こうした値をファイルに書かず、サーバーを起動するときの環境変数で渡します。上の表は、この環境変数の名前と意味の一覧です。パスワードやアクセスキーのような秘密の値は、Gitのリポジトリにも、Dockerのイメージにも含めないようにします。
永続的なストレージ
SQLiteには、永続的なディスクストレージが必要です。ホスティングサービスが次のものを提供していることを確認してください。
- マウントされたボリュームまたは永続ディスク
- データベースのディレクトリーへの書き込み権限
- データベースファイルのバックアップの仕組み
SQLiteのファイルとアップロード用のディレクトリーの両方をバックアップします。復旧時にどちらかを置き換える場合は、先にプロセスを停止します。バックアップと復旧を参照してください。
ヘルスチェック
ロードバランサー向けに、ヘルスチェック用のエンドポイントを追加します。
export const GET = () => {
return new Response("OK", { status: 200 });
};
このエンドポイントで分かるのは、Node.jsのプロセスがAstroのルートに応答できることです。データベース、ストレージのバックエンド、マイグレーションの状態、プラグインのサンドボックスが正常であることは分かりません。新しいリリースに通信を流す前に、これらの依存先を個別に確かめます。
通信を流す前に確かめる
新しいビルドを起動した後、本番のリクエストが使うのと同じ実行時のサービスを確かめます。
/healthと、コンテンツの公開ページを1つリクエストします。どちらも成功の応答を返す必要があります。- ビルドしたプロジェクトで
npx emdash migrate --checkを実行します。設定したデータベースについて、未適用のマイグレーションや不明なマイグレーションがないと報告される必要があります。 /_emdash/adminにサインインし、削除してよい下書きを作成または編集して、公開します。公開ページに変更が表示されることを確認します。- 削除してよいメディアファイルをアップロードし、返されたURLを開きます。確かめた後、そのファイルを削除します。
- サイトでサンドボックス型プラグインを使っている場合は、プラグインのルートまたはフックを1つ呼び出し、サーバーのログにサンドボックスが使えないというエラーや
workerdの起動エラーがないことを確認します。
該当するすべての確認に合格するまで、新しいインスタンスをロードバランサーに入れないでください。