Docker 和 Java 入门
现代 Java 应用程序开发离不开容器化。Docker 是一个用于在隔离环境(容器)中打包、交付和运行应用程序的平台。对于 Java 开发者来说,Docker 解决了那个永恒的问题:"在我机器上能运行!"。容器确保您的应用程序在本地机器、开发服务器和生产环境中以相同方式运行。
在本文中,我们将探讨如何使用 Docker 容器化 Java 应用程序:从简单的 Dockerfile 到为微服务架构优化镜像。所有示例均用 Java 编写,可直接使用。
Java 应用程序的 Docker 基础
什么是 Docker 镜像和容器?
Docker 镜像是一个只读模板,包含运行应用程序所需的一切:JVM、库、代码和配置。容器是镜像的运行实例。对于 Java 来说,这意味着您无需手动在服务器上安装 JDK——JVM 已经在容器内部。
为 Java 创建简单的 Dockerfile
我们来看一个基本示例。我们有一个简单的 Java 应用程序(例如 HelloWorld.java)。
// HelloWorld.javapublic class HelloWorld { public static void main(String[] args) { System.out.println("Hello from Docker and Java!"); }}创建 Dockerfile:
# 使用官方 OpenJDK 镜像FROM openjdk:11-jre-slim
# 设置工作目录WORKDIR /app
# 复制编译后的 jar 或 class 文件COPY HelloWorld.class .
# 启动命令CMD ["java", "HelloWorld"]构建和运行:
# 构建镜像docker build -t hello-java .
# 运行容器docker run hello-java输出:Hello from Docker and Java!
Spring Boot 应用程序的容器化
对于实际项目(例如基于 Spring Boot 的项目),过程会更复杂。我们来看一个典型的微服务。
多阶段构建
这是 Java 的最佳实践:首先使用完整的 JDK 构建应用程序,然后将结果复制到轻量级的 JRE 镜像中。
# 阶段 1:构建FROM maven:3.8.5-openjdk-11 AS buildWORKDIR /appCOPY pom.xml .RUN mvn dependency:go-offlineCOPY src ./srcRUN mvn clean package -DskipTests
# 阶段 2:运行FROM openjdk:11-jre-slimWORKDIR /appCOPY --from=build /app/target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]说明:
- build — 使用 Maven 和完整 JDK 进行编译。
- 最终镜像 — 仅包含 JRE 和准备好的 jar 文件。镜像大小减少 2-3 倍。
优化层缓存
Docker 会缓存每一层(指令)。为了加快构建速度,将不常更改的依赖项放在前面:
FROM maven:3.8.5-openjdk-11 AS buildWORKDIR /app# 缓存依赖项COPY pom.xml .RUN mvn dependency:go-offline# 现在复制代码COPY src ./srcRUN mvn clean package现在,如果您只更改代码,Docker 只会重新构建最后几层,而依赖项将从缓存中获取。
使用环境变量和配置文件
向 Java 应用程序传递参数
Docker 允许通过环境变量灵活配置应用程序。对于 Spring Boot 来说尤其方便。
docker run -e SPRING_PROFILES_ACTIVE=prod -e DB_URL=jdbc:postgresql://db:5432/mydb my-app在 Dockerfile 中可以设置默认值:
ENV SPRING_PROFILES_ACTIVE=devENV DB_URL=jdbc:h2:mem:testdbJava + 数据库的 docker-compose 示例
对于微服务,使用 docker-compose.yml 很方便:
version: '3.8'services: app: bu