292 lines
9.0 KiB
Bash
292 lines
9.0 KiB
Bash
#!/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 |