Ohhnews

分类导航

$ cd ..
foojay原文

使用 Docker Init 容器化 Java 26 项目

#docker#java#容器化#开发工具#spring boot

目录

Docker Init 在 Docker Desktop 4.27 版本中被引入,那时大语言模型(LLM)还没有成为解决一切问题的默认方案。它是一个“智能”交互式向导,能够分析你的项目并生成:

  • 一个 Dockerfile(多阶段构建,生产环境就绪)
  • 一个 compose.yaml 文件
  • 一个 .dockerignore 文件
  • 一个包含构建和运行说明的 README.Docker.md 文件

它的价值在于确定性——它不是基于概率的猜测。它始终遵循 Docker 的最佳实践,每次都能生成正确的输出。

[LOADING...]

技术要求

  • Docker Desktop 4.27 或更高版本

创建新项目

我正在使用一个 Spring Boot 项目。由于现在刚入春,我已经有一段时间没碰过它了——所以我们开始吧。

前往 https://start.spring.io/ 并创建一个项目,配置如下:

  • Project: Maven
  • Language: Java
  • Spring Boot: 4.0.5 (或任何最新的稳定版本)
  • Packaging: Jar
  • Java: 26

我使用了以下坐标,你也可以自定义:

  • Group: io.dockersecurity
  • Artifact: hello-wowlrd
  • Package Name: io.dockersecurity.hello-wowlrd

下载、解压并进入该目录:

$ bash
cd hello-wowlrd

运行 Docker Init

正如我英国朋友所说,“It's Docker, innit?”

$ bash
docker init

交互式向导会自动检测你的 Java 项目。选择“Java”,确认源目录和 Java 版本,并输入端口:

? What application platform does your project use? Java
? What's the relative directory (with a leading .) for your app? ./src
? What version of Java do you want to use? 26
? What port does your server listen on? 8080

Docker Init 会生成四个文件。最重要的是 Dockerfile

$ dockerfile
# syntax=docker/dockerfile:1

################################################################################
# Stage 1: 解析并下载依赖
FROM eclipse-temurin:26-jdk-jammy as deps

WORKDIR /build

COPY --chmod=0755 mvnw mvnw
COPY .mvn/ .mvn/

RUN --mount=type=bind,source=pom.xml,target=pom.xml \
    --mount=type=cache,target=/root/.m2 ./mvnw dependency:go-offline -DskipTests

################################################################################
# Stage 2: 构建应用程序
FROM deps as package

WORKDIR /build

COPY ./src src/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
    --mount=type=cache,target=/root/.m2 \
    ./mvnw package -DskipTests && \
    mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar

################################################################################
# Stage 3: 提取 Spring Boot 层
FROM package as extract

WORKDIR /build

RUN java -Djarmode=layertools -jar target/app.jar extract --destination target/extracted

################################################################################
# Stage 4: 最小化运行时镜像
FROM eclipse-temurin:26-jre-jammy AS final

ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser
USER appuser

COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./

EXPOSE 8080

ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]

这是一个非常规范的多阶段构建:分离了依赖解析、编译、层提取,并使用了一个带有非 root 用户的最小化运行时镜像。Gord 一定会赞同的。

关于 Java 26 基础镜像的说明

生成的 Dockerfile 引用了 eclipse-temurin:26-jdk-jammyeclipse-temurin:26-jre-jammy。由于 Java 26 刚刚发布,这些 Eclipse Temurin 镜像可能尚未在 Docker Hub 上完全可用。

你可以改用 SAP Machine 镜像——SAP 的免费 OpenJDK 发行版在 Ubuntu 24.04 (Noble Numbat) 上提供了 Java 26:

  • sapmachine:26-jdk-ubuntu-noble
  • sapmachine:26-jre-ubuntu-noble

在 Docker Hub 上可以找到它们:https://hub.docker.com/_/sapmachine。只需将两个 FROM 行中的 eclipse-temurin 替换为 sapmachine 即可。

构建与运行

$ bash
docker compose up --build

生成的 compose.yaml 非常简洁:

$ config
services:
  server:
    build:
      context: .
    ports:
      - 8080:8080

应用程序启动后会立即以退出代码 0 停止。这是预期的结果:因为没有 HTTP 端点来保持它运行。

添加 Controller

创建 src/main/java/io/dockersecurity/hellowowlrd/HelloController.java

$ java
package io.dockersecurity.hellowowlrd;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "Hello, Docker Security!";
    }
}

pom.xml 中添加 Spring Web 依赖:

$ xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

再次构建并运行:

$ bash
docker compose up --build

验证:

$ bash
curl http://localhost:8080
# Hello, Docker Security!

更多链接

Docker Init 支持的不仅仅是 Java。如果你想尝试其他语言,Docker 的官方指南是一个很好的起点:https://docs.docker.com/guides/

我参与编写了 C++ 指南——Docker 在页面顶部向我表示了感谢,这意味着我写了这些文字,然后代表他们感谢了我自己。值得一读:

总结

Java 26 刚刚发布,而 Docker Init 开箱即用,完美支持——包括多阶段构建、层提取、非 root 用户以及用于缓存的绑定挂载。你可以在一分钟内获得一个生产就绪的 Dockerfile。等 Eclipse Temurin 更新后,再把基础镜像换回去即可。在此之前,SAP Machine 能够满足你的需求。

如果你想了解更多 Docker Commandos(或命令),请访问:https://dockersecurity.io/commandos