#!/bin/bash # Fast deploy — BuildKit cache + persistent build dir # Source-only changes: ~40-60s | With package changes: ~90s set -e SERVER=root@159.195.60.33 CONTAINER=qc-server-new START=$(date +%s) step() { printf "\n\033[1;34m>>>\033[0m [%s] %s\n" "$1" "$2"; } # ── Pack source (exclude heavy/unchanged stuff) ── step "1/3" "Packing source..." tar czf /tmp/pnpl.tar.gz \ --exclude=node_modules \ --exclude=.next \ --exclude=.git \ --exclude=brand/ \ --exclude=shots/ \ . SIZE=$(wc -c < /tmp/pnpl.tar.gz | awk '{printf "%.1fM", $1/1048576}') echo " ${SIZE} tarball" # ── Upload ── step "2/3" "Uploading..." scp -o ConnectTimeout=20 -q /tmp/pnpl.tar.gz ${SERVER}:/tmp/pnpl.tar.gz # ── Build + deploy with full cache ── step "3/3" "Building + deploying..." ssh -o ConnectTimeout=20 ${SERVER} " incus file push /tmp/pnpl.tar.gz ${CONTAINER}/tmp/pnpl.tar.gz incus exec ${CONTAINER} -- bash -c ' cd /opt/pnpl tar xzf /tmp/pnpl.tar.gz rm /tmp/pnpl.tar.gz # BuildKit build with npm + Next.js cache mounts docker buildx build -t pnpl-app:latest --load . 2>&1 | tail -8 # Restart via docker compose (matches Dokploy) cd /etc/dokploy/compose/pnpl/code docker compose -p pnpl up -d --force-recreate app 2>&1 | tail -4 # Clean dangling only (preserve build cache!) docker image prune -f 2>&1 | tail -1 ' rm -f /tmp/pnpl.tar.gz " ELAPSED=$(( $(date +%s) - START )) echo "" echo "=== Deployed in ${ELAPSED}s ==="