#!/bin/bash # ============================================================================= # Docker 镜像构建和部署自动化脚本 # # 用法: # ./docker_deplay.sh # 完整构建和部署流程 (默认AMD64架构) # ./docker_deplay.sh -amd # 构建和部署AMD64架构 # ./docker_deplay.sh -arm # 构建和部署ARM64架构 # ./docker_deplay.sh -upload # 仅上传已存在的tar文件并部署 # ./docker_deplay.sh -upload -amd # 仅上传已存在的AMD64架构tar文件并部署 # ./docker_deplay.sh -upload -arm # 仅上传已存在的ARM64架构tar文件并部署 # ============================================================================= # 配置变量 - 请根据实际情况修改 SERVER_HOST="6.6.6.86" # 服务器IP地址 SERVER_USER="ubuntu" # 服务器用户名 SERVER_PASSWORD="qweasdzxc1" # 服务器密码 SERVER_PORT="22" # SSH端口,默认22 IMAGE_NAME="epage_server" # Docker镜像名称 IMAGE_TAG="latest" # Docker镜像标签 CONTAINER_NAME="epage_server-container" # 容器名称 LOCAL_PORT="8199" # 本地端口 CONTAINER_PORT="8199" # 容器端口 TAR_FILE="${IMAGE_NAME}-${IMAGE_TAG}.tar" # 压缩包文件名 # 架构相关变量 PLATFORM="linux/amd64" # 默认架构 ARCH_SUFFIX="" # 架构后缀,用于区分不同架构的tar文件 # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查依赖 check_dependencies() { log_info "检查依赖..." if ! command -v docker &> /dev/null; then log_error "Docker 未安装,请先安装 Docker" exit 1 fi if ! command -v sshpass &> /dev/null; then log_error "sshpass 未安装,请先安装 sshpass" log_info "macOS: brew install sshpass" log_info "Ubuntu: sudo apt-get install sshpass" exit 1 fi log_success "依赖检查完成" } # 解析命令行参数 parse_arguments() { while [[ $# -gt 0 ]]; do case $1 in -amd) PLATFORM="linux/amd64" ARCH_SUFFIX="-amd64" log_info "设置目标架构为 AMD64" shift ;; -arm) PLATFORM="linux/arm64" ARCH_SUFFIX="-arm64" log_info "设置目标架构为 ARM64" shift ;; -upload) UPLOAD_ONLY=true log_info "设置为仅上传模式" shift ;; *) log_error "未知参数: $1" log_info "支持的参数: -amd, -arm, -upload" exit 1 ;; esac done # 更新TAR_FILE名,包含架构后缀 TAR_FILE="${IMAGE_NAME}-${IMAGE_TAG}${ARCH_SUFFIX}.tar" log_info "镜像文件名: ${TAR_FILE}" } # 构建Docker镜像 build_image() { log_info "开始构建 Docker 镜像..." # 检查是否存在旧的tar文件 if [ -f "$TAR_FILE" ]; then log_warning "发现旧的tar文件,正在删除..." rm -f "$TAR_FILE" fi # 构建镜像并导出为tar文件 docker buildx build --platform $PLATFORM -t "${IMAGE_NAME}:${IMAGE_TAG}" --output type=docker,dest="./${TAR_FILE}" . if [ $? -eq 0 ]; then log_success "Docker 镜像构建完成: ${TAR_FILE}" else log_error "Docker 镜像构建失败" exit 1 fi } # 上传文件到服务器 upload_to_server() { log_info "上传文件到服务器..." sshpass -p "$SERVER_PASSWORD" scp -P "$SERVER_PORT" -o StrictHostKeyChecking=no "$TAR_FILE" "${SERVER_USER}@${SERVER_HOST}:/tmp/" if [ $? -eq 0 ]; then log_success "文件上传成功" else log_error "文件上传失败" exit 1 fi } # 在服务器上部署 deploy_on_server() { log_info "在服务器上部署..." sshpass -p "$SERVER_PASSWORD" ssh -p "$SERVER_PORT" -o StrictHostKeyChecking=no "${SERVER_USER}@${SERVER_HOST}" << EOF set -e echo "[INFO] 开始服务器端部署..." # 检查并停止现有容器 if sudo docker ps -a --format 'table {{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then echo "[INFO] 发现现有容器 ${CONTAINER_NAME},正在停止并删除..." sudo docker stop ${CONTAINER_NAME} || true sudo docker rm ${CONTAINER_NAME} || true fi # 检查并删除现有镜像 if sudo docker images --format 'table {{.Repository}}:{{.Tag}}' | grep -q "^${IMAGE_NAME}:${IMAGE_TAG}$"; then echo "[INFO] 发现现有镜像 ${IMAGE_NAME}:${IMAGE_TAG},正在删除..." sudo docker rmi ${IMAGE_NAME}:${IMAGE_TAG} || true fi # 加载新镜像 echo "[INFO] 加载新镜像..." sudo docker load -i /tmp/${TAR_FILE} # 验证镜像是否加载成功 if sudo docker images | grep -q "${IMAGE_NAME}"; then echo "[SUCCESS] 镜像加载成功" else echo "[ERROR] 镜像加载失败" exit 1 fi # 运行新容器 echo "[INFO] 启动新容器..." sudo docker run -d -p ${LOCAL_PORT}:${CONTAINER_PORT} --name ${CONTAINER_NAME} ${IMAGE_NAME}:${IMAGE_TAG} # 验证容器是否启动成功 if sudo docker ps | grep -q "${CONTAINER_NAME}"; then echo "[SUCCESS] 容器启动成功" echo "[INFO] 容器状态:" sudo docker ps | grep "${CONTAINER_NAME}" else echo "[ERROR] 容器启动失败" echo "[INFO] 查看容器日志:" sudo docker logs ${CONTAINER_NAME} exit 1 fi # 清理临时文件 echo "[INFO] 清理临时文件..." rm -f /tmp/${TAR_FILE} echo "[SUCCESS] 部署完成!" echo "[INFO] 应用访问地址: http://${SERVER_HOST}:${LOCAL_PORT}" EOF if [ $? -eq 0 ]; then log_success "服务器部署完成" else log_error "服务器部署失败" exit 1 fi } # 清理本地文件 cleanup_local() { log_info "清理本地临时文件..." if [ -f "$TAR_FILE" ]; then rm -f "$TAR_FILE" log_success "本地临时文件已清理" fi } # 显示部署信息 show_deployment_info() { log_success "部署完成!" echo "" echo "==========================================" echo "部署信息:" echo "==========================================" echo "服务器地址: ${SERVER_HOST}" echo "应用端口: ${LOCAL_PORT}" echo "访问地址: http://${SERVER_HOST}:${LOCAL_PORT}" echo "容器名称: ${CONTAINER_NAME}" echo "镜像名称: ${IMAGE_NAME}:${IMAGE_TAG}" echo "目标架构: ${PLATFORM}" echo "镜像文件: ${TAR_FILE}" echo "==========================================" echo "" log_info "如需查看容器日志,请在服务器上运行: sudo docker logs ${CONTAINER_NAME}" log_info "如需停止容器,请在服务器上运行: sudo docker stop ${CONTAINER_NAME}" } # 主函数 main() { echo "==========================================" echo "Docker 镜像构建和部署自动化脚本" echo "==========================================" echo "" # 解析命令行参数 UPLOAD_ONLY=false parse_arguments "$@" # 检查配置 if [ "$SERVER_HOST" = "your-server-ip" ] || [ "$SERVER_PASSWORD" = "your-password" ]; then log_error "请先配置脚本顶部的服务器信息" log_info "需要修改的变量:" log_info " - SERVER_HOST: 服务器IP地址" log_info " - SERVER_USER: 服务器用户名" log_info " - SERVER_PASSWORD: 服务器密码" exit 1 fi # 检查是否是上传模式 if [ "$UPLOAD_ONLY" = true ]; then log_info "检测到 -upload 参数,跳过构建步骤" # 检查tar文件是否存在 if [ ! -f "$TAR_FILE" ]; then log_error "未找到tar文件: $TAR_FILE" log_info "请先运行脚本构建镜像,或确保tar文件存在" exit 1 fi log_success "找到tar文件: $TAR_FILE" # 执行上传和部署流程 upload_to_server deploy_on_server cleanup_local show_deployment_info else # 执行完整的部署流程 check_dependencies build_image upload_to_server deploy_on_server cleanup_local show_deployment_info fi } # 脚本入口 if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi