305 lines
8.0 KiB
Bash
305 lines
8.0 KiB
Bash
#!/bin/bash
|
|
#
|
|
# IT0 Web Admin - Deployment Script
|
|
# ==================================
|
|
#
|
|
# Usage:
|
|
# ./deploy.sh build - Build Docker image
|
|
# ./deploy.sh start - Build and start service
|
|
# ./deploy.sh stop - Stop service
|
|
# ./deploy.sh restart - Restart service
|
|
# ./deploy.sh logs - View logs
|
|
# ./deploy.sh status - Show service status
|
|
# ./deploy.sh clean - Clean containers and images
|
|
#
|
|
|
|
set -e
|
|
|
|
# ===========================================================================
|
|
# Configuration
|
|
# ===========================================================================
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
PROJECT_NAME="it0-web-admin"
|
|
IMAGE_NAME="it0-web-admin"
|
|
CONTAINER_NAME="it0-web-admin"
|
|
DEFAULT_PORT=3000
|
|
|
|
# API Configuration
|
|
API_DOMAIN="${API_DOMAIN:-it0api.szaiai.com}"
|
|
API_BASE_URL="${API_BASE_URL:-https://${API_DOMAIN}}"
|
|
WS_URL="${WS_URL:-wss://${API_DOMAIN}}"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# ===========================================================================
|
|
# Docker Check
|
|
# ===========================================================================
|
|
|
|
check_docker() {
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker is not installed. Please install Docker first."
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker info &> /dev/null; then
|
|
log_error "Docker service is not running. Please start Docker."
|
|
exit 1
|
|
fi
|
|
|
|
if docker compose version &> /dev/null; then
|
|
COMPOSE_CMD="docker compose"
|
|
elif command -v docker-compose &> /dev/null; then
|
|
COMPOSE_CMD="docker-compose"
|
|
else
|
|
log_error "Docker Compose is not installed."
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Docker check passed"
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Ensure docker-compose.yml exists
|
|
# ===========================================================================
|
|
|
|
ensure_compose_file() {
|
|
if [ ! -f "$SCRIPT_DIR/docker-compose.yml" ]; then
|
|
log_info "Creating docker-compose.yml..."
|
|
cat > "$SCRIPT_DIR/docker-compose.yml" << EOF
|
|
version: '3.8'
|
|
|
|
services:
|
|
web-admin:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
container_name: ${CONTAINER_NAME}
|
|
ports:
|
|
- "\${PORT:-${DEFAULT_PORT}}:3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- NEXT_PUBLIC_API_BASE_URL=${API_BASE_URL}
|
|
- NEXT_PUBLIC_WS_URL=${WS_URL}
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
EOF
|
|
log_success "docker-compose.yml created"
|
|
fi
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Ensure Dockerfile exists
|
|
# ===========================================================================
|
|
|
|
ensure_dockerfile() {
|
|
if [ ! -f "$SCRIPT_DIR/Dockerfile" ]; then
|
|
log_info "Creating Dockerfile..."
|
|
cat > "$SCRIPT_DIR/Dockerfile" << 'EOF'
|
|
# Stage 1: Dependencies
|
|
FROM node:20-alpine AS deps
|
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
WORKDIR /app
|
|
COPY package.json pnpm-lock.yaml* ./
|
|
RUN pnpm install --frozen-lockfile --prod=false
|
|
|
|
# Stage 2: Build
|
|
FROM node:20-alpine AS builder
|
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
WORKDIR /app
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY . .
|
|
RUN pnpm build
|
|
|
|
# Stage 3: Production
|
|
FROM node:20-alpine AS runner
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production
|
|
|
|
RUN addgroup --system --gid 1001 nodejs
|
|
RUN adduser --system --uid 1001 nextjs
|
|
|
|
COPY --from=builder /app/public ./public
|
|
COPY --from=builder /app/.next/standalone ./
|
|
COPY --from=builder /app/.next/static ./.next/static
|
|
|
|
USER nextjs
|
|
EXPOSE 3000
|
|
ENV PORT=3000
|
|
CMD ["node", "server.js"]
|
|
EOF
|
|
log_success "Dockerfile created"
|
|
fi
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Commands
|
|
# ===========================================================================
|
|
|
|
build() {
|
|
log_info "Building Docker image..."
|
|
ensure_compose_file
|
|
ensure_dockerfile
|
|
$COMPOSE_CMD build --no-cache
|
|
log_success "Image built successfully"
|
|
}
|
|
|
|
start() {
|
|
log_info "Starting IT0 Web Admin..."
|
|
ensure_compose_file
|
|
ensure_dockerfile
|
|
|
|
PORT=${PORT:-$DEFAULT_PORT}
|
|
|
|
# Check if port is occupied
|
|
if command -v lsof &> /dev/null && lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
|
|
log_warn "Port $PORT is already in use, stopping existing service..."
|
|
stop
|
|
fi
|
|
|
|
$COMPOSE_CMD up -d --build
|
|
|
|
# Wait for service to start
|
|
log_info "Waiting for service to start..."
|
|
sleep 5
|
|
|
|
if docker ps | grep -q "$CONTAINER_NAME"; then
|
|
log_success "Service deployed successfully!"
|
|
log_info "Access URL: http://localhost:$PORT"
|
|
log_info "API endpoint: $API_BASE_URL"
|
|
else
|
|
log_error "Service failed to start. Check logs: ./deploy.sh logs"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
stop() {
|
|
log_info "Stopping service..."
|
|
$COMPOSE_CMD down
|
|
log_success "Service stopped"
|
|
}
|
|
|
|
restart() {
|
|
log_info "Restarting service..."
|
|
stop
|
|
start
|
|
}
|
|
|
|
logs() {
|
|
$COMPOSE_CMD logs -f
|
|
}
|
|
|
|
status() {
|
|
log_info "Service status:"
|
|
docker ps -a --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
|
|
echo ""
|
|
# Health check
|
|
PORT=${PORT:-$DEFAULT_PORT}
|
|
if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$PORT" 2>/dev/null | grep -q "200"; then
|
|
log_success "Web Admin is running (port $PORT)"
|
|
else
|
|
log_warn "Web Admin is not responding (port $PORT)"
|
|
fi
|
|
}
|
|
|
|
clean() {
|
|
log_info "Cleaning containers and images..."
|
|
$COMPOSE_CMD down --rmi local --volumes --remove-orphans
|
|
docker image prune -f
|
|
log_success "Cleanup complete"
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Help
|
|
# ===========================================================================
|
|
|
|
show_help() {
|
|
echo ""
|
|
echo "IT0 Web Admin Deployment Script"
|
|
echo ""
|
|
echo "Usage: $0 <command>"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " build Build Docker image"
|
|
echo " start Build and start service (default)"
|
|
echo " stop Stop service"
|
|
echo " restart Restart service"
|
|
echo " logs View service logs"
|
|
echo " status Show service status"
|
|
echo " clean Clean containers and images"
|
|
echo " help Show this help message"
|
|
echo ""
|
|
echo "Environment Variables:"
|
|
echo " PORT Service port (default: 3000)"
|
|
echo " API_DOMAIN API domain (default: it0api.szaiai.com)"
|
|
echo " API_BASE_URL API base URL (default: https://it0api.szaiai.com)"
|
|
echo " WS_URL WebSocket URL (default: wss://it0api.szaiai.com)"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 start # Start on default port 3000"
|
|
echo " PORT=8080 $0 start # Start on port 8080"
|
|
echo " API_DOMAIN=api.example.com $0 start # Use custom API domain"
|
|
echo ""
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Main
|
|
# ===========================================================================
|
|
|
|
main() {
|
|
cd "$SCRIPT_DIR"
|
|
|
|
check_docker
|
|
|
|
case "${1:-start}" in
|
|
build)
|
|
build
|
|
;;
|
|
start)
|
|
start
|
|
;;
|
|
stop)
|
|
stop
|
|
;;
|
|
restart)
|
|
restart
|
|
;;
|
|
logs)
|
|
logs
|
|
;;
|
|
status)
|
|
status
|
|
;;
|
|
clean)
|
|
clean
|
|
;;
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
log_error "Unknown command: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|