Nodevisor Docs
Examples

Docker Cluster

Deploy a production stack with Traefik, Postgres, and your Node.js app.

Overview

This recipe deploys a complete production stack using Docker Swarm:

  • Traefik as reverse proxy with automatic SSL via Let's Encrypt
  • Postgres as the database with persistent storage
  • Your Node.js app with automatic builds and rolling deployments

Cluster Definition

import {
  DockerCluster, DockerNode, ClusterUser,
  Traefik, Postgres, NodeWeb, DockerRegistry
} from 'nodevisor';

// Define the cluster
const cluster = new DockerCluster({
  name: 'production',
  nodes: [
    new DockerNode({ host: process.env.HOST! }),
  ],
  users: [
    new ClusterUser({
      username: 'root',
      privateKeyPath: '~/.ssh/id_ed25519',
    }),
  ],
  registry: new DockerRegistry({
    server: 'ghcr.io',
    username: process.env.REGISTRY_USER!,
    password: process.env.REGISTRY_TOKEN!,
  }),
});

// Reverse proxy with SSL
cluster.addDependency(new Traefik({
  ssl: {
    email: 'ops@example.com',
    redirect: true,
  },
  dashboard: {
    host: 'traefik.example.com',
    username: 'admin',
    password: process.env.TRAEFIK_PASSWORD_HASH!,
  },
}));

// Database
cluster.addDependency(new Postgres({
  database: 'myapp',
  username: 'myapp',
  password: process.env.POSTGRES_PASSWORD!,
}));

// Application
cluster.addDependency(new NodeWeb({
  name: 'api',
  appDir: './apps/api',
  tags: ['latest'],
  domains: ['api.example.com'],
  port: 3000,
  environment: {
    NODE_ENV: 'production',
    DATABASE_URL: `postgresql://myapp:${process.env.POSTGRES_PASSWORD}@postgres:5432/myapp`,
  },
}));

export default cluster;

Deploy

import cluster from './cluster';

// First time: setup servers (install Docker, firewall, users)
await cluster.setup();

// Build images, push to registry, deploy to all nodes
await cluster.deploy();

Run with the CLI:

nodevisor-cli setup .nodevisor/cluster.ts
nodevisor-cli deploy .nodevisor/cluster.ts

Generate Docker Compose YAML

You can inspect the generated configuration:

// Output the docker-compose.yml equivalent
console.log(cluster.yaml());

Local Development

Deploy locally using Docker Compose instead of Swarm:

await cluster.deployLocal();

Service Types

ServiceBase ClassDefault ImageDefault Port
TraefikWebProxytraefik:3.1.780, 443, 8080
PostgresPortDockerServicepostgres:17.55432
RedisPortDockerServiceredis:8.0.26379
NodeWebWebBuilt from source3000
NextjsWebBuilt from source3000
WhoamiWebtraefik/whoami80
WireGuardDockerServicelinuxserver/wireguard51820
SocatDockerServicealpine/socat

See the Docker package reference for full configuration options.

On this page