[英]Install package in Docker image created by Spring Boot Maven plugin
My Spring Boot project contains the Spring Boot Maven Plugin which I use for building a Docker image by running mvn spring-boot:build-image
.我的 Spring Boot 项目包含 Spring Boot Maven 插件,我使用它通过运行mvn spring-boot:build-image
来构建 Docker 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>
When deploying this image to a Docker stack I need to run a healthcheck using the curl
command but unfortunately curl
is not installed by the default buildpack.将此映像部署到 Docker 堆栈时,我需要使用curl
命令运行运行状况检查,但不幸的是默认 buildpack 未安装curl
。
Is it possible to further tweak the image building process so that curl
gets installed into the iamge?是否可以进一步调整图像构建过程,以便将curl
安装到图像中? I couldn't find the necessary information我找不到必要的信息
TLDR; TLDR;
Install curl
into the build image with:使用以下命令将curl
安装到构建映像中:
docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install curl -y"
Crab container id of the stopped container with docker ps -a
:使用docker ps -a
已停止容器的 Crab 容器 ID:
$ 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
Create a new container image based on the one we installed curl
into with:根据我们安装curl
镜像创建一个新的容器镜像:
docker commit 2ff7db32825f my-app-with-curl
Fire up a new container defining the correct ENTRYPOINT
to start Spring Boot app:启动一个定义正确ENTRYPOINT
的新容器来启动 Spring Boot 应用程序:
docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-curl
Now curl
should be ready inside your container.现在curl
应该在你的容器中准备好了。
Details of the solution:解决方案详情:
The reasoning behind Cloud Native Buildpacks (CNBs) & Paketo.io, which are basically abstracted away by the spring-boot-maven-plugin
s build-image
goal, is to free us from the need to write/maintain our own Dockerfiles
. Cloud Native Buildpacks (CNBs) 和 Paketo.io 背后的原因,基本上被spring-boot-maven-plugin
的build-image
目标抽象出来,是让我们无需编写/维护我们自己的Dockerfiles
。 So the inversion of this is: It's easy to configure the build process, but it is not easy to change things like installed packages.所以这个倒过来是:配置构建过程很容易,但改变安装包之类的东西并不容易。
The reason is, that those packages are maintained in a so called stack , that manages the used build
-time and run
-time images.原因是,这些包维护在所谓的堆栈中,它管理使用的build
和run
映像。 And if the stack doesn't define a Mixin for your OS-level dependency , then you can't simply add another package.如果堆栈没有为您的操作系统级依赖项定义Mixin ,那么您不能简单地添加另一个包。 It would also not suffice to create your own simple buildpack (I tried this approach). 创建自己的简单 buildpack也是不够的(我尝试过这种方法)。 And creating your own stacks, buildpacks and/or builders would also negate the huge benefits that Cloud Native Buildpacks provide!创建自己的堆栈、构建包和/或构建器也会抵消云原生构建包提供的巨大好处! Amongst other things we would be also forced to keep the images updated ourselves...除其他事项外,我们还将被迫自行更新图像......
But there's another solution.但还有另一种解决方案。 As we don't want to create our own stacks/buildpacks, we can tweak the container image which has been created by CNBs/ spring-boot-maven-plugin
.由于我们不想创建自己的堆栈/构建包,我们可以调整由 CNBs/ spring-boot-maven-plugin
创建的容器镜像。 Because the official docs show us how to hook into the startup process of the produced containers and run shell scripts for example.因为官方文档向我们展示了如何挂钩生成的容器的启动过程并运行 shell 脚本。 Let's assume our mvn spring-boot:build-image
command produced a container image called my-app:0.0.1-SNAPSHOT
.假设我们的mvn spring-boot:build-image
命令生成了一个名为my-app:0.0.1-SNAPSHOT
的容器镜像。
Then first we install curl
into the image with:然后首先我们将curl
安装到图像中:
docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install curl -y"
We need to use --user="root"
here in order that the command apt-get update && apt-get install curl -y
will run successfully (otherwise we would run into errors like List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
).我们需要在这里使用--user="root"
以便命令apt-get update && apt-get install curl -y
能够成功运行(否则我们会遇到像List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
)。 This will install curl, but we shouldn't use the resulting container in production.这将安装 curl,但我们不应该在生产中使用生成的容器。 Because our Spring Boot app would run using the root user, which would introduce a variety of security problems.因为我们的 Spring Boot 应用程序将使用 root 用户运行,这会引入各种安全问题。 Also we've overwritten the ENTRYPOINT
of our container, so it wouldn't be able to start our app.此外,我们已经覆盖了容器的ENTRYPOINT
,因此它无法启动我们的应用程序。
Therefore we simply start this stopped container with a new command , entrypoint & user!因此,我们只需使用新命令、入口点和用户启动这个停止的容器! Simply crab the container id of the stopped container with docker ps -a
:只需使用docker ps -a
获取已停止容器的容器 ID:
$ 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
And create a new container image based on the one we installed curl
into with:并根据我们安装curl
镜像创建一个新的容器镜像:
docker commit 2ff7db32825f my-app-with-curl
Finally fire up a new container based on this new image, defining the correct ENTRYPOINT
to start our Spring Boot app and also using the cnb
user again (as defined in the Cloud Native Buildpacks):最后基于这个新镜像启动一个新容器,定义正确的ENTRYPOINT
来启动我们的 Spring Boot 应用程序,并再次使用cnb
用户(如 Cloud Native Buildpacks 中定义的):
docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-curl
Off topic but relevant :离题但相关:
There are ongoing discussions if it is desired to install curl in a production container.如果需要在生产容器中安装 curl,目前正在进行讨论。 See this post for example . 例如,请参阅此帖子。
我最终使用了一个安装的卷(例如/utils
)和一个静态编译的 curl( https://github.com/moparistthebest/static-curl )和配置的健康检查器,比如
/utils/curl http://localhost:8080/actuator/health
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.