Skip to content

Deployment Modes: Docker vs. Process

epd supports two distinct deployment runtimes configured via the top-level mode field: Docker and Process (PM2).

Both modes share the exact same blue/green zero-downtime guarantees, Traefik SSL routing, health checks, and instant rollbacks.


Quick Comparison

FeatureDocker Mode (mode: docker)Process Mode (mode: process)
Best ForMulti-language apps, containers, microservicesUltra-low RAM VPS, Bun/Node/Python apps
Server RequirementsDocker Engine installedNode.js/Bun, PM2, and rsync
Container OverheadMinimal (~20-40MB per container)Zero container overhead
Build LocationLocal machine or CI runnerRemote server (or pre-built artifact)
Image RegistryOptional (can stream over SSH)None needed
Process ManagerDocker Engine daemonPM2 process supervisor

1. Docker Mode (Default)

In Docker mode, your application is packaged as an OCI/Docker container image.

yaml
name: my-app
mode: docker
image: ghcr.io/my-org/my-app

servers:
  web:
    hosts: [203.0.113.10]
    port: 3000
    domains: [app.example.com]

How It Works:

  1. epd builds an image locally (using BuildKit / buildx) tagged with the current commit SHA.
  2. Registry or SSH Stream:
    • If registry: is specified, epd pushes the image to your registry (e.g. GitHub Packages or Docker Hub), and servers pull it.
    • If no registry is specified, epd streams the image directly to each server over SSH using docker save | gzip | ssh ... docker load.
  3. Containers run on a shared Docker bridge network (epd).
  4. Replicas communicate with Traefik using internal container names: http://epd-<app>-<service>-<slot>-<replica>:<port>

Custom Docker Build Configuration

yaml
build:
  dockerfile: docker/Dockerfile.prod
  context: .
  platform: linux/amd64
  args:
    NODE_ENV: production
    API_URL: https://api.example.com

2. Process Mode (No Docker on Server)

If you don't want or can't run Docker on your servers (for example, on a tiny 512MB or 1GB VPS), mode: process runs your code natively using PM2.

yaml
name: my-app
mode: process

process:
  install: bun install --frozen-lockfile
  build: bun run build
  start: bun run start
  exclude:
    - ".git"
    - "node_modules"
    - ".env"
    - "dist"
    - "*.log"

servers:
  web:
    hosts: [203.0.113.10]
    replicas: 2
    port: 3000
    domains: [app.example.com]

How It Works:

  1. epd uploads your code via rsync into /var/lib/epd/apps/<app>/releases/<version>/.
  2. Runs the install and build commands directly on the server.
  3. Starts each replica under pm2 with an assigned unique localhost port (e.g., 20101, 20102).
  4. Traefik (running as a native binary managed by PM2) automatically routes traffic from ports 80/443 to the healthy PM2 replica ports.

Runtime Examples

yaml
mode: process
process:
  install: bun install --frozen-lockfile
  build: bun run build
  start: bun run start
yaml
mode: process
process:
  install: npm ci --omit=dev
  build: npm run build
  start: npm run start
yaml
mode: process
process:
  install: pip install -r requirements.txt
  start: python -m uvicorn main:app --host 127.0.0.1 --port $PORT
yaml
mode: process
process:
  build: go build -o server .
  start: ./server

Next Steps

Released under the MIT License.