Windows 下将 Java 项目打包为 Docker 容器并部署的完整指南

在微服务和云原生架构日益普及的今天,Docker 已成为 Java 应用部署的事实标准。然而,许多开发者在 Windows 环境下尝试将 Spring Boot 等 Java 项目打包成 Docker 镜像时,常会遇到权限、路径或脚本兼容性问题------例如经典的错误:

bash 复制代码
/bin/sh: 1: touch: not found
or
exec: "sh": executable file not found in $PATH

甚至在 Dockerfile 中执行 RUN sh -c 'touch /app.jar' 时失败。本文将手把手教你如何在 Windows 系统下正确构建 Java 项目的 Docker 镜像,并成功部署运行,避开常见陷阱。


一、准备工作

1. 安装必要工具

  • JDK 8/11/17+ :用于编译 Java 项目
  • Maven 或 Gradle:构建工具(本文以 Maven 为例)
  • Docker Desktop for Windows:确保已启用 WSL2 后端(推荐)
  • IDE(如 IntelliJ IDEA 或 VS Code)

✅ 建议:使用 WSL2(Windows Subsystem for Linux)可极大减少跨平台兼容问题。

2. 构建可执行 JAR 包

以 Spring Boot 项目为例,在项目根目录执行:

go 复制代码
mvn clean package -DskipTests

生成的 JAR 文件通常位于 target/your-app.jar。


二、编写正确的 Dockerfile

关键点:避免在非 Linux 环境下使用不兼容的 shell 命令,并选择合适的 base 镜像。

bash 复制代码
# 使用官方 OpenJDK 镜像(Alpine 更小,但注意 glibc 兼容性)
FROM openjdk:17-jdk-slim

# 设置工作目录
WORKDIR /app

# 将本地 JAR 文件复制到容器中
COPY target/*.jar app.jar

# 【关键】解决"touch"问题:仅在需要修改时间戳时才使用
# 实际上,现代 Spring Boot 应用通常不需要 touch
# 若你看到旧教程中的 RUN touch /app.jar,可直接删除!

# 暴露端口(根据应用配置调整)
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

⚠️ 注意:

  • 不要写 RUN sh -c 'touch /app.jar' ------ 这是早期为解决 Spring Boot 在某些只读文件系统中启动失败而引入的 hack,在现代 Docker 和 Spring Boot 版本中已不再需要。
  • 如果你坚持使用 Alpine 镜像(openjdk:17-alpine),请确保你的应用不依赖 glibc(Alpine 使用 musl libc),否则可能报错。

三、在 Windows 下构建镜像

打开 PowerShell 或 CMD(建议在项目根目录操作):

perl 复制代码
# 构建镜像(注意末尾的 . 表示上下文路径)
docker build -t my-java-app:1.0 .

# 查看镜像是否创建成功
docker images

🔍 常见问题排查:

  • 文件路径错误 :确保 COPY target/*.jar app.jar 中的 target 目录存在且包含 JAR。
  • 换行符问题(CRLF vs LF) :若使用 Git Bash 或 WSL,确保 Dockerfile 为 Unix 换行(LF)。可在 VS Code 右下角切换。
  • 权限问题:Windows 一般不会出现,但在 WSL 中需确保文件可读。

四、运行容器

css 复制代码
docker run -d --name my-app -p 8080:8080 my-java-app:1.0
  • -d:后台运行
  • -p 8080:8080:将宿主机 8080 端口映射到容器 8080 端口

查看日志验证是否启动成功:

perl 复制代码
docker logs -f my-app

五、优化建议(进阶)

1. 多阶段构建(减小镜像体积)

bash 复制代码
# 构建阶段
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# 运行阶段
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

2. 使用 .dockerignore

避免将 target/ 以外的临时文件(如 .git, *.log)复制进镜像:

bash 复制代码
.git
*.log
README.md
Dockerfile
.dockerignore

3. 健康检查(可选)

bash 复制代码
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

六、关于 "RUN touch /app.jar" 的真相

该命令最早出现在 Spring Boot 官方早期文档中,目的是确保 JAR 文件的时间戳不是未来时间(某些构建环境如 CI/CD 可能导致时间异常),从而避免 Spring Boot 启动时因"非法时间"拒绝加载。

但在以下情况下完全不需要:

  • 本地正常构建(mvn package)
  • 使用现代 JDK 和 Spring Boot(2.3+)
  • 容器文件系统可写(默认情况)

因此,除非你明确遇到时间戳相关错误,否则应删除该行,避免引入不必要的复杂性。


结语

在 Windows 下打包 Java 项目为 Docker 容器并非难事,关键在于理解 Docker 构建上下文、选择合适的 base 镜像,并摒弃过时的"经验代码"。通过本文的步骤,你可以快速、可靠地将 Spring Boot 应用容器化,并为后续部署到 Kubernetes 或云平台打下基础。

💡 最后提醒:开发环境尽量贴近生产环境。若生产使用 Linux,建议在 WSL2 或 Linux 虚拟机中测试 Docker 镜像,以提前暴露兼容性问题。

相关推荐
孟健6 分钟前
出海开发者资金合规:从港卡结汇到完税申报实操
后端·架构
乌暮23 分钟前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习
架构技术专栏1 小时前
Skill 有效性与稳定性评估:用对照、重复与证据判断价值
后端
拔剑纵狂歌1 小时前
ClickHouse system.query_log 字段详解与排障实践
后端·clickhouse·1024程序员节
再吃一根胡萝卜2 小时前
把本地 RAG 问答做"准":多轮指代消解 + 云端语义向量 + TXT 章节切分
后端
怕浪猫2 小时前
2026年9月面18个后端
后端·面试·github
IT_陈寒2 小时前
Vue 这个响应式陷阱,我的头发都掉没了
前端·人工智能·后端
谁在黄金彼岸2 小时前
trae的gitee mcp莫名错误
后端
前端的日常2 小时前
一个人+AI做情侣食谱小程序,30天纯赚
前端·javascript·后端
再吃一根胡萝卜3 小时前
给 RAG 问答加上「多轮指代消解」:让"他 / 这个"不再翻车
后端