FerryDocs
Get started

Quickstart

Start a server, deploy a small Node.js app, then change it, roll it back and clean up.

Edit on GitHub

You deploy examples/node-hello, a small Node.js from the Ferry repository. Ferry takes it from your disk. You need no git repository and no .

First, install Ferry. See Install Ferry. The output on this page comes from a real run. Ids, times and ports are different on your machine.

Start the server

If you used the install script, ferryd runs already and you created your account. Go to the next step.

If not, start the server.

Terminal
ferryd
Output
  Ferry 0.1.0 is running in the background (pid 48213)
  Dashboard + API : http://127.0.0.1:7878
  Dashboard (proxy): http://ferry.localhost:8080
  Apps            : http://<name>.localhost:8080
  …

  Create your account: http://127.0.0.1:7878/setup?code=5b0e…

Open the Create your account link in your browser. Enter your email and a password of 8 characters or more. Click Create account. You are now in the .

Log in with the CLI

Terminal
ferry login --server http://127.0.0.1:7878

The command opens a page in your browser and shows a code. Make sure that the page shows the code of your terminal. Then click Approve.

Output
Logged in to http://127.0.0.1:7878 (Ferry 0.1.0)
Saved to /home/you/.config/ferry/config.json

On a server with no browser, add --no-browser. Then open the URL on your computer, through the of the install script.

Deploy the app

Get the example. If you built Ferry from source, you have it already.

Terminal
git clone https://github.com/rogerbentcha/ferry
cd ferry/examples/node-hello

Run ferry up. It sends the current folder to the server and deploys it.

Terminal
$ 

--follow shows the until the app is live. The first deploy is slower: Docker downloads the node:22-alpine one time.

Open the URL of the last line.

Terminal
curl http://node-hello.localhost:8080
Output
Hello from Ferry (node)! service=node-hello deploy=dep-3493c505ea9b4415b359

Read the deploy log

The full log has more lines than the terminal above. These lines tell what Ferry did.

Line of the logWhat Ferry did
Created web service 'node-hello'ferry up created a with the name of the folder.
Detected Node.js runtimeFerry found the from package.json and wrote a Dockerfile.
Build successfulDocker built the .
Using port 10000 (default port)The app sets no port. Ferry gives it the default port in the variable PORT.
Limits: 512 MiB memory, 1 CPU per instanceThe default of each container
Health check passedThe port of the new accepts connections.
Routing traffic to the new instance(s)The sends the requests to the new instance.

To read the log again, run ferry logs --deploy dep-3493c505ea9b4415b359.

Look at the app

Terminal
ferry status node-hello
Output
node-hello: live — 1/1 instance(s) running
INSTANCE   DEPLOY     STATE     PORT    CPU            MEMORY                 RESTARTS   STARTED
82e2be     4415b359   running   62694   4.7% / 1 CPU   24.2 MiB / 512.0 MiB   0          8s ago
CommandShows
ferry servicesThe list of your services
ferry status node-helloEach instance, with its CPU and memory use next to its limits
ferry logs node-helloWhat the app writes. -f continues with the new lines.
ferry open node-helloThe URL. The command also tries to open it in your browser.

In the dashboard at http://127.0.0.1:7878, open node-hello. You do not need to sign in again.

Deploy a change

Edit the text in server.js.

server.js
res.end(`Hello from Ferry (node)! service=…`); 
res.end(`Hello again from Ferry! service=…`); 

Run the same command again.

Terminal
ferry up --follow
Output
09:36:41 ==> Health check passed
09:36:41 ==> Routing traffic to the new instance(s)
09:36:43 ==> Stopping 1 old instance(s)
09:36:43 ==> Your service is live 🎉

The service exists already. Thus ferry up only uploads and deploys. The old answered until the new container passed its . Then the proxy moved the traffic, and Ferry stopped the old container. This is a deploy with .

Roll back

Ferry keeps each deploy. List the deploys of the service.

Terminal
ferry deploys node-hello
Output
ID                         STATUS        TRIGGER   COMMIT   CREATED   DURATION
dep-ba5a7fce730d4061aaa7   live          upload    -        5s ago    1s
dep-3493c505ea9b4415b359   deactivated   upload    -        23s ago   2s

Copy the id of the first deploy, on the last line. Then roll back to it.

Terminal
ferry rollback node-hello dep-3493c505ea9b4415b359 --follow
Output
09:36:49 ==> Rolling back to deploy dep-3493c505ea9b4415b359 (deploy dep-16d99450e6984bb18843)
09:36:49 ==> Reusing image ferry/node-hello:dep-3493c505ea9b4415b359 of deploy dep-3493c505ea9b4415b359
…
09:36:53 ==> Your service is live 🎉

Ferry uses the image of that deploy again and builds nothing. A is a new deploy with the rollback. You can roll it back too.

If a deploy fails

Deploy with a start command that crashes.

Terminal
ferry up --start-cmd "node crash.js" --follow
Output
09:37:33 [d1c6b8] Error: Cannot find module '/app/crash.js'
…
09:37:34 ==> Removing 1 new instance(s)
09:37:34 ==> Deploy failed: instance d1c6b8 crashed (exit code 1)
Deploy dep-ca4bc7b5862742959b70 failed (deploy_failed): instance d1c6b8 crashed (exit code 1)

The command stops with 1. Ferry removes the new instance, and the previous deploy continues to answer. If an instance crashes during the health check, the log also shows the last 50 lines of its output.

To repair it, remove the setting and deploy again.

Terminal
ferry up --start-cmd "" --follow

Clean up

Terminal
ferry delete node-hello
ferryd stop
Output
Delete service 'node-hello' with all its deploys? [y/N] y
Deleted service 'node-hello'

Ferry deletes the service with its containers, its images and its deploy history. Add --yes to delete with no question. If systemd runs ferryd, stop it with sudo systemctl stop ferryd.

Deploy other things

ferry up works for each folder that Ferry can build. ferry create makes a service from a git or from an image.

Terminal
# A static site: nginx serves the folder as it is
ferry up my-site --dir ./public --type static

# A git repository, with 2 instances and an HTTP health check
ferry create api --repo https://github.com/you/api --branch main --instances 2 --health /healthz --follow

# A prebuilt image
ferry create hello --image nginx:alpine --port 80

# A cron job that runs each night at 03:00 UTC
ferry create nightly --type cron --image busybox:stable --schedule "0 3 * * *" --start-cmd 'echo hello'

See Deploy an app for the service types, the sources and the build settings.

On this page