portler
v0.4.1
Published
Process runner with automatic port assignment and env resolution, from local development to production.
Readme
Portler
Portler runs multi-service projects with automatic port assignment and environment resolution, on a dev machine, a CI runner, or a production host. It reads portler.yml, finds free ports, resolves references such as backend.url, and starts services in dependency order.
Documentation · Getting started · CLI reference · Configuration reference
Note: Portler is still evolving. The
portler.ymlformat is being improved and can change in breaking ways in upcoming releases, so check the release notes when you upgrade.
Install
Portler requires Node.js 22.6 or newer.
npm install -g portler
portler --helpPortler supports Linux and macOS. On Windows, use WSL2; native Windows is intentionally unsupported because safe process teardown relies on POSIX process groups. Docker and Kubernetes tooling are only required when using those modes.
Quick start
Generate a starter configuration and adapt it to your project:
portler initA portler.yml for a web app with a database looks like this:
proxy:
routes:
/api: backend
/: frontend
services:
postgres:
use: postgres@18 # built-in preset: image, port, volume, healthcheck
backend:
command: npm run dev
cwd: backend
setup:
- run: npm install
if_missing: node_modules
port: 4000
port_env: PORT
depends_on:
- postgres
env:
DATABASE_URL: ${postgres.database_url}
frontend:
command: npm run dev
cwd: frontend
setup:
- run: npm install
if_missing: node_modules
port: 3000
port_env: PORT
depends_on:
- backendStart and manage the stack:
portler up
portler up -d # run in the background
portler ps # show running services
portler logs backend --follow
portler downOn portler up:
- Every service gets a free host port, so this stack can run next to other projects and checkouts. Local processes receive it through
port_env. ${postgres.database_url}resolves to Postgres's assigned port, soDATABASE_URLalways points at the right place. Inportler up dockerthe sameDATABASE_URLbecomespostgres:5432, the address a container needs.- Postgres runs in Docker. Its data lives in the managed volume
@postgres-data, which survives restarts and can be forked for another checkout. npm installruns only whilenode_modulesis missing.- The backend starts once Postgres passes its healthcheck, and the frontend once the backend answers.
- The proxy serves the whole stack on one URL, printed as
project url./api/usersgoes tobackendwith the path unchanged, so the backend serves its routes under/api, and everything else goes tofrontend. The browser only talks to one origin, so CORS stops being a problem, and WebSockets work too, so dev-server hot reload keeps working.
Highlights
- Automatic ports — let multiple projects and checkouts run side by side.
- Service references — keep URLs and environment variables in sync.
- Dependency and health checks — control startup order.
- Docker and local Kubernetes — use the same configuration.
- Managed volumes — make it easy to fork local data between checkouts.
- Database presets —
use: postgres@18,[email protected]orredis@8, or a preset file of your own for any other database. - Reverse proxy — puts the stack behind one URL, so the browser only talks to one origin.
- Setup & production — install and build steps live next to the services and run once per checkout, while a path is missing, or every time;
portler startruns one service on a platform without Docker.
Portler verifies resource ownership before stopping processes or removing managed resources.
