Sql_Injection/deploy.sh
2025-11-27 11:25:53 +05:30

321 lines
11 KiB
Bash

#!/usr/bin/env bash
# deploy.sh - quickstart with Docker MySQL + backend + frontend
# Usage: ./deploy.sh
set -euo pipefail
# ---------- CONFIG ----------
ROOT_DIR="$(pwd)"
BACKEND_DIR="backend"
FRONTEND_DIR="frontend"
BACKEND_LOG="backend.log"
FRONTEND_LOG="frontend.log"
VENV_DIR_ABS="$ROOT_DIR/$BACKEND_DIR/.venv"
MYSQL_CONTAINER="sqlilab_mysql"
MYSQL_PORT=3307
MYSQL_ROOT_PASSWORD="12345"
MYSQL_DATABASE="sqlilab"
PYTHON_BIN="python3"
PIP_BIN=""
DOCKER_CMD=""
# ----------------------------
timestamp(){ date +"%Y-%m-%d %H:%M:%S"; }
info(){ echo -e "$(timestamp) [INFO] $*"; }
fail(){ echo -e "$(timestamp) [ERROR] $*" >&2; exit 1; }
warn(){ echo -e "$(timestamp) [WARN] $*"; }
run_quiet(){ "$@" >/dev/null 2>&1 || true; }
# ---------- Docker helpers (unchanged) ----------
check_docker(){
if ! command -v docker >/dev/null 2>&1; then
return 1
fi
if docker info >/dev/null 2>&1; then
DOCKER_CMD="docker"
info "Docker CLI usable without sudo."
return 0
fi
if sudo docker info >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
info "Docker CLI usable with sudo."
return 0
fi
return 1
}
start_docker_daemon(){
info "Attempting to start Docker daemon..."
if command -v systemctl >/dev/null 2>&1; then
run_quiet sudo systemctl daemon-reload
run_quiet sudo systemctl enable docker || warn "systemctl enable returned non-zero"
run_quiet sudo systemctl start docker || warn "systemctl start returned non-zero"
for i in {1..30}; do
if sudo docker info >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
info "Docker daemon ready (systemd)."
return 0
fi
sleep 1
done
warn "Docker did not become ready via systemctl in 30s."
else
warn "systemctl not found; trying dockerd fallback."
fi
if command -v dockerd >/dev/null 2>&1; then
if ! pgrep -x dockerd >/dev/null 2>&1; then
sudo dockerd >> /var/log/docker-dockerd.log 2>&1 & disown || warn "Failed to start dockerd"
info "Started dockerd in background (logs -> /var/log/docker-dockerd.log)"
else
warn "dockerd already running"
fi
for i in {1..30}; do
if sudo docker info >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
info "Docker ready (dockerd fallback)."
return 0
fi
sleep 1
done
fi
return 1
}
ensure_docker_ready(){
if check_docker; then return 0; fi
warn "Docker CLI/daemon not usable; attempting to start daemon..."
if start_docker_daemon && check_docker; then return 0; fi
return 1
}
# ---------- Python / Node / pip checks ----------
info "Checking python & pip..."
if command -v python3 >/dev/null 2>&1; then
PYTHON_BIN="python3"
else
fail "python3 not found. Install Python 3."
fi
if command -v pip3 >/dev/null 2>&1; then
PIP_BIN="pip3"
elif command -v pip >/dev/null 2>&1; then
PIP_BIN="pip"
else
info "Installing python3-pip..."
sudo apt update -y
sudo apt install -y python3-pip
PIP_BIN="pip3"
fi
# info "Checking Node.js & npm..."
# if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then
# info "Installing Node.js (LTS)..."
# sudo apt update -y
# sudo apt install -y ca-certificates curl gnupg
# sudo mkdir -p /etc/apt/keyrings
# curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
# NODE_MAJOR=20
# echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
# sudo apt update -y
# sudo apt install -y nodejs
# fi
# ---------- helper to start background processes ----------
start_bg(){
local cmd="$1"; local logfile="$2"; local pidfile="$3"
nohup bash -lc "$cmd" >>"$logfile" 2>&1 &
local pid=$!
echo "$pid" > "$pidfile"
info "Started: '$cmd' (pid=$pid) -> $logfile"
}
# ---------- sanity checks ----------
[ -d "$BACKEND_DIR" ] || fail "Backend directory '$BACKEND_DIR' not found."
# [ -d "$FRONTEND_DIR" ] || fail "Frontend directory '$FRONTEND_DIR' not found."
[ -f "$BACKEND_DIR/init.sql" ] || fail "BACKEND_DIR/init.sql not found. Please create $BACKEND_DIR/init.sql"
# ---------- Install Docker (if missing) ----------
info "Checking Docker installation..."
DOCKER_WAS_INSTALLED=false
if ! command -v docker >/dev/null 2>&1; then
info "Docker not found. Installing Docker..."
DOCKER_WAS_INSTALLED=true
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER" || warn "usermod returned non-zero"
info "Docker installation completed."
fi
if ! ensure_docker_ready; then
if [ "$DOCKER_WAS_INSTALLED" = true ]; then
fail "Docker daemon not running after install. Check: sudo systemctl status docker and logs."
else
fail "Docker is installed but not usable. Try: sudo systemctl start docker"
fi
fi
info "Docker ready. Using command: $DOCKER_CMD"
if [ "$DOCKER_CMD" = "sudo docker" ]; then
warn "docker requires sudo in this shell. Run: newgrp docker OR log out/in to use docker without sudo."
fi
# ---------- DOCKER MYSQL SETUP ----------
info "Setting up MySQL Docker container..."
if $DOCKER_CMD ps -a --format '{{.Names}}' | grep -q "^${MYSQL_CONTAINER}$"; then
info "Removing existing MySQL container..."
$DOCKER_CMD stop "$MYSQL_CONTAINER" 2>/dev/null || true
$DOCKER_CMD rm "$MYSQL_CONTAINER" 2>/dev/null || true
fi
info "Pulling MySQL 8.0 image..."
$DOCKER_CMD pull mysql:8.0
info "Starting MySQL container..."
$DOCKER_CMD run -d \
--name "$MYSQL_CONTAINER" \
-e MYSQL_ROOT_PASSWORD="$MYSQL_ROOT_PASSWORD" \
-e MYSQL_DATABASE="$MYSQL_DATABASE" \
-e MYSQL_ROOT_HOST='%' \
-p "$MYSQL_PORT:3306" \
-v "$ROOT_DIR/$BACKEND_DIR/init.sql:/docker-entrypoint-initdb.d/init.sql:ro" \
mysql:8.0 \
--default-authentication-plugin=mysql_native_password
info "Waiting for MySQL to be ready..."
for i in {1..60}; do
if $DOCKER_CMD exec "$MYSQL_CONTAINER" mysqladmin ping -h localhost -uroot -p"$MYSQL_ROOT_PASSWORD" >/dev/null 2>&1; then
info "MySQL ready."
break
fi
sleep 1
if [ "$i" -eq 60 ]; then
fail "MySQL failed to start. Check logs: $DOCKER_CMD logs $MYSQL_CONTAINER"
fi
done
sleep 3
# ---------- BACKEND PREP: ensure python3-venv installed, create venv, install requirements & gunicorn ----------
info "Preparing backend virtualenv and dependencies..."
info "Ensuring python3-venv and pip are installed..."
sudo apt update -y
sudo apt install -y python3-venv python3-pip
# create venv if missing (use absolute path)
if [ ! -d "$VENV_DIR_ABS" ]; then
info "Creating virtualenv at $VENV_DIR_ABS"
$PYTHON_BIN -m venv "$VENV_DIR_ABS" || fail "Failed to create virtualenv at $VENV_DIR_ABS"
fi
# Activate and install requirements inside venv
# shellcheck source=/dev/null
. "$VENV_DIR_ABS/bin/activate" || fail "Failed to activate virtualenv at $VENV_DIR_ABS"
info "Upgrading pip & installing backend requirements..."
pip install --upgrade pip setuptools wheel >/dev/null
if [ -f "$ROOT_DIR/$BACKEND_DIR/requirements.txt" ]; then
pip install -r "$ROOT_DIR/$BACKEND_DIR/requirements.txt" || warn "pip install -r returned non-zero"
else
warn "requirements.txt not found in $BACKEND_DIR"
fi
info "Installing gunicorn..."
pip install --upgrade gunicorn >/dev/null || warn "pip install gunicorn returned non-zero"
deactivate || true
# compute gunicorn binary absolute path and verify
GUNICORN_BIN="$VENV_DIR_ABS/bin/gunicorn"
if [ ! -x "$GUNICORN_BIN" ]; then
fail "gunicorn binary not found at $GUNICORN_BIN (venv may be broken)"
fi
# ---------- DETECT app.py location and set APP_MODULE ----------
# prefer backend/app.py, fallback to backend/backend/app.py
if [ -f "$ROOT_DIR/$BACKEND_DIR/app.py" ]; then
APP_MODULE="backend.app:app"
START_CWD="$ROOT_DIR"
elif [ -f "$ROOT_DIR/$BACKEND_DIR/backend/app.py" ]; then
APP_MODULE="backend.backend.app:app"
START_CWD="$ROOT_DIR"
else
# if neither exists, fail early with helpful message
fail "Could not find app.py under $BACKEND_DIR. Please ensure backend/app.py exists."
fi
info "Using APP_MODULE=$APP_MODULE"
# ---------- START BACKEND (Flask dev server, no Gunicorn) ----------
info "Starting backend with Flask development server (no Gunicorn)..."
BACKEND_APP="app.py" # your backend/app.py
if sudo ss -ltnp 2>/dev/null | grep -q ':5000'; then
warn "Port 5000 already in use; skipping backend start."
else
BACKEND_CMD="bash -lc 'cd \"$ROOT_DIR/$BACKEND_DIR\" && \
source \"$VENV_DIR_ABS/bin/activate\" && \
FLASK_APP=$BACKEND_APP FLASK_ENV=development flask run --host=0.0.0.0 --port=5000'"
BACKEND_PIDFILE="$ROOT_DIR/backend.pid"
start_bg "$BACKEND_CMD" "$ROOT_DIR/$BACKEND_LOG" "$BACKEND_PIDFILE"
fi
# # ---------- FRONTEND ----------
# info "Starting frontend..."
# if [ -f "$ROOT_DIR/$FRONTEND_DIR/package.json" ]; then
# cd "$ROOT_DIR/$FRONTEND_DIR"
# if [[ "$(pwd)" == /mnt/* ]]; then
# info "Detected WSL/Windows FS. Cleaning node_modules..."
# rm -rf node_modules package-lock.json
# npm install
# else
# if [ -f "package-lock.json" ]; then
# if ! npm ci; then
# rm -rf node_modules
# npm install
# fi
# else
# npm install
# fi
# fi
# FRONTEND_START_CMD=${FRONTEND_START_CMD:-"npm run dev"}
# FRONTEND_PIDFILE="$ROOT_DIR/frontend.pid"
# start_bg "$FRONTEND_START_CMD" "$ROOT_DIR/$FRONTEND_LOG" "$FRONTEND_PIDFILE"
# cd "$ROOT_DIR"
# else
# warn "No package.json in frontend/ — skipping frontend start."
# fi
# ---------- FINISH ----------
echo ""
echo "========================================="
echo "🚀 Application Started (or attempted)!"
echo "========================================="
echo "$(timestamp) MySQL (Docker) → localhost:$MYSQL_PORT"
echo " Container: $MYSQL_CONTAINER"
echo " Database: $MYSQL_DATABASE"
echo ""
echo "$(timestamp) Backend → http://localhost:5000"
echo " Log: $BACKEND_LOG"
echo " PID: $(cat backend.pid 2>/dev/null || echo 'N/A')"
echo ""
# echo "$(timestamp) Frontend → http://localhost:5173"
# echo " Log: $FRONTEND_LOG"
# echo " PID: $(cat frontend.pid 2>/dev/null || echo 'N/A')"
echo "========================================="
echo ""
echo "Useful commands:"
echo " tail -f $BACKEND_LOG"
# echo " tail -f $FRONTEND_LOG"
echo " $DOCKER_CMD logs -f $MYSQL_CONTAINER"
echo " $DOCKER_CMD exec -it $MYSQL_CONTAINER mysql -uroot -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE"
echo " kill \$(cat backend.pid 2>/dev/null || echo '') && kill \$(cat frontend.pid 2>/dev/null || echo '') && $DOCKER_CMD stop $MYSQL_CONTAINER"
echo "========================================="