spring-boot - 在 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 中?我找不到必要的信息
解决方案
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…" 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-plugin
sbuild-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…" 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,目前正在进行讨论。例如,请参阅这篇文章。
推荐阅读
- c# - C# - 带有 IP 地址范围的端口扫描
- ruby-on-rails - 具有多个范围参数的 Ruby on Rails 路由
- python - 如何在 tk 的按钮上放置带有文本的背景图像?
- typescript - 如何在 TypeScript 中获取 wasm 文件
- java - 如何将 spring data mongodb 2.1.0.RELEASE 与 spring boot 2.0.5 和 Jhipster 5.3.3 一起使用?
- spring - Spring Batch作业抛出StackOverflowError:启动时出现空错误
- opengl - 以顶点为向量的 VBO
- function - 哈斯克尔井字游戏
- inno-setup - 如何在 ShellExec 行中用其常量替换目录
- django - 试图在帖子列表 Django 模板中获得用户的平均评分