add initial Docker setup with .dockerignore, Dockerfile, docker-compose.yml, and deployment script
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
**/node_modules
|
||||||
|
server/data.db
|
||||||
|
server/data.db-wal
|
||||||
|
server/data.db-shm
|
||||||
|
**/*.log
|
||||||
|
agent
|
||||||
|
docs
|
||||||
|
*.bat
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# BizGaze Support — server secrets / config.
|
||||||
|
# Copy this file to `.env` next to docker-compose.yml on the server and fill in
|
||||||
|
# real values. The real `.env` is gitignored — NEVER commit credentials.
|
||||||
|
# Compose injects these into the container via `env_file:`.
|
||||||
|
|
||||||
|
# Managed TURN relay (Metered) — makes WebRTC work on mobile/cellular & strict NATs.
|
||||||
|
# Comma-separated URL list; username + credential from the Metered dashboard.
|
||||||
|
TURN_URLS=turn:global.relay.metered.ca:80,turn:global.relay.metered.ca:80?transport=tcp,turn:global.relay.metered.ca:443,turns:global.relay.metered.ca:443?transport=tcp
|
||||||
|
TURN_USERNAME=
|
||||||
|
TURN_CREDENTIAL=
|
||||||
|
|
||||||
|
# Optional: open self-registration of the first/any team (1 to enable).
|
||||||
|
# ALLOW_REGISTRATION=1
|
||||||
|
|
||||||
|
# Optional: shared secret for BizGaze SSO + signed webhook delivery.
|
||||||
|
# SSO_SECRET=
|
||||||
|
|
||||||
|
# Optional: BizGaze webhook endpoint for session events.
|
||||||
|
# BIZGAZE_WEBHOOK_URL=
|
||||||
@@ -19,6 +19,10 @@ npm-debug.log*
|
|||||||
# Environment files
|
# Environment files
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Deploy secrets (server password / host) — keep the .example tracked
|
||||||
|
deploy.config
|
||||||
|
|
||||||
# Build output
|
# Build output
|
||||||
dist/
|
dist/
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# BizGaze Support — server image
|
||||||
|
# Node 24 ships node:sqlite as a stable built-in (no flag), which db.js relies on.
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
WORKDIR /app/server
|
||||||
|
|
||||||
|
# Install deps first for layer caching (only `ws`, plus optional nodemailer)
|
||||||
|
COPY server/package*.json ./
|
||||||
|
RUN npm install --omit=dev --no-audit --no-fund
|
||||||
|
|
||||||
|
# App source
|
||||||
|
COPY server/ ./
|
||||||
|
|
||||||
|
# Served HTTP port (NPM terminates TLS and proxies here). DB lives on a volume.
|
||||||
|
ENV PORT=8090
|
||||||
|
ENV DB_PATH=/data/data.db
|
||||||
|
EXPOSE 8090
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# deploy.sh — run this ON THE SERVER, from inside the cloned repo
|
||||||
|
# (the app lives at /opt/bizgaze-support).
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1. Snapshots the current working tree (code + .env + certs, excluding .git)
|
||||||
|
# into a rotating backup, keeping the newest $KEEP_BACKUPS.
|
||||||
|
# 2. Pulls the latest commit of $GIT_BRANCH (git reset --hard, so the box
|
||||||
|
# always matches origin exactly).
|
||||||
|
# 3. Rebuilds the image and recreates the container. The named data volume
|
||||||
|
# (data.db) persists; the untracked .env / server/cert.pem / server/key.pem
|
||||||
|
# are gitignored and therefore preserved across every pull.
|
||||||
|
# 4. Verifies the app is serving.
|
||||||
|
#
|
||||||
|
# Usage (on the server):
|
||||||
|
# cd /opt/bizgaze-support
|
||||||
|
# ./deploy.sh # pull latest + rebuild
|
||||||
|
# ./deploy.sh --no-pull # rebuild current checkout (no git pull)
|
||||||
|
# ./deploy.sh --rollback # restore newest backup snapshot + rebuild
|
||||||
|
#
|
||||||
|
# Fire it from your laptop without logging in:
|
||||||
|
# plink -ssh -P 61 -pw '<pw>' root@118.95.33.89 \
|
||||||
|
# "cd /opt/bizgaze-support && ./deploy.sh"
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
GIT_BRANCH="${GIT_BRANCH:-master}"
|
||||||
|
KEEP_BACKUPS="${KEEP_BACKUPS:-3}"
|
||||||
|
CONTAINER="${CONTAINER:-bizgaze-support}"
|
||||||
|
|
||||||
|
cd "$(dirname "$(readlink -f "$0")")"
|
||||||
|
APP_DIR="$(pwd)"
|
||||||
|
BK_DIR="${APP_DIR}.backups"
|
||||||
|
|
||||||
|
log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
|
||||||
|
ok() { printf '\033[1;32m ✓\033[0m %s\n' "$*"; }
|
||||||
|
warn(){ printf '\033[1;33m ! %s\033[0m\n' "$*"; }
|
||||||
|
die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
[ -d .git ] || die "Not a git checkout. Run the one-time bootstrap first (see DEPLOY.md)."
|
||||||
|
command -v docker >/dev/null || die "docker not found on this host."
|
||||||
|
|
||||||
|
# --- args ---
|
||||||
|
DO_PULL=1; ROLLBACK=0
|
||||||
|
for a in "$@"; do case "$a" in
|
||||||
|
--no-pull) DO_PULL=0 ;;
|
||||||
|
--rollback) ROLLBACK=1 ;;
|
||||||
|
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||||
|
*) die "Unknown argument: $a" ;;
|
||||||
|
esac; done
|
||||||
|
|
||||||
|
snapshot() {
|
||||||
|
mkdir -p "$BK_DIR"
|
||||||
|
local ts rev
|
||||||
|
ts="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
rev="$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
|
||||||
|
log "Snapshot -> $BK_DIR/${ts}-${rev}.tgz"
|
||||||
|
tar --exclude=./.git --exclude=./node_modules \
|
||||||
|
--exclude=./server/node_modules -czf "$BK_DIR/${ts}-${rev}.tgz" -C "$APP_DIR" .
|
||||||
|
# rotate: keep newest $KEEP_BACKUPS
|
||||||
|
local old
|
||||||
|
old="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) || true)"
|
||||||
|
if [ -n "$old" ]; then
|
||||||
|
echo "Pruning old backups:"; echo "$old" | sed 's/^/ rm /'
|
||||||
|
echo "$old" | xargs -r rm -f
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild() {
|
||||||
|
[ -f .env ] || warn "No .env present — TURN/SSO secrets will be unset."
|
||||||
|
log "Rebuilding and recreating the container …"
|
||||||
|
docker compose config >/dev/null || die "docker-compose.yml is invalid."
|
||||||
|
docker compose up -d --build
|
||||||
|
docker compose ps
|
||||||
|
}
|
||||||
|
|
||||||
|
verify() {
|
||||||
|
log "Verifying /api/ice …"
|
||||||
|
if docker exec "$CONTAINER" wget -qO- http://localhost:8090/api/ice 2>/dev/null | grep -q iceServers; then
|
||||||
|
ok "App is serving."
|
||||||
|
else
|
||||||
|
warn "Could not confirm /api/ice — check: docker logs $CONTAINER"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- rollback mode ---
|
||||||
|
if [ "$ROLLBACK" -eq 1 ]; then
|
||||||
|
latest="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | head -n1 || true)"
|
||||||
|
[ -n "$latest" ] || die "No backups found in $BK_DIR"
|
||||||
|
log "Rolling back from: $latest"
|
||||||
|
snapshot # snapshot the (broken) current state first
|
||||||
|
tar -xzf "$latest" -C "$APP_DIR"
|
||||||
|
rebuild; verify
|
||||||
|
ok "Rolled back to $latest"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- normal deploy ---
|
||||||
|
snapshot
|
||||||
|
if [ "$DO_PULL" -eq 1 ]; then
|
||||||
|
log "Fetching origin/$GIT_BRANCH …"
|
||||||
|
git fetch origin "$GIT_BRANCH"
|
||||||
|
git reset --hard "origin/$GIT_BRANCH" # untracked .env / *.pem are preserved
|
||||||
|
ok "Now at $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)"
|
||||||
|
fi
|
||||||
|
rebuild
|
||||||
|
verify
|
||||||
|
ok "Deploy complete. Backups kept: $KEEP_BACKUPS (in $BK_DIR)."
|
||||||
|
echo " Rollback with: ./deploy.sh --rollback"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# BizGaze Support — deployed behind the existing Nginx Proxy Manager.
|
||||||
|
# No host ports are published: NPM reaches this container by name on the
|
||||||
|
# shared `nginx_proxy_manager_default` network. TLS is terminated by NPM,
|
||||||
|
# which proxies https://remote.bizgaze.com -> bizgaze-support:8090.
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
image: bizgaze-support:latest
|
||||||
|
container_name: bizgaze-support
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- PORT=8090
|
||||||
|
- DB_PATH=/data/data.db
|
||||||
|
# Secrets (TURN credentials, SSO_SECRET, BIZGAZE_WEBHOOK_URL, etc.) live in
|
||||||
|
# a .env file next to this compose file. It is gitignored — never committed.
|
||||||
|
# See .env.example for the expected keys.
|
||||||
|
env_file:
|
||||||
|
- path: .env
|
||||||
|
required: false
|
||||||
|
volumes:
|
||||||
|
- bizgaze_support_data:/data # persists data.db across rebuilds
|
||||||
|
networks:
|
||||||
|
- npm
|
||||||
|
|
||||||
|
networks:
|
||||||
|
npm:
|
||||||
|
external: true
|
||||||
|
name: nginx_proxy_manager_default
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
bizgaze_support_data:
|
||||||
Reference in New Issue
Block a user