- 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.
81 lines
3.8 KiB
Bash
Executable File
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\""
|