Node.js アプリをデプロイする(Express)

Lizard (lizard.build) で Node.js アプリをホストするには、package.json を含むフォルダーをデプロイします。lizardpack は lock ファイルからパッケージマネージャーを選び、依存関係をインストールし、build スクリプトがあれば実行して、start スクリプトでアプリをポート 3000 で起動します。.nvmrc や engines.node で別のメジャーバージョンを指定しない限り、Node.js 22 を使います。Lizard はポートを PORT で渡すので、そのポートで待ち受けてください。

テスト状況: 以下の Express サンプルは Express 5.3.0 を使ってローカルで動作し、データベースのルートは pg 8.23.1 を使って PostgreSQL 14 に対して動作しました。ビルドプランは、Lizard が使う lizardpack で確認しました。このガイドのデプロイ手順は、まだ最初から最後まで試していません。

始める前に

  • lock ファイルの作成とローカルでのテストに使う、手元のコンピューターの Node.js と npm。
  • lizard login でサインイン済みで、Pro または 7 日間の Pro トライアル(カードが必要)を利用している Lizard CLI。料金を参照してください。

Next.js、Nuxt、Astro、SvelteKit、Vite のアプリには専用のガイドがあります。フレームワークガイドを参照してください。

最小構成の Express アプリ

package.json:

{
  "name": "express-app",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "node server.js"
  },
  "engines": {
    "node": "22.x"
  },
  "dependencies": {
    "express": "^5.1.0"
  }
}

server.js:

import express from "express";
 
const app = express();
const port = Number(process.env.PORT) || 3000;
 
app.get("/", (req, res) => {
  res.send("Hello from Express on Lizard");
});
 
app.get("/healthz", (req, res) => {
  res.json({ status: "ok" });
});
 
app.listen(port, "0.0.0.0", () => {
  console.log(`listening on ${port}`);
});

npm install を実行して package-lock.json を作成し、両方のファイルをコミットして、node_modules と .env を .gitignore に追加します。ローカルで確認します:

npm start
curl http://localhost:3000/healthz

lizardpack が Node.js アプリに対して行うこと

ステップ内容
パッケージマネージャーbun.lock または bun.lockb: Bun。pnpm-lock.yaml: pnpm。yarn.lock: Yarn。package-lock.json: npm ci。lock ファイルなし: npm install。
Node.js のバージョン.nvmrc、次に .node-version、次に .tool-versions、次に engines.node。使われるのはメジャーバージョンだけで、node:<major>-slim 上でビルドされます。デフォルトは 22。
ビルドpackage.json に build スクリプトがあれば、devDependencies を含む別のステージで実行
起動start スクリプト。なければ node <main>。それもなければ server.js、index.js、app.js、main.js、dist/index.js のうち最初に見つかったもの
ランタイムNODE_ENV=production、ポート 3000

build スクリプトがない場合、イメージはパッケージをインストールする前に NODE_ENV=production を設定するため、devDependencies はインストールされません。そのため、devDependencies にある nodemon、tsx、ts-node を呼び出す start スクリプトは失敗します。TypeScript では、build でコンパイルし、その出力を起動してください:

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

バージョンファイルと注意点は ランタイムバージョン で説明しています。サービスのビルドコマンドと起動コマンドは空のままにしてください。どちらかが設定されていると、Lizard は node:22-alpine をベースに独自の Dockerfile を生成し、バージョンファイルを無視します。ビルドパイプラインを参照してください。

デプロイ

アプリのルートから実行します:

lizard init --name node-app
lizard add --service web
lizard up --service web --port 3000

lizard up はフォルダーをアップロードし、Lizard 上でビルドして URL を表示します。git リポジトリ内では .gitignore に書かれたものをスキップします。git の外では node_modules はスキップしますが、.env ファイルはアップロードします。ローカルコードからデプロイするを参照してください。

git push to deploy を使う場合は、リポジトリを GitHub に push し、lizard add -r your-org/your-app -n web で接続します。GitHub からデプロイするを参照してください。

変数を設定する

lizard secrets set SESSION_SECRET="$(openssl rand -hex 32)" --service web

値は process.env.SESSION_SECRET で読み取ります。変数を変更すると、再ビルドなしでサービスが再起動します。変数とシークレットを参照してください。

Managed Postgres を追加する

lizard add postgres
lizard secrets set DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' --service web
npm install pg

シングルクォートで囲むと、シェルは ${{…}} を解釈しません。Lizard はデプロイ時に 参照 を、プロジェクトのプライベートネットワーク上のデータベースのアドレスに解決します。server.js にプールとルートを追加します:

import pg from "pg";
 
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
 
app.get("/db", async (req, res) => {
  const { rows } = await pool.query("SELECT now() AS now");
  res.json(rows[0]);
});

Express 5 はルートで reject された promise をエラーハンドラーに渡すため、クエリが失敗してもプロセスはクラッシュせず、HTTP 500 を返します。マイグレーションは、データベースのパブリック URL を使って手元のコンピューターから実行します:

lizard run --service postgres -- npm run migrate

キャッシュやジョブキューには、同じ方法で Managed Redis を追加します。lizard add redis を実行してから、REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' を設定してください。

動作を確認する

lizard logs --build --service web
lizard logs --service web --tail 100
lizard ps

ランタイムログには listening on 3000 が表示されます。lizard up が表示した URL で /healthz と /db をリクエストしてください。

よくある問題

症状対処
lock ファイルが同期していないため npm ci が失敗するローカルで npm install を実行し、package-lock.json をコミットします。
nodemon: not found または tsx: not foundこれらのツールは devDependencies なので、起動用にはインストールされません。build ステップを追加するか、ツールを dependencies に移します。
デプロイがいつまでも healthy にならないprocess.env.PORT で待ち受けてください。5000 のような固定ポートはサービスポートと一致しません。サービスが healthy にならないを参照してください。
Node.js のバージョンが違う.nvmrc にメジャーバージョン(例: 24)を書き、もう一度デプロイします。
Cannot use import statement outside a modulepackage.json に "type": "module" を追加するか、require を使います。

キューコンシューマーや Discord bot のように HTTP を提供しない Node.js プロセスは、バックグラウンドワーカー として実行します。

関連項目

更新日