FerryDocs

Node.js

Ferry builds a Node.js app from package.json, with npm, Yarn, pnpm or Bun.

Edit on GitHub

Detect. Ferry finds package.json, bun.lock or bun.lockb.

1 / 5

A minimal example

package.json
package-lock.json
server.js
package.json
{
  "name": "hello-node",
  "private": true,
  "scripts": { "start": "node server.js" }
}
server.js
const http = require("http");

const port = Number(process.env.PORT || 3000);
http
  .createServer((req, res) => res.end("Hello from Node on Ferry\n"))
  .listen(port, "0.0.0.0", () => console.log(`listening on :${port}`));
Terminal
ferry up hello-node --follow

What Ferry generates

StepWhat Ferry generates
node:<major>-alpine. The default is 22. With engines.node in package.json, Ferry uses a major version that satisfies it: "20.x" gives node:20-alpine. Bun projects use oven/bun:1-alpine.
From the packageManager field. If there is none, from the : bun.lock/bun.lockb → Bun, pnpm-lock.yaml → pnpm, yarn.lock → Yarn. If there is none, npm. Yarn and pnpm run through Corepack.
BuildYour build command. If there is none: <package manager> run build, when package.json has a build script. Ferry sets NODE_ENV=production after the install. Thus the devDependencies are there for the build.
StartWith a start script: npm start (yarn start with Yarn 2+, bun run start with Bun). With no start script: node with the main file of package.json, server.js, index.js or app.js.

The install command

Package managerCommand
npm, with a lockfilenpm ci --include=dev
npm, with no lockfilenpm install --include=dev
Yarn 1yarn install --frozen-lockfile --production=false
Yarn 2+yarn install --immutable
pnpmpnpm install --frozen-lockfile
Bunbun install

On this page