首页 > 解决方案 > 在 Spring Boot Maven 插件创建的 Docker 镜像中安装包

问题描述

我的 Spring Boot 项目包含 Spring Boot Maven 插件,我通过运行mvn spring-boot:build-image.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>build-image</goal>
            </goals>
        </execution>
    </executions>
</plugin>

将此映像部署到 Docker 堆栈时,我需要使用该curl命令运行运行状况检查,但遗憾curl的是默认 buildpack 未安装此映像。

是否可以进一步调整图像构建过程以便curl安装到 iamge 中?我找不到必要的信息

标签: spring-bootdockerspring-boot-maven-plugin

解决方案


TLDR;

使用以下命令安装curl到构建映像中:

docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install curl -y"

已停止容器的 Crab 容器 ID docker ps -a

$ docker ps -a
CONTAINER ID   IMAGE                                  COMMAND                  CREATED          STATUS                       PORTS     NAMES
2ff7db32825f   my-app:0.0.1-SNAPSHOT   "launcher 'apt-get u…&quot;   44 minutes ago   Exited (0) 44 minutes ago              reverent_swanson

根据我们安装的镜像创建一个新的容器镜像curl

docker commit 2ff7db32825f my-app-with-curl

启动一个新容器,定义正确ENTRYPOINT的启动 Spring Boot 应用程序:

docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-curl

现在curl应该在您的容器内准备就绪。


解决方案详情:

Cloud Native Buildpacks (CNBs) 和 Paketo.io 背后的原因,基本上是由spring-boot-maven-pluginsbuild-image目标抽象出来的,是为了让我们摆脱编写/维护自己的Dockerfiles. 所以这反过来是:配置构建过程很容易,但改变安装包之类的东西并不容易。

原因是,这些包被维护在一个所谓的堆栈中,它管理使用的build时间和run时间图像。如果堆栈没有为您的操作系统级依赖项定义 Mixin,那么您不能简单地添加另一个包。创建自己的简单 buildpack也是不够的(我尝试过这种方法)。创建自己的堆栈、构建包和/或构建器也会抵消云原生构建包提供的巨大好处!除其他事项外,我们还将被迫自己更新图像......

但还有另一种解决方案。由于我们不想创建自己的堆栈/构建包,我们可以调整由 CNBs/ 创建的容器镜像spring-boot-maven-plugin。因为官方文档向我们展示了如何挂钩到生成的容器的启动过程并运行 shell 脚本。假设我们的mvn spring-boot:build-image命令生成了一个名为my-app:0.0.1-SNAPSHOT.

然后首先我们安装curl到镜像中:

docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install curl -y"

我们需要在--user="root"这里使用才能使命令apt-get update && apt-get install curl -y成功运行(否则我们会遇到类似的错误List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied))。这将安装 curl,但我们不应该在生产中使用生成的容器。因为我们的 Spring Boot 应用会使用 root 用户运行,这会引入各种安全问题。此外,我们已经覆盖了ENTRYPOINT我们的容器,所以它无法启动我们的应用程序。

因此,我们只需使用新命令、入口点和用户启动这个停止的容器!只需使用以下命令抓取已停止容器的容器 ID docker ps -a

$ docker ps -a
CONTAINER ID   IMAGE                                  COMMAND                  CREATED          STATUS                       PORTS     NAMES
2ff7db32825f   my-app:0.0.1-SNAPSHOT   "launcher 'apt-get u…&quot;   44 minutes ago   Exited (0) 44 minutes ago              reverent_swanson

并根据我们安装的镜像创建一个新的容器镜像curl

docker commit 2ff7db32825f my-app-with-curl

最后基于这个新镜像启动一个新容器ENTRYPOINT,定义正确的启动我们的 Spring Boot 应用程序并cnb再次使用用户(如 Cloud Native Buildpacks 中所定义):

docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-curl

离题但相关

如果需要在生产容器中安装 curl,目前正在进行讨论。例如,请参阅这篇文章


推荐阅读