Files
OTSSignsOrchestrator/deploy.sh
Matt Batchelder 9a35e40083 feat: Add initial deployment setup for OTSSignsOrchestrator
- Create index.html for the web application interface.
- Implement deploy.sh script for building and deploying the application to a Docker Swarm manager.
- Add docker-compose.yml for defining application and PostgreSQL service configurations.
2026-03-23 21:28:14 -04:00

81 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# deploy.sh — Build and deploy OTSSignsOrchestrator to a Docker Swarm manager over SSH
set -euo pipefail
# ── Configuration ─────────────────────────────────────────────────────────────
SWARM_HOST="${SWARM_HOST:-}" # e.g. user@10.0.0.1 or set via env
IMAGE_NAME="${IMAGE_NAME:-otssigns-orchestrator}"
IMAGE_TAG="${IMAGE_TAG:-latest}"
STACK_NAME="${STACK_NAME:-otssigns}"
COMPOSE_FILE="docker-compose.yml"
REMOTE_DIR="${REMOTE_DIR:-/opt/otssigns}"
ENV_FILE="${ENV_FILE:-.env}" # local .env file with secrets
# ── Validate ──────────────────────────────────────────────────────────────────
if [[ -z "$SWARM_HOST" ]]; then
echo "ERROR: SWARM_HOST is not set."
echo " Usage: SWARM_HOST=user@host ./deploy.sh"
echo " Or set SWARM_HOST in your environment."
exit 1
fi
if [[ ! -f "$COMPOSE_FILE" ]]; then
echo "ERROR: $COMPOSE_FILE not found. Run this script from the repository root."
exit 1
fi
FULL_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
echo "==> Deploying ${FULL_IMAGE} to swarm manager: ${SWARM_HOST}"
echo " Stack: ${STACK_NAME}"
echo " Remote dir: ${REMOTE_DIR}"
echo ""
# ── Step 1: Build the image locally ──────────────────────────────────────────
echo "==> [1/5] Building Docker image..."
docker build -t "${FULL_IMAGE}" .
# ── Step 2: Save and stream the image to the remote host ─────────────────────
echo "==> [2/5] Transferring image to ${SWARM_HOST}..."
docker save "${FULL_IMAGE}" | ssh "${SWARM_HOST}" "docker load"
# ── Step 3: Prepare the remote directory and upload compose file + env ────────
echo "==> [3/5] Uploading compose file and environment..."
ssh "${SWARM_HOST}" "mkdir -p ${REMOTE_DIR}"
scp "${COMPOSE_FILE}" "${SWARM_HOST}:${REMOTE_DIR}/docker-compose.yml"
if [[ -f "$ENV_FILE" ]]; then
scp "${ENV_FILE}" "${SWARM_HOST}:${REMOTE_DIR}/.env"
echo " Uploaded ${ENV_FILE} -> ${REMOTE_DIR}/.env"
else
echo " WARNING: No .env file found at '${ENV_FILE}'. Secrets must already exist on the remote host."
fi
# ── Step 4: Apply EF Core migrations before deploying the new stack ───────────
# The app runs migrations on startup (UseMigrationsEndPoint / MigrateAsync in Program.cs).
# If you need explicit pre-deploy migrations, uncomment the block below and
# ensure the remote host can reach PostgreSQL directly.
#
# echo "==> [3b] Running EF Core migrations..."
# ssh "${SWARM_HOST}" "docker run --rm --env-file ${REMOTE_DIR}/.env \
# -e ConnectionStrings__OrchestratorDb='...' \
# ${FULL_IMAGE} dotnet OTSSignsOrchestrator.dll --migrate-only"
# ── Step 5: Deploy the stack ──────────────────────────────────────────────────
echo "==> [4/5] Deploying stack '${STACK_NAME}'..."
ssh "${SWARM_HOST}" "cd ${REMOTE_DIR} && \
docker stack deploy \
--compose-file docker-compose.yml \
--with-registry-auth \
--prune \
${STACK_NAME}"
# ── Step 6: Verify rollout ────────────────────────────────────────────────────
echo "==> [5/5] Waiting for service to converge..."
ssh "${SWARM_HOST}" "docker service ls --filter name=${STACK_NAME}"
echo ""
echo "==> Deploy complete."
echo " Run the following to stream logs:"
echo " ssh ${SWARM_HOST} \"docker service logs -f ${STACK_NAME}_app\""