118 lines
3.5 KiB
Bash
Executable File
118 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# ---------- logging helpers ----------
|
|
ts() { date +"%Y-%m-%d %H:%M:%S"; }
|
|
log() { echo "[$(ts)] [INFO] $*"; }
|
|
warn(){ echo "[$(ts)] [WARN] $*" >&2; }
|
|
err() { echo "[$(ts)] [ERROR] $*" >&2; }
|
|
die() { err "$*"; exit 1; }
|
|
|
|
dump_diag() {
|
|
warn "Diagnostics:"
|
|
docker compose ps || true
|
|
echo
|
|
warn "docker ps (name=mssql2025):"
|
|
docker ps --filter "name=mssql2025" || true
|
|
echo
|
|
warn "Last 250 lines of container logs (mssql2025):"
|
|
docker logs --tail=250 mssql2025 2>/dev/null || warn "No logs available."
|
|
}
|
|
|
|
on_error() {
|
|
local exit_code=$?
|
|
err "Start failed (exit code=$exit_code)."
|
|
dump_diag
|
|
exit "$exit_code"
|
|
}
|
|
trap on_error ERR
|
|
|
|
# ---------- go to repo root ----------
|
|
cd "$(dirname "$0")/.."
|
|
|
|
# ---------- preflight ----------
|
|
command -v docker >/dev/null 2>&1 || die "docker is not installed or not in PATH."
|
|
docker info >/dev/null 2>&1 || die "docker daemon not reachable. Start docker service (sudo systemctl start docker)."
|
|
|
|
[[ -f .env ]] || die "Missing .env. Create it first: cp .env.example .env (then edit MSSQL_SA_PASSWORD)."
|
|
|
|
# Load .env
|
|
set -a
|
|
# shellcheck disable=SC1091
|
|
source .env
|
|
set +a
|
|
|
|
[[ -n "${MSSQL_SA_PASSWORD:-}" ]] || die "MSSQL_SA_PASSWORD is empty in .env"
|
|
|
|
# Validate MSSQL_PID for SQL Server 2025 containers
|
|
case "${MSSQL_PID:-Developer}" in
|
|
"Enterprise Developer"|"EnterpriseDeveloper"|"Enterprise_Developer")
|
|
cat >&2 <<'EOF'
|
|
[ERROR] MSSQL_PID is set to "Enterprise Developer", which SQL Server 2025 containers reject.
|
|
Fix: edit .env and set:
|
|
MSSQL_PID=Developer
|
|
(or: DeveloperStandard)
|
|
EOF
|
|
exit 2
|
|
;;
|
|
Developer|DeveloperStandard|Express|Evaluation|Standard|Enterprise)
|
|
;;
|
|
*)
|
|
warn "MSSQL_PID='${MSSQL_PID}' is unusual. If SQL Server errors about PID format, set MSSQL_PID=Developer."
|
|
;;
|
|
esac
|
|
|
|
log "Hard-resetting previous instance (if any)..."
|
|
# Bring down compose stack (remove orphans), but do NOT delete volumes because we use bind mounts (./data)
|
|
docker compose down --remove-orphans >/dev/null 2>&1 || true
|
|
|
|
# If there is a stray container with same name, kill it too (outside compose)
|
|
if docker ps -a --format '{{.Names}}' | grep -qx 'mssql2025'; then
|
|
warn "Found stray container named mssql2025; removing it..."
|
|
docker rm -f mssql2025 >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
log "Starting fresh container..."
|
|
log "Settings: port=${MSSQL_PORT:-1433}, pid=${MSSQL_PID:-Developer}, cpuset=0-7, cpus=8.0"
|
|
|
|
# Ensure image is present (optional but nice)
|
|
docker compose pull >/dev/null 2>&1 || true
|
|
|
|
# Force recreate every time to avoid “stuck” states
|
|
docker compose up -d --force-recreate --remove-orphans
|
|
|
|
# ---------- wait for healthy ----------
|
|
log "Waiting for container healthcheck to become healthy..."
|
|
max_seconds=180
|
|
sleep_step=2
|
|
elapsed=0
|
|
|
|
while (( elapsed < max_seconds )); do
|
|
state="$(docker inspect -f '{{.State.Status}}' mssql2025 2>/dev/null || true)"
|
|
health="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}no-healthcheck{{end}}' mssql2025 2>/dev/null || true)"
|
|
|
|
printf "\r[%s] state=%-10s health=%-12s elapsed=%3ss/%ss" "$(ts)" "${state:-unknown}" "${health:-unknown}" "$elapsed" "$max_seconds"
|
|
|
|
if [[ "$health" == "healthy" ]]; then
|
|
echo
|
|
log "SQL Server is healthy ✅"
|
|
log "Connect: localhost,${MSSQL_PORT:-1433} (user: sa)"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$state" == "exited" ]]; then
|
|
echo
|
|
err "Container exited before becoming healthy."
|
|
dump_diag
|
|
exit 1
|
|
fi
|
|
|
|
sleep "$sleep_step"
|
|
elapsed=$((elapsed + sleep_step))
|
|
done
|
|
|
|
echo
|
|
err "Timed out waiting for SQL Server to become healthy (${max_seconds}s)."
|
|
dump_diag
|
|
exit 1
|