2026-01-21 03:34:16 +08:00
|
|
|
|
# 多阶段构建:前后端一体化部署(支持混合编译)
|
|
|
|
|
|
# 构建参数:控制是否在 Docker 内编译
|
|
|
|
|
|
# - BUILD_IN_DOCKER=true (默认): Docker 内部编译(本地开发)
|
|
|
|
|
|
# - BUILD_IN_DOCKER=false: 使用外部产物(GitHub Actions)
|
|
|
|
|
|
ARG BUILD_IN_DOCKER=true
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 阶段1:构建前端 ====================
|
2025-12-03 03:08:53 +08:00
|
|
|
|
FROM node:18-alpine AS frontend-build
|
2026-01-21 03:34:16 +08:00
|
|
|
|
ARG BUILD_IN_DOCKER
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
WORKDIR /app/frontend
|
|
|
|
|
|
|
2025-12-07 16:46:18 +08:00
|
|
|
|
# 定义构建参数(版本号信息)
|
|
|
|
|
|
ARG VERSION=dev
|
|
|
|
|
|
ARG GIT_TAG=
|
|
|
|
|
|
ARG GITHUB_REPO_URL=https://github.com/WrBug/PolyHermes
|
|
|
|
|
|
|
|
|
|
|
|
# 设置环境变量(用于 Vite 构建时注入)
|
|
|
|
|
|
ENV VERSION=${VERSION}
|
|
|
|
|
|
ENV GIT_TAG=${GIT_TAG}
|
|
|
|
|
|
ENV GITHUB_REPO_URL=${GITHUB_REPO_URL}
|
2026-01-21 04:16:01 +08:00
|
|
|
|
# 复制前端文件(先复制 package.json 以利用 Docker 缓存)
|
2025-12-03 03:08:53 +08:00
|
|
|
|
COPY frontend/package*.json ./
|
2026-01-21 03:34:16 +08:00
|
|
|
|
|
|
|
|
|
|
# 条件:仅在 Docker 内部编译时安装依赖
|
|
|
|
|
|
RUN if [ "$BUILD_IN_DOCKER" = "true" ]; then \
|
|
|
|
|
|
npm ci; \
|
|
|
|
|
|
fi
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
2026-01-21 04:16:01 +08:00
|
|
|
|
# 复制所有前端源文件
|
2025-12-03 03:08:53 +08:00
|
|
|
|
COPY frontend/ ./
|
|
|
|
|
|
|
2026-01-21 04:16:01 +08:00
|
|
|
|
# 条件:仅在 Docker 内部编译时执行构建
|
|
|
|
|
|
# 如果 BUILD_IN_DOCKER=false,需要从构建上下文复制外部编译的 dist
|
2026-01-21 03:34:16 +08:00
|
|
|
|
RUN if [ "$BUILD_IN_DOCKER" = "true" ]; then \
|
|
|
|
|
|
echo "🔨 Docker 内部编译前端..."; \
|
|
|
|
|
|
npm run build; \
|
|
|
|
|
|
else \
|
2026-01-21 04:16:01 +08:00
|
|
|
|
echo "⏭️ 使用外部产物,将在下一步复制"; \
|
|
|
|
|
|
mkdir -p dist; \
|
2026-01-21 03:34:16 +08:00
|
|
|
|
fi
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
2026-01-21 04:16:01 +08:00
|
|
|
|
# 如果使用外部产物,从构建上下文复制外部编译的 dist
|
|
|
|
|
|
# 注意:这个 COPY 在 BUILD_IN_DOCKER=false 时必需
|
|
|
|
|
|
# 在 BUILD_IN_DOCKER=true 时,如果前端已编译,这个 COPY 会尝试覆盖,但结果相同
|
|
|
|
|
|
# 如果本地没有 dist(BUILD_IN_DOCKER=true 且未编译),这个 COPY 会失败,但上面的 RUN 已经编译了
|
|
|
|
|
|
COPY frontend/dist ./dist
|
|
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# ==================== 阶段2:构建后端 ====================
|
2025-12-03 03:08:53 +08:00
|
|
|
|
FROM gradle:8.5-jdk17 AS backend-build
|
2026-01-21 03:34:16 +08:00
|
|
|
|
ARG BUILD_IN_DOCKER
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
WORKDIR /app/backend
|
|
|
|
|
|
|
|
|
|
|
|
# 复制 Gradle 配置文件
|
|
|
|
|
|
COPY backend/build.gradle.kts backend/settings.gradle.kts ./
|
|
|
|
|
|
COPY backend/gradle ./gradle
|
|
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 条件:仅在 Docker 内部编译时下载依赖
|
|
|
|
|
|
RUN if [ "$BUILD_IN_DOCKER" = "true" ]; then \
|
|
|
|
|
|
gradle dependencies --no-daemon || true; \
|
|
|
|
|
|
fi
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
# 复制源代码
|
|
|
|
|
|
COPY backend/src ./src
|
|
|
|
|
|
|
2026-01-21 04:06:23 +08:00
|
|
|
|
# 如果使用外部产物,先从构建上下文复制外部编译的 JAR
|
|
|
|
|
|
# 注意:如果 BUILD_IN_DOCKER=true 且本地没有 JAR,这个 COPY 会失败,但会在下面编译生成
|
|
|
|
|
|
COPY backend/build/libs/*.jar build/libs/
|
|
|
|
|
|
|
|
|
|
|
|
# 条件:仅在 Docker 内部编译时执行构建(会覆盖外部产物)
|
2026-01-21 03:34:16 +08:00
|
|
|
|
RUN if [ "$BUILD_IN_DOCKER" = "true" ]; then \
|
|
|
|
|
|
echo "🔨 Docker 内部编译后端..."; \
|
|
|
|
|
|
gradle bootJar --no-daemon; \
|
|
|
|
|
|
else \
|
2026-01-21 04:06:23 +08:00
|
|
|
|
echo "⏭️ 使用外部产物"; \
|
|
|
|
|
|
mkdir -p build/libs; \
|
|
|
|
|
|
if [ -z "$(ls -A build/libs/*.jar 2>/dev/null)" ]; then \
|
|
|
|
|
|
echo "❌ 错误:BUILD_IN_DOCKER=false 但找不到外部产物 backend/build/libs/*.jar"; \
|
|
|
|
|
|
exit 1; \
|
|
|
|
|
|
fi; \
|
2026-01-21 03:34:16 +08:00
|
|
|
|
fi
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# ==================== 阶段3:运行环境 ====================
|
2025-12-03 03:15:52 +08:00
|
|
|
|
FROM eclipse-temurin:17-jre-jammy
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
WORKDIR /app
|
|
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 安装 Nginx、Python 和必要的工具
|
2025-12-03 03:08:53 +08:00
|
|
|
|
RUN apt-get update && \
|
2026-01-21 03:34:16 +08:00
|
|
|
|
apt-get install -y nginx curl tzdata jq python3 python3-flask python3-requests && \
|
2025-12-03 03:08:53 +08:00
|
|
|
|
rm -rf /var/lib/apt/lists/* && \
|
2025-12-03 05:34:26 +08:00
|
|
|
|
rm -rf /etc/nginx/sites-enabled/default
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
# 从构建阶段复制文件
|
2026-01-21 04:06:23 +08:00
|
|
|
|
# 当 BUILD_IN_DOCKER=false 时,构建阶段已经复制了外部产物
|
2025-12-03 03:08:53 +08:00
|
|
|
|
COPY --from=frontend-build /app/frontend/dist /usr/share/nginx/html
|
|
|
|
|
|
COPY --from=backend-build /app/backend/build/libs/*.jar app.jar
|
|
|
|
|
|
|
|
|
|
|
|
# 复制 Nginx 配置
|
|
|
|
|
|
COPY docker/nginx.conf /etc/nginx/nginx.conf
|
|
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 创建更新服务相关目录和脚本
|
|
|
|
|
|
RUN mkdir -p /app/updates /app/backups /var/log/polyhermes
|
|
|
|
|
|
COPY docker/update-service.py /app/update-service.py
|
2025-12-03 03:08:53 +08:00
|
|
|
|
COPY docker/start.sh /app/start.sh
|
|
|
|
|
|
RUN chmod +x /app/start.sh
|
|
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 记录初始版本(从构建参数)
|
|
|
|
|
|
ARG VERSION=dev
|
|
|
|
|
|
ARG GIT_TAG=dev
|
|
|
|
|
|
RUN echo "{\"version\":\"${VERSION}\",\"tag\":\"${GIT_TAG}\",\"buildTime\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" > /app/version.json
|
|
|
|
|
|
|
|
|
|
|
|
# 创建非 root 用户
|
2025-12-03 03:39:13 +08:00
|
|
|
|
RUN useradd -m -u 1000 appuser
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 设置目录权限
|
2025-12-03 05:25:14 +08:00
|
|
|
|
RUN mkdir -p /var/log/nginx /var/lib/nginx /var/cache/nginx /var/run && \
|
2025-12-03 03:08:53 +08:00
|
|
|
|
chown -R appuser:appuser /app && \
|
2026-01-21 03:34:16 +08:00
|
|
|
|
chown -R root:root /usr/share/nginx/html /var/log/nginx /var/lib/nginx /var/cache/nginx /etc/nginx /var/run
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
# 暴露端口
|
|
|
|
|
|
EXPOSE 80
|
|
|
|
|
|
|
|
|
|
|
|
# 健康检查
|
|
|
|
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
2026-01-21 03:34:16 +08:00
|
|
|
|
CMD curl -f http://localhost/api/system/health || exit 1
|
2025-12-03 03:08:53 +08:00
|
|
|
|
|
2026-01-21 03:34:16 +08:00
|
|
|
|
# 启动服务
|
2025-12-03 03:08:53 +08:00
|
|
|
|
ENTRYPOINT ["/app/start.sh"]
|