# Author: fruit.com.cn # # 多阶段构建:maven 构建 fat jar -> JRE 运行(非 root、tini 做 1 号进程)。 # 三个可运行件共用一份 Dockerfile,用 MODULE 构建参数区分。 # # 构建(在 FruitServer 目录下执行): # docker build -t fruitshorts/app-api:latest --build-arg MODULE=fruitshorts-app-api . # docker build -t fruitshorts/admin-api:latest --build-arg MODULE=fruitshorts-admin-api . # docker build -t fruitshorts/transcode-worker:latest --build-arg MODULE=fruitshorts-transcode-worker \ # --build-arg INSTALL_FFMPEG=true . # # 注意:本机当前没有 Docker(见 DEPLOY.md),这份 Dockerfile 未经本机构建验证。 # ---------- 1. 构建阶段 ---------- FROM maven:3.9-eclipse-temurin-21 AS build WORKDIR /build # Maven Central 在国内网络下拉依赖不稳定(构建时曾出现 maven-filtering:3.3.1 解析失败), # 构建阶段固定走阿里云 central 镜像;其它仓库仍直连。 RUN mkdir -p /root/.m2 \ && printf '%s\n' \ '' \ ' ' \ ' ' \ ' aliyun-central' \ ' central' \ ' https://maven.aliyun.com/repository/central' \ ' ' \ ' ' \ '' > /root/.m2/settings.xml # 先只拷各模块 pom 再拉依赖:依赖层可复用,改业务代码不会重新下载依赖 COPY pom.xml . COPY fruitshorts-common/pom.xml fruitshorts-common/ COPY fruitshorts-framework/pom.xml fruitshorts-framework/ COPY fruitshorts-module-system/pom.xml fruitshorts-module-system/ COPY fruitshorts-module-content/pom.xml fruitshorts-module-content/ COPY fruitshorts-module-media/pom.xml fruitshorts-module-media/ COPY fruitshorts-module-user/pom.xml fruitshorts-module-user/ COPY fruitshorts-module-playback/pom.xml fruitshorts-module-playback/ COPY fruitshorts-module-interaction/pom.xml fruitshorts-module-interaction/ COPY fruitshorts-module-commerce/pom.xml fruitshorts-module-commerce/ COPY fruitshorts-module-creator/pom.xml fruitshorts-module-creator/ COPY fruitshorts-admin-api/pom.xml fruitshorts-admin-api/ COPY fruitshorts-app-api/pom.xml fruitshorts-app-api/ COPY fruitshorts-transcode-worker/pom.xml fruitshorts-transcode-worker/ RUN mvn -B -q -DskipTests dependency:go-offline COPY . . ARG MODULE=fruitshorts-app-api RUN mvn -B -DskipTests -pl ${MODULE} -am package \ && cp ${MODULE}/target/*.jar /build/app.jar # ---------- 2. 运行阶段 ---------- FROM eclipse-temurin:21-jre # ffmpeg 只有转码 worker 需要,用构建参数控制,避免把 80MB 装进两个 API 镜像 ARG INSTALL_FFMPEG=false RUN apt-get update \ && apt-get install -y --no-install-recommends tini curl \ && if [ "$INSTALL_FFMPEG" = "true" ]; then \ apt-get install -y --no-install-recommends ffmpeg; \ fi \ && rm -rf /var/lib/apt/lists/* # 非 root 运行;/data/uploads 预留给媒资挂载卷 RUN groupadd -r fruitshorts \ && useradd -r -g fruitshorts -d /app -s /sbin/nologin fruitshorts \ && mkdir -p /app /data/uploads \ && chown -R fruitshorts:fruitshorts /app /data/uploads WORKDIR /app COPY --from=build --chown=fruitshorts:fruitshorts /build/app.jar /app/app.jar USER fruitshorts ENV JAVA_OPTS="-XX:MaxRAMPercentage=75 -XX:+UseG1GC -Duser.timezone=Asia/Shanghai" \ SPRING_PROFILES_ACTIVE=prod \ MEDIA_ROOT_DIR=/data/uploads # 健康检查打 /healthz(不依赖 actuator,见 HealthController) HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \ CMD curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}/healthz || exit 1 ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["sh", "-c", "exec java $JAVA_OPTS -jar /app/app.jar"]