Java项目不推荐用Makefile替代Maven/Gradle构建,而应将其作为胶水层调用mvn verify生成fat-jar,再用docker build(多阶段、temurin镜像)、tag、push完成标准化流程,支持变量注入与CI复用。

Java 项目中不推荐直接用 Makefile 驱动 Docker 构建与推送,因为 Maven 和 Gradle 已原生支持构建、测试、打包(如 mvn clean package 生成 JAR/WAR),而 Docker 构建本质是分层打包和镜像操作,Makefile 只能做轻量封装,不能替代构建工具本身。但若团队习惯用 make 统一入口,可将其作为“胶水层”,调用 Maven + Docker CLI 完成标准化流程。
核心思路:Makefile 只负责编排,不重复造轮子
Makefile 不处理编译、依赖下载或单元测试,而是:
- 调用
mvn verify确保代码通过测试并生成可运行的 fat-jar(如target/app.jar) - 执行
docker build,以该 JAR 为上下文构建镜像(推荐多阶段构建,基础镜像用eclipse-temurin:17-jre-jammy) - 用
docker tag和docker push推送至私有仓库或 Docker Hub - 支持变量注入(如
IMAGE_NAME、VERSION、REGISTRY),便于 CI/CD 复用
一个实用的 Makefile 示例
放在项目根目录,与 pom.xml 同级:
# 默认目标
.PHONY: help build push deploy clean
help:
@echo "Usage:"
@echo " make build # 构建本地镜像"
@echo " make push # 构建并推送到 registry"
@echo " make deploy # 构建、打标签、推送(含版本)"
@echo " make clean # 清理构建产物"
<h1>可配置参数(可被环境变量或 make 命令覆盖)</h1><p>IMAGE_NAME ?= my-java-app
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
REGISTRY ?= docker.io
FULL_IMAGE := $(REGISTRY)/$(IMAGE_NAME):$(VERSION)</p><h1>构建 jar(复用 Maven 生命周期)</h1><p>target/app.jar: pom.xml
mvn -q clean verify -DskipTests</p><h1>构建 Docker 镜像(依赖 jar 已存在)</h1><p>build: target/app.jar
docker build \
--build-arg JAR_FILE=app.jar \
-t $(IMAGE_NAME):latest \
-t $(FULL_IMAGE) \
.</p><h1>推送镜像(需提前登录 docker login)</h1><p>push: build
docker push $(FULL_IMAGE)</p><h1>一键部署(常用于 CI 脚本)</h1><p>deploy: push
@echo "✅ Deployed $(FULL_IMAGE)"</p><h1>清理</h1><p>clean:
rm -rf target/
docker image rm $(IMAGE_NAME):latest $(FULL_IMAGE) 2>/dev/null || true</p>Dockerfile 配合建议(关键点)
确保 Dockerfile 支持构建参数、最小化体积、非 root 运行:
立即学习“Java免费学习笔记(深入)”;
- 使用
ARG JAR_FILE动态指定 jar 名,避免硬编码 - 基础镜像选 slim/jre 版本(如
eclipse-temurin:17-jre-jammy),不要用openjdk:17-jdk - 创建普通用户(
useradd -r -u 1001 -g root javauser),用USER javauser切换 - 暴露正确端口(
EXPOSE 8080),ENTRYPOINT 用["java","-jar","/app.jar"]
注意事项与避坑提示
实际使用时需注意:
- Makefile 不跨平台:Windows 上需 WSL 或 Git Bash;CI 中建议统一用 Linux runner
-
敏感信息不写死:registry 凭据靠
docker login提前配置,不要在 Makefile 里存密码 -
版本号建议自动化:用
git describe或 CI 环境变量(如GITHUB_SHA、CI_PIPELINE_ID)生成 -
跳过测试要显式控制:生产构建应保留
-DskipTests=false,开发调试才加-DskipTests


















