Развертывание приложения Node.js (Express)
Чтобы разместить приложение Node.js на Lizard (lizard.build), разверните папку с package.json. По lock-файлу lizardpack выбирает менеджер пакетов, ставит зависимости, запускает скрипт build, если он есть, и стартует приложение скриптом start на порту 3000. Используется Node.js 22, если .nvmrc или engines.node не задают другую мажорную версию. Lizard передаёт порт в PORT; слушайте этот порт.
Статус тестов: пример на Express ниже запускался локально с Express 5.3.0, а маршрут к базе данных проверили с pg 8.23.1 и PostgreSQL 14. План сборки мы проверили в планировщике сборки lizardpack, который использует Lizard. Полный деплой по этому руководству мы ещё не проводили.
Перед началом
- Node.js и npm на вашем компьютере, чтобы создать lock-файл и проверить приложение локально.
- Lizard CLI с выполненным
lizard loginи тариф Pro или 7-дневный пробный период Pro (нужна карта). См. цены.
Для приложений на 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. |
| Сборка | Скрипт build, если он есть в package.json, на отдельном этапе, где установлены ваши devDependencies |
| Запуск | Скрипт start; иначе node <main>; иначе первый из server.js, index.js, app.js, main.js, dist/index.js |
| Рантайм | NODE_ENV=production, порт 3000 |
Без скрипта build образ задаёт NODE_ENV=production до установки пакетов, поэтому devDependencies не ставятся. Тогда скрипт start, который вызывает nodemon, tsx или ts-node из devDependencies, падает. Для TypeScript компилируйте код в build и запускайте результат:
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
}Файлы версий и их особые случаи описаны на странице версии рантайма. Оставьте команды сборки и запуска сервиса пустыми: если задана любая из них, Lizard пишет собственный Dockerfile на node:22-alpine и игнорирует ваши файлы версий. См. конвейер сборки.
Развертывание
Из корня приложения:
lizard init --name node-app
lizard add --service web
lizard up --service web --port 3000lizard up загружает папку, собирает её на Lizard и выводит URL. Внутри git-репозитория он пропускает всё, что перечислено в .gitignore; вне git пропускает node_modules, но загружает файлы .env. См. развертывание из локального кода.
Для git push to deploy отправьте репозиторий на GitHub и подключите его командой 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 передаёт отклонённый промис из маршрута своему обработчику ошибок, поэтому неудачный запрос возвращает 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. Запросите /healthz и /db по URL, который вывел lizard up.
Частые проблемы
| Симптом | Что делать |
|---|---|
npm ci падает, потому что lock-файл не совпадает с package.json | Выполните npm install локально и закоммитьте package-lock.json. |
nodemon: not found или tsx: not found | Эти инструменты лежат в devDependencies и для запуска не ставятся. Добавьте шаг build или перенесите инструмент в dependencies. |
| Деплой так и не становится работоспособным | Слушайте process.env.PORT. Жёстко заданный порт, например 5000, не совпадает с портом сервиса. См. сервис так и не становится работоспособным. |
| Не та версия Node.js | Укажите мажорную версию в .nvmrc, например 24, и разверните снова. |
Cannot use import statement outside a module | Добавьте "type": "module" в package.json или используйте require. |
Процесс Node.js, который не отдаёт HTTP, например потребитель очереди или Discord-бот, работает как фоновый обработчик.
См. также
Обновлено