288b0c25e6
- Update Docker image names and network configurations - Rename package.json project names to picpeak-backend/frontend - Update CI/CD configurations (Drone CI and GitHub Actions) - Update documentation and setup scripts - Update application branding in source code - Change default database name to picpeak - Update PM2 ecosystem config 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
196 lines
5.3 KiB
Bash
Executable File
196 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo -e "${GREEN}PicPeak Deployment Script${NC}"
|
|
echo "========================================"
|
|
|
|
# Default values
|
|
STACK_NAME="picpeak"
|
|
ENV_FILE="../../.env.production"
|
|
REGISTRY_URL="${REGISTRY_URL:-}"
|
|
VERSION="${VERSION:-latest}"
|
|
|
|
# Parse command line arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--env)
|
|
ENV_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--registry)
|
|
REGISTRY_URL="$2"
|
|
shift 2
|
|
;;
|
|
--version)
|
|
VERSION="$2"
|
|
shift 2
|
|
;;
|
|
--stack-name)
|
|
STACK_NAME="$2"
|
|
shift 2
|
|
;;
|
|
--help)
|
|
echo "Usage: $0 [options]"
|
|
echo "Options:"
|
|
echo " --env FILE Path to environment file (default: ../../.env.production)"
|
|
echo " --registry URL Docker registry URL"
|
|
echo " --version VERSION Image version to deploy (default: latest)"
|
|
echo " --stack-name NAME Stack name (default: picpeak)"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown option: $1${NC}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Check if Docker is in swarm mode
|
|
if ! docker info | grep -q "Swarm: active"; then
|
|
echo -e "${RED}Docker is not in swarm mode. Run init-swarm.sh first.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if environment file exists
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
echo -e "${RED}Environment file not found: $ENV_FILE${NC}"
|
|
echo "Please create it from .env.production.example"
|
|
exit 1
|
|
fi
|
|
|
|
# Load environment variables
|
|
echo -e "${GREEN}Loading environment variables...${NC}"
|
|
set -a
|
|
source "$ENV_FILE"
|
|
set +a
|
|
|
|
# Export deployment variables
|
|
export REGISTRY_URL
|
|
export VERSION
|
|
|
|
# Validate required environment variables
|
|
required_vars=(
|
|
"FRONTEND_HOST"
|
|
"BACKEND_HOST"
|
|
"ADMIN_URL"
|
|
"FRONTEND_URL"
|
|
"ACME_EMAIL"
|
|
"DB_NAME"
|
|
"EMAIL_FROM"
|
|
)
|
|
|
|
echo -e "${GREEN}Validating configuration...${NC}"
|
|
for var in "${required_vars[@]}"; do
|
|
if [ -z "${!var}" ]; then
|
|
echo -e "${RED}Missing required environment variable: $var${NC}"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Check if Traefik is running
|
|
if ! docker service ls | grep -q "traefik_traefik"; then
|
|
echo -e "${YELLOW}Traefik is not running. Deploy it first with:${NC}"
|
|
echo "cd ../traefik && docker stack deploy -c docker-compose.traefik.yml traefik"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if secrets exist
|
|
echo -e "${GREEN}Checking Docker secrets...${NC}"
|
|
required_secrets=(
|
|
"jwt_secret"
|
|
"db_user"
|
|
"db_password"
|
|
"smtp_user"
|
|
"smtp_pass"
|
|
)
|
|
|
|
for secret in "${required_secrets[@]}"; do
|
|
if ! docker secret ls | grep -q $secret; then
|
|
echo -e "${RED}Missing required secret: $secret${NC}"
|
|
echo "Run create-secrets.sh first"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Pull latest images if registry is specified
|
|
if [ ! -z "$REGISTRY_URL" ]; then
|
|
echo -e "${GREEN}Pulling latest images...${NC}"
|
|
docker pull ${REGISTRY_URL}/photo-sharing-backend:${VERSION} || true
|
|
docker pull ${REGISTRY_URL}/photo-sharing-frontend:${VERSION} || true
|
|
fi
|
|
|
|
# Deploy the stack
|
|
echo -e "${GREEN}Deploying stack: $STACK_NAME${NC}"
|
|
echo -e "${BLUE}Version: $VERSION${NC}"
|
|
echo -e "${BLUE}Registry: ${REGISTRY_URL:-local}${NC}"
|
|
|
|
cd ..
|
|
docker stack deploy \
|
|
-c docker-stack.yml \
|
|
--with-registry-auth \
|
|
$STACK_NAME
|
|
|
|
# Wait for services to start
|
|
echo -e "${GREEN}Waiting for services to start...${NC}"
|
|
sleep 10
|
|
|
|
# Check service status
|
|
echo -e "${GREEN}Service status:${NC}"
|
|
docker service ls --filter "label=com.docker.stack.namespace=$STACK_NAME"
|
|
|
|
# Wait for database to be ready
|
|
echo -e "${GREEN}Waiting for database to be ready...${NC}"
|
|
max_attempts=30
|
|
attempt=1
|
|
while [ $attempt -le $max_attempts ]; do
|
|
if docker exec $(docker ps -q -f name=${STACK_NAME}_db) pg_isready -U postgres > /dev/null 2>&1; then
|
|
echo -e "${GREEN}Database is ready!${NC}"
|
|
break
|
|
fi
|
|
echo -n "."
|
|
sleep 2
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
if [ $attempt -gt $max_attempts ]; then
|
|
echo -e "${RED}Database failed to start in time${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Run database migrations
|
|
echo -e "${GREEN}Running database migrations...${NC}"
|
|
sleep 5
|
|
docker exec $(docker ps -q -f name=${STACK_NAME}_backend -f status=running | head -1) npm run migrate || {
|
|
echo -e "${YELLOW}Migration failed. This might be normal if migrations already ran.${NC}"
|
|
}
|
|
|
|
# Show deployment information
|
|
echo ""
|
|
echo -e "${GREEN}Deployment complete!${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}Access URLs:${NC}"
|
|
echo "Frontend: https://${FRONTEND_HOST}"
|
|
echo "Backend API: https://${BACKEND_HOST}/api"
|
|
if [ ! -z "$UMAMI_HOST" ]; then
|
|
echo "Analytics: https://${UMAMI_HOST}"
|
|
fi
|
|
if [ ! -z "$TRAEFIK_HOST" ]; then
|
|
echo "Traefik Dashboard: https://${TRAEFIK_HOST}/dashboard/"
|
|
fi
|
|
echo ""
|
|
echo -e "${BLUE}Useful commands:${NC}"
|
|
echo "View logs: docker service logs ${STACK_NAME}_backend"
|
|
echo "Scale service: docker service scale ${STACK_NAME}_backend=5"
|
|
echo "Update service: docker service update ${STACK_NAME}_backend"
|
|
echo "Remove stack: docker stack rm $STACK_NAME"
|
|
echo ""
|
|
echo -e "${GREEN}Health check:${NC}"
|
|
curl -s -o /dev/null -w "Frontend: %{http_code}\n" https://${FRONTEND_HOST}/health || true
|
|
curl -s -o /dev/null -w "Backend: %{http_code}\n" https://${BACKEND_HOST}/api/health || true |