#!/bin/bash set -e # ============================================================ # 碳信网 - 镜像打包脚本 # 用法: bash devops/pack-image.sh [VERSION] [SERVER_USER] [SERVER_HOST] # 示例: # bash devops/pack-image.sh txw-web 1.0.0 root 192.168.1.100 # bash devops/pack-image.sh txw-all # ============================================================ # 默认配置 DEFAULT_VERSION="latest" DEFAULT_SERVER_USER="root" DEFAULT_SERVER_HOST="192.168.1.100" # 参数解析 IMAGE_TYPE=${1:-} VERSION=${2:-${DEFAULT_VERSION}} SERVER_USER=${3:-${DEFAULT_SERVER_USER}} SERVER_HOST=${4:-${DEFAULT_SERVER_HOST}} PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" IMAGE_NAME="" REMOTE_IMAGE_PATH="" REMOTE_DIR="" SERVICE_NAME="" # 镜像元数据 case "${IMAGE_TYPE}" in txw-web) IMAGE_NAME="txw-web:${VERSION}" REMOTE_IMAGE_PATH="/opt/txw/images/txw-web-${VERSION}.tar" REMOTE_DIR="/opt/txw/txw-web" SERVICE_NAME="txw-web" ;; txw-all) IMAGE_NAME="txw-all:${VERSION}" REMOTE_IMAGE_PATH="/opt/txw/images/txw-all-${VERSION}.tar" REMOTE_DIR="/opt/txw/txw-all" SERVICE_NAME="txw-all" ;; *) echo "============================================" echo " 碳信网 - 镜像打包脚本" echo "============================================" echo "" echo "用法: bash devops/pack-image.sh [VERSION] [SERVER_USER] [SERVER_HOST]" echo "" echo "参数说明:" echo " txw-web 前端镜像 (默认版本: ${DEFAULT_VERSION})" echo " txw-all 后端镜像 (默认版本: ${DEFAULT_VERSION})" echo " VERSION 镜像版本,默认为 ${DEFAULT_VERSION}" echo " SERVER_USER 服务器用户,默认为 ${DEFAULT_SERVER_USER}" echo " SERVER_HOST 服务器地址,默认为 ${DEFAULT_SERVER_HOST}" echo "" echo "示例:" echo " bash devops/pack-image.sh txw-web 1.0.0 root 192.168.1.100" echo " bash devops/pack-image.sh txw-all" echo "" echo "============================================" exit 1 ;; esac # 确保镜像是最新的 ensure_image() { local local_image=$(docker images -q ${IMAGE_NAME} 2>/dev/null) if [ -z "${local_image}" ]; then echo "" echo "[!] 本地未找到镜像: ${IMAGE_NAME}" echo "[*] 正在尝试构建..." case "${IMAGE_TYPE}" in txw-web) bash "${SCRIPT_DIR}/build.sh" "${VERSION}" ;; txw-all) echo "[!] 后端镜像需要完整构建,请执行:" echo " bash devops/build.sh ${VERSION}" exit 1 ;; esac fi } # 打包镜像 pack_image() { echo "" echo "============================================" echo " 碳信网 - 镜像打包" echo "============================================" echo " 镜像类型: ${IMAGE_TYPE}" echo " 版本: ${VERSION}" echo " 镜像名称: ${IMAGE_NAME}" echo "============================================" # 确保镜像存在 ensure_image # 镜像输出目录 PACK_DIR="${SCRIPT_DIR}/images" mkdir -p "${PACK_DIR}" TIMESTAMP=$(date +%Y-%m-%d%H%M%S) PACKAGE_FILE="${PACK_DIR}/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar" MD5_FILE="${PACKAGE_FILE}.md5" echo "" echo ">>> [1/4] 打包镜像 -> ${PACKAGE_FILE}" docker save -o "${PACKAGE_FILE}" "${IMAGE_NAME}" echo "" echo ">>> [2/4] gzip 压缩 (最高压缩级别)" GZIP_FILE="${PACKAGE_FILE}.gz" gzip -9 -f "${PACKAGE_FILE}" echo "" echo ">>> [3/4] 生成校验文件" md5sum "${GZIP_FILE}" > "${GZIP_FILE}.md5" md5sum "${PACKAGE_FILE}" > "${MD5_FILE}" echo "" echo ">>> [4/4] 打包完成" ls -lh "${GZIP_FILE}" "${GZIP_FILE}.md5" "${MD5_FILE}" echo "" echo "============================================" echo " 下一步操作提示" echo "============================================" echo "" echo ">>> 1. 传输镜像到服务器 (推荐使用 .tar.gz 压缩包,体积更小)" echo "" echo " # 方式一: scp 传输压缩包" echo " scp ${GZIP_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/" echo " scp ${GZIP_FILE}.md5 ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/" echo "" echo " # 方式二: scp 传输原始 tar 包 (不压缩)" echo " scp ${PACKAGE_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/" echo " scp ${MD5_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/" echo "" echo ">>> 2. SSH 到服务器后,执行以下命令:" echo "" echo " # 创建目录" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'mkdir -p /opt/txw/images'" echo "" echo " # 解压 (如果上传的是 .tar.gz)" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'gunzip /opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar.gz'" echo "" echo " # 加载镜像" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker load -i /opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar'" echo "" echo ">>> 3. 更新并重启服务" echo "" echo " # 停止旧容器" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker stop ${SERVICE_NAME} || true'" echo "" echo " # 移除旧容器" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker rm ${SERVICE_NAME} || true'" echo "" echo " # 启动新容器 (txw-all 示例)" echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker run -d \\'" echo " --name ${SERVICE_NAME} \\" echo " --restart=always \\" echo " -p 8080:8080 \\" echo " ${IMAGE_NAME}'" echo "" echo ">>> 4. 一键执行脚本 (上传 .tar.gz 后 ssh 内执行)" echo "" echo " ssh ${SERVER_USER}@${SERVER_HOST} << 'EOF'" echo " #!/bin/bash" echo " GZIP_PATH=\"/opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar.gz\"" echo " " echo " # 解压" echo " gunzip \${GZIP_PATH}" echo " " echo " # 加载镜像" echo " docker load -i \${GZIP_PATH%.gz}" echo " " echo " # 停止并移除旧容器" echo " docker stop ${SERVICE_NAME} 2>/dev/null || true" echo " docker rm ${SERVICE_NAME} 2>/dev/null || true" echo " " echo " # 启动新容器" echo " docker run -d \\" echo " --name ${SERVICE_NAME} \\" echo " --restart=always \\" echo " -p 8080:8080 \\" echo " ${IMAGE_NAME}" echo " EOF" echo "" echo "============================================" echo "" echo "[*] 打包文件: ${GZIP_FILE} (压缩后,推荐传输)" echo "[*] 原始文件: ${PACKAGE_FILE} (未压缩)" echo "[*] 校验文件: ${GZIP_FILE}.md5 ${MD5_FILE}" echo "" } # 执行打包 pack_image