Files
ewoooc/deploy_docker_uat.sh
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

276 lines
8.8 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# =============================================================================
# WOOO TECH - Momo Pro System
# UAT Docker 一鍵部署腳本
# =============================================================================
set -e
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 配置
UAT_HOST="192.168.0.110"
UAT_USER="wooo"
UAT_PATH="/home/wooo/momo_pro_system"
LOCAL_PATH="/Users/ogt/momo_pro_system"
IMAGE_NAME="wooo/momo-pro-system"
CONTAINER_NAME="momo-pro-system"
# 函數:打印帶顏色的訊息
print_header() {
echo ""
echo -e "${PURPLE}=============================================================================${NC}"
echo -e "${PURPLE} $1${NC}"
echo -e "${PURPLE}=============================================================================${NC}"
}
print_step() {
echo -e "${CYAN}$1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
# 檢查 SSH 連線
check_ssh() {
print_step "檢查 SSH 連線..."
if ssh -o ConnectTimeout=5 -o BatchMode=yes ${UAT_USER}@${UAT_HOST} "echo ok" 2>/dev/null; then
print_success "SSH 連線正常(免密碼)"
return 0
else
print_warning "需要 SSH 密碼驗證"
return 1
fi
}
# 主要部署流程
deploy() {
print_header "WOOO TECH - UAT Docker 部署"
echo -e "${CYAN}目標主機: ${UAT_USER}@${UAT_HOST}${NC}"
echo -e "${CYAN}部署時間: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo ""
# 步驟 1: 同步配置檔案
print_header "步驟 1/6: 同步 Docker 配置檔案到 UAT"
print_step "上傳 Dockerfile..."
scp "${LOCAL_PATH}/Dockerfile" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 docker-compose.yml..."
scp "${LOCAL_PATH}/docker-compose.yml" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 .dockerignore..."
scp "${LOCAL_PATH}/.dockerignore" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 docker/ 目錄..."
scp -r "${LOCAL_PATH}/docker" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 requirements.txt..."
scp "${LOCAL_PATH}/requirements.txt" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳核心 Python 檔案..."
scp "${LOCAL_PATH}/app.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
scp "${LOCAL_PATH}/auth.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
scp "${LOCAL_PATH}/config.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
scp "${LOCAL_PATH}/scheduler.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 HTML 模板..."
scp "${LOCAL_PATH}"/*.html ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/ 2>/dev/null || true
print_step "上傳 services/ 目錄..."
scp -r "${LOCAL_PATH}/services" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 database/ 目錄..."
scp -r "${LOCAL_PATH}/database" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 utils/ 目錄..."
scp -r "${LOCAL_PATH}/utils" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 static/ 目錄..."
scp -r "${LOCAL_PATH}/static" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_step "上傳 web/ 目錄..."
scp -r "${LOCAL_PATH}/web" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
print_success "檔案同步完成"
# 步驟 2: 停止現有服務
print_header "步驟 2/6: 停止現有服務"
print_step "停止 systemd momo 服務..."
ssh ${UAT_USER}@${UAT_HOST} "sudo systemctl stop momo 2>/dev/null || echo '服務未運行'"
print_step "停止並刪除舊的 Docker 容器..."
ssh ${UAT_USER}@${UAT_HOST} "docker stop ${CONTAINER_NAME} 2>/dev/null || true"
ssh ${UAT_USER}@${UAT_HOST} "docker rm ${CONTAINER_NAME} 2>/dev/null || true"
print_success "服務已停止"
# 步驟 3: 建置 Docker Image
print_header "步驟 3/6: 建置 Docker Image"
print_info "這可能需要幾分鐘,請耐心等候..."
ssh ${UAT_USER}@${UAT_HOST} "cd ${UAT_PATH} && docker build -t ${IMAGE_NAME}:latest ."
print_success "Docker Image 建置完成"
# 步驟 4: 啟動 Docker 容器
print_header "步驟 4/6: 啟動 Docker 容器"
ssh ${UAT_USER}@${UAT_HOST} "cd ${UAT_PATH} && docker run -d \
--name ${CONTAINER_NAME} \
-p 5000:5000 \
-v ./data:/app/data \
-v ./logs:/app/logs \
-v ./config:/app/config \
-v ./backups:/app/backups \
--env-file .env \
--restart unless-stopped \
${IMAGE_NAME}:latest"
print_success "Docker 容器已啟動"
# 步驟 5: 等待服務啟動
print_header "步驟 5/6: 等待服務啟動"
print_info "等待 30 秒讓服務完全啟動..."
for i in {1..30}; do
echo -ne "\r${CYAN}等待中... ${i}/30 秒${NC}"
sleep 1
done
echo ""
print_success "等待完成"
# 步驟 6: 驗證部署
print_header "步驟 6/6: 驗證部署"
print_step "檢查容器狀態..."
ssh ${UAT_USER}@${UAT_HOST} "docker ps --filter name=${CONTAINER_NAME} --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
print_step "測試健康檢查端點..."
HEALTH_STATUS=$(ssh ${UAT_USER}@${UAT_HOST} "curl -s -o /dev/null -w '%{http_code}' http://localhost:5000/health" || echo "000")
if [ "$HEALTH_STATUS" = "200" ]; then
print_success "健康檢查通過 (HTTP 200)"
else
print_warning "健康檢查回傳 HTTP ${HEALTH_STATUS}"
fi
print_step "測試首頁..."
HOME_STATUS=$(ssh ${UAT_USER}@${UAT_HOST} "curl -s -o /dev/null -w '%{http_code}' http://localhost:5000/" || echo "000")
if [ "$HOME_STATUS" = "200" ] || [ "$HOME_STATUS" = "302" ]; then
print_success "首頁正常 (HTTP ${HOME_STATUS})"
else
print_warning "首頁回傳 HTTP ${HOME_STATUS}"
fi
# 完成
print_header "部署完成!"
echo ""
echo -e "${GREEN}┌─────────────────────────────────────────────────────────────┐${NC}"
echo -e "${GREEN}│ 🎉 UAT Docker 部署成功! │${NC}"
echo -e "${GREEN}├─────────────────────────────────────────────────────────────┤${NC}"
echo -e "${GREEN}│ 存取網址: http://${UAT_HOST}:5000 │${NC}"
echo -e "${GREEN}│ 容器名稱: ${CONTAINER_NAME}${NC}"
echo -e "${GREEN}│ 映像名稱: ${IMAGE_NAME}:latest │${NC}"
echo -e "${GREEN}└─────────────────────────────────────────────────────────────┘${NC}"
echo ""
echo -e "${CYAN}常用指令:${NC}"
echo -e " 查看日誌: ssh ${UAT_USER}@${UAT_HOST} 'docker logs -f ${CONTAINER_NAME}'"
echo -e " 重啟容器: ssh ${UAT_USER}@${UAT_HOST} 'docker restart ${CONTAINER_NAME}'"
echo -e " 停止容器: ssh ${UAT_USER}@${UAT_HOST} 'docker stop ${CONTAINER_NAME}'"
echo ""
}
# 顯示使用說明
usage() {
echo "使用方式: $0 [選項]"
echo ""
echo "選項:"
echo " deploy 執行完整部署 (預設)"
echo " status 檢查 UAT 容器狀態"
echo " logs 查看容器日誌"
echo " restart 重啟容器"
echo " stop 停止容器"
echo " help 顯示此說明"
echo ""
}
# 檢查狀態
check_status() {
print_header "UAT Docker 容器狀態"
ssh ${UAT_USER}@${UAT_HOST} "docker ps -a --filter name=${CONTAINER_NAME} --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
echo ""
print_step "磁碟空間:"
ssh ${UAT_USER}@${UAT_HOST} "df -h | head -3"
}
# 查看日誌
view_logs() {
print_header "UAT Docker 容器日誌 (最近 100 行)"
ssh ${UAT_USER}@${UAT_HOST} "docker logs --tail 100 ${CONTAINER_NAME}"
}
# 重啟容器
restart_container() {
print_header "重啟 UAT Docker 容器"
ssh ${UAT_USER}@${UAT_HOST} "docker restart ${CONTAINER_NAME}"
print_success "容器已重啟"
}
# 停止容器
stop_container() {
print_header "停止 UAT Docker 容器"
ssh ${UAT_USER}@${UAT_HOST} "docker stop ${CONTAINER_NAME}"
print_success "容器已停止"
}
# 主程式
case "${1:-deploy}" in
deploy)
deploy
;;
status)
check_status
;;
logs)
view_logs
;;
restart)
restart_container
;;
stop)
stop_container
;;
help|--help|-h)
usage
;;
*)
print_error "未知選項: $1"
usage
exit 1
;;
esac