diff --git a/install.sh b/install.sh index 0b9993a..3105b5e 100644 --- a/install.sh +++ b/install.sh @@ -82,27 +82,89 @@ echo "" info "Checking prerequisites..." +# Detect package manager +install_pkg() { + if command -v apt-get &>/dev/null; then + sudo apt-get update -qq && sudo apt-get install -y -qq "$@" + elif command -v dnf &>/dev/null; then + sudo dnf install -y -q "$@" + elif command -v yum &>/dev/null; then + sudo yum install -y -q "$@" + elif command -v apk &>/dev/null; then + sudo apk add --quiet "$@" + else + fatal "Could not detect package manager. Install manually: $*" + fi +} + # Docker if command -v docker &>/dev/null; then DOCKER_VER=$(docker --version 2>/dev/null | head -1) success "Docker found: $DOCKER_VER" else - fatal "Docker is not installed. Install it from https://docs.docker.com/engine/install/" + warn "Docker is not installed." + echo -en "${CYAN}Install Docker now? [Y/n]:${NC} " + read -r install_docker + if [[ ! "$install_docker" =~ ^[Nn] ]]; then + info "Installing Docker via official install script..." + curl -fsSL https://get.docker.com | sudo sh + sudo systemctl enable --now docker 2>/dev/null || true + # Add current user to docker group so sudo isn't needed + if ! groups | grep -q docker; then + sudo usermod -aG docker "$USER" + warn "Added $USER to docker group. You may need to log out and back in." + warn "For now, the script will use sudo for docker commands." + # Use sudo for docker for the rest of this script + DOCKER_SUDO="sudo" + fi + success "Docker installed: $(docker --version 2>/dev/null || sudo docker --version 2>/dev/null)" + else + fatal "Docker is required. Install it from https://docs.docker.com/engine/install/" + fi fi +DOCKER_SUDO="${DOCKER_SUDO:-}" + # Docker Compose v2 -if docker compose version &>/dev/null; then - COMPOSE_VER=$(docker compose version 2>/dev/null | head -1) +if ${DOCKER_SUDO} docker compose version &>/dev/null; then + COMPOSE_VER=$(${DOCKER_SUDO} docker compose version 2>/dev/null | head -1) success "Docker Compose found: $COMPOSE_VER" else - fatal "Docker Compose v2 not found. Install it: https://docs.docker.com/compose/install/" + warn "Docker Compose v2 not found." + echo -en "${CYAN}Install Docker Compose plugin now? [Y/n]:${NC} " + read -r install_compose + if [[ ! "$install_compose" =~ ^[Nn] ]]; then + info "Installing Docker Compose plugin..." + if command -v apt-get &>/dev/null; then + sudo apt-get update -qq && sudo apt-get install -y -qq docker-compose-plugin + else + # Manual install for non-apt systems + COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep '"tag_name"' | head -1 | cut -d'"' -f4) + sudo mkdir -p /usr/local/lib/docker/cli-plugins + sudo curl -SL "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-linux-$(uname -m)" \ + -o /usr/local/lib/docker/cli-plugins/docker-compose + sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose + fi + success "Docker Compose installed: $(${DOCKER_SUDO} docker compose version 2>/dev/null)" + else + fatal "Docker Compose v2 is required. Install it: https://docs.docker.com/compose/install/" + fi fi # OpenSSL if command -v openssl &>/dev/null; then success "OpenSSL found" else - fatal "OpenSSL is not installed. Install it: apt install openssl" + warn "OpenSSL not found. Installing..." + install_pkg openssl + success "OpenSSL installed" +fi + +# curl (needed for health checks) +if ! command -v curl &>/dev/null; then + warn "curl not found. Installing..." + install_pkg curl + success "curl installed" fi # Compose file exists @@ -232,13 +294,13 @@ echo "" info "Building Docker images (this may take a few minutes on first run)..." echo "" -docker compose -f "$COMPOSE_FILE" build --no-cache +${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" build --no-cache echo "" info "Starting services..." echo "" -docker compose -f "$COMPOSE_FILE" up -d +${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" up -d # ─── Step 6: Health Check ─────────────────────────────────── @@ -251,11 +313,11 @@ INTERVAL=5 while [[ $ELAPSED -lt $MAX_WAIT ]]; do # Check database - DB_HEALTHY=$(docker compose -f "$COMPOSE_FILE" ps --format json 2>/dev/null | \ + DB_HEALTHY=$(${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" ps --format json 2>/dev/null | \ grep -o '"db"[^}]*"healthy"' 2>/dev/null && echo "yes" || echo "no") # Check app - APP_RUNNING=$(docker compose -f "$COMPOSE_FILE" ps --status running --format json 2>/dev/null | \ + APP_RUNNING=$(${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" ps --status running --format json 2>/dev/null | \ grep -o '"app"' 2>/dev/null && echo "yes" || echo "no") if [[ "$DB_HEALTHY" == *"yes"* ]] && [[ "$APP_RUNNING" == *"yes"* ]]; then @@ -273,7 +335,7 @@ echo "" SERVICES_UP=true for service in db minio app; do - STATUS=$(docker compose -f "$COMPOSE_FILE" ps "$service" --format "{{.Status}}" 2>/dev/null || echo "not found") + STATUS=$(${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" ps "$service" --format "{{.Status}}" 2>/dev/null || echo "not found") if echo "$STATUS" | grep -qi "up\|running\|healthy"; then success "$service: $STATUS" else @@ -283,17 +345,17 @@ for service in db minio app; do done # Check migrate completed -MIGRATE_STATUS=$(docker compose -f "$COMPOSE_FILE" ps migrate --format "{{.Status}}" 2>/dev/null || echo "not found") +MIGRATE_STATUS=$(${DOCKER_SUDO} docker compose -f "$COMPOSE_FILE" ps migrate --format "{{.Status}}" 2>/dev/null || echo "not found") if echo "$MIGRATE_STATUS" | grep -qi "exited (0)\|completed"; then success "migrate: completed successfully" else - warn "migrate: $MIGRATE_STATUS (check logs: docker compose -f $COMPOSE_FILE logs migrate)" + warn "migrate: $MIGRATE_STATUS (check logs: ${DOCKER_SUDO} docker compose -f $COMPOSE_FILE logs migrate)" fi if [[ "$SERVICES_UP" == "false" ]]; then echo "" error "Some services failed to start. Check logs:" - echo " docker compose -f $COMPOSE_FILE logs" + echo " ${DOCKER_SUDO} docker compose -f $COMPOSE_FILE logs" exit 1 fi