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 镜像,以提前暴露兼容性问题。

相关推荐
大尚来也2 小时前
Python 实战指南:一键批量旋转 PDF 页面方向
后端
大黄评测2 小时前
跳出索引思维定式:一次基于业务逻辑的非典型 SQL 优化实践
后端
bcbnb2 小时前
Fastlane 结合 AppUploader 来实现 CI 集成自动化上架
后端
鱼人2 小时前
Python argparse 入门到实战:命令行参数解析全指南
后端
大魔王7193 小时前
进程线程和协程一
后端
icebreaker3 小时前
Mokup:构建工具友好的可视化 Mock 工具
前端·javascript·后端
无心水3 小时前
2025,一路有你!
java·人工智能·分布式·后端·深度学习·架构·2025博客之星
AskHarries3 小时前
skills-lc-cli:3 天做出来的一个小工具,结果自己每天都在用
后端