package-docker-deploy.sh 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/usr/bin/env bash
  2. # 打包 Docker 交付物:预构建应用镜像 + compose + 数据库 SQL(不含前后端源码)
  3. # 目标运行环境:甲方 Linux x86_64 云主机(固定 linux/amd64,与发版机 macOS/ARM 无关)
  4. set -euo pipefail
  5. ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
  6. cd "$ROOT"
  7. # 交付镜像架构(甲方云主机默认 amd64;勿改为 arm64 除非已确认对方为 ARM 云)
  8. export DOCKER_PLATFORM=linux/amd64
  9. export DOCKER_BUILDKIT=1
  10. VERSION="${1:-$(date +%Y%m%d)}"
  11. OUT_DIR="${ROOT}/dist"
  12. PKG_NAME="zkxw-docker-deploy-${VERSION}"
  13. STAGING="${OUT_DIR}/${PKG_NAME}"
  14. ARCHIVE="${OUT_DIR}/${PKG_NAME}.tar.gz"
  15. IMAGES_TAR="${STAGING}/images/zkxw-app-images.tar"
  16. BACKEND_IMAGE="zkxw-backend:${VERSION}"
  17. WEB_IMAGE="zkxw-web:${VERSION}"
  18. echo "==> [1/4] 构建应用镜像(平台 ${DOCKER_PLATFORM},供 Linux 云主机)"
  19. "${ROOT}/scripts/build-docker-images.sh" "${VERSION}"
  20. echo "==> [2/4] 导出镜像到 tar"
  21. rm -rf "${STAGING}"
  22. mkdir -p "${STAGING}/images" "${STAGING}/deploy/docker" "${STAGING}/docs/sql"
  23. docker save -o "${IMAGES_TAR}" "${BACKEND_IMAGE}" "${WEB_IMAGE}"
  24. echo "==> [3/4] 组装部署文件(无 backend/ web-admin 源码)"
  25. cp "${ROOT}/deploy/docker/docker-compose.yml" "${STAGING}/deploy/docker/"
  26. sed -e "s|^ZKXW_BACKEND_IMAGE=.*|ZKXW_BACKEND_IMAGE=${BACKEND_IMAGE}|" \
  27. -e "s|^ZKXW_WEB_IMAGE=.*|ZKXW_WEB_IMAGE=${WEB_IMAGE}|" \
  28. "${ROOT}/deploy/docker/.env.example" > "${STAGING}/deploy/docker/.env.example"
  29. # 若本地 deploy/docker/.env 已配置登录 RSA 私钥,注入到交付包 .env.example(避免多 worker 登录解密失败)
  30. LOCAL_ENV="${ROOT}/deploy/docker/.env"
  31. if [[ -f "${LOCAL_ENV}" ]]; then
  32. STAGING_ENV="${STAGING}/deploy/docker/.env.example"
  33. if python3 - "${LOCAL_ENV}" "${STAGING_ENV}" <<'PY'
  34. import sys
  35. from pathlib import Path
  36. local_env, staging_env = map(Path, sys.argv[1:3])
  37. rsa_line = next(
  38. (line for line in local_env.read_text().splitlines() if line.startswith("LOGIN_RSA_PRIVATE_KEY_PEM=")),
  39. "",
  40. )
  41. if not rsa_line:
  42. sys.exit(2)
  43. lines: list[str] = []
  44. for line in staging_env.read_text().splitlines():
  45. if line.startswith("# LOGIN_RSA_PRIVATE_KEY_PEM=") or line.startswith("LOGIN_RSA_PRIVATE_KEY_PEM="):
  46. continue
  47. if line.startswith("# 登录 RSA"):
  48. lines.append(
  49. "# 登录 RSA(多 worker/多实例须配置同一私钥;打包时已从 deploy/docker/.env 注入)"
  50. )
  51. continue
  52. if line.startswith("API_REQUEST_LOG_ENABLED="):
  53. lines.append(rsa_line)
  54. lines.append(line)
  55. staging_env.write_text("\n".join(lines) + "\n")
  56. PY
  57. then
  58. echo " 已从 deploy/docker/.env 注入 LOGIN_RSA_PRIVATE_KEY_PEM"
  59. elif [[ $? -eq 2 ]]; then
  60. echo " 警告: deploy/docker/.env 未配置 LOGIN_RSA_PRIVATE_KEY_PEM,交付包内仍为占位;多 worker 下登录可能失败"
  61. else
  62. echo " 错误: 注入 LOGIN_RSA_PRIVATE_KEY_PEM 失败" >&2
  63. exit 1
  64. fi
  65. fi
  66. cp "${ROOT}/deploy/docker/README.md" "${STAGING}/deploy/docker/"
  67. cp -R "${ROOT}/deploy/docker/mysql" "${STAGING}/deploy/docker/"
  68. cp "${ROOT}/docs/sql/zkxw.sql" "${STAGING}/docs/sql/zkxw.sql"
  69. cp "${ROOT}/deploy/docker/README.md" "${STAGING}/部署说明.md"
  70. cp "${ROOT}/deploy/docker/部署指导手册.html" "${STAGING}/部署指导手册.html"
  71. cp "${ROOT}/deploy/docker/部署指导手册.html" "${STAGING}/deploy/docker/部署指导手册.html"
  72. cat > "${STAGING}/VERSION.txt" <<EOF
  73. package=${PKG_NAME}
  74. version=${VERSION}
  75. platform=${DOCKER_PLATFORM}
  76. backend_image=${BACKEND_IMAGE}
  77. web_image=${WEB_IMAGE}
  78. built_at=$(date -Iseconds)
  79. git_commit=$(git -C "${ROOT}" rev-parse --short HEAD 2>/dev/null || echo unknown)
  80. deploy_dir=deploy/docker
  81. EOF
  82. echo "==> [4/4] 生成压缩包"
  83. mkdir -p "${OUT_DIR}"
  84. tar -czf "${ARCHIVE}" -C "${OUT_DIR}" "${PKG_NAME}"
  85. echo ""
  86. echo "完成: ${ARCHIVE}"
  87. echo "应用镜像: $(du -h "${IMAGES_TAR}" | cut -f1)"
  88. echo "总包大小: $(du -h "${ARCHIVE}" | cut -f1)"
  89. echo ""
  90. echo "包内不含前后端源码,包含:"
  91. echo " - images/zkxw-app-images.tar"
  92. echo " - deploy/docker/ (compose + .env.example + mysql init)"
  93. echo " - docs/sql/zkxw.sql"
  94. echo " - 部署指导手册.html(客户安装手册,浏览器打开)"
  95. echo ""
  96. echo "甲方服务器执行:"
  97. echo " tar -xzf ${PKG_NAME}.tar.gz"
  98. echo " cd ${PKG_NAME}"
  99. echo " docker load -i images/zkxw-app-images.tar"
  100. echo " cd deploy/docker && cp .env.example .env && vim .env"
  101. echo " docker compose up -d"