txw/devops/pack-image.sh
2026-05-03 17:49:17 +08:00

204 lines
6.4 KiB
Bash

#!/bin/bash
set -e
# ============================================================
# 碳信网 - 镜像打包脚本
# 用法: bash devops/pack-image.sh <txw-web|txw-all> [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 <txw-web|txw-all> [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