SpringBoot 容器镜像更新只要200k,你敢信???

  • 导读
  • 基础环境
  • 基于传统单个jar包构建模式
    • 基础Dockerfile
    • Base镜像信息
    • Base镜像大小 622MB
    • Base镜像history信息
    • 传统构建方式
    • 构建后镜像大小 为基础镜像大小 622MB + 2*65M <= 757MB
    • 成品构建history信息
    • 优化Dockerfile
  • 基于spring boot 分层构建方式
    • 探索基于分层构建原理
    • 基于分层构建构建制品镜像
    • 验证模拟开发推送代码更新镜像
  • 验证镜像

图片


导读

在容器化实践中部署spring boot应用普遍采用基础java镜像再添加jar包层来构建应用镜像制品。随着公司业务大量上云,每个变更日上传到云上镜像日渐增多,导致本地机房到云上带宽压力倍增。为解决镜像上传问题,调研了相关技术栈决定采用spring boot 2.3新增的镜像分层构建功能。

基础环境

  • spring boot version >= 2.3
  • java oracle jdk 8u201
  • docker version 20.10.13

基于传统单个jar包构建模式

基础Dockerfile

以下是我们基于基础镜像构建spring boot镜像制品的Dockerfile,采用了比较传统的COPY jar包。相信这也是大家普遍采用的模式。Dockefile如下,该Dockerfile存在一个坑,会在下边阐述。

bash 复制代码
FROM registry.xxx.com/base/oracle-jdk:8u201
ENV TZ=Asia/Shanghai
ENV LC_ALL en_US.utf8
WORKDIR /app
ADD ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
ADD ./entrypoint.sh /app/bin/entrypoint.sh
ENTRYPOINT  exec bash /app/bin/entrypoint.sh
RUN ln -s /app/logs /app/log && chown 1001.1001 -R /app

Base镜像信息

我们base镜像主要分三层添加了相关常用的工具如telnet netstat等以及安全修复

arduino 复制代码
docker image inspect registry.xxx.com/base/oracle-jdk:8u201

分层信息:

json 复制代码
"RootFS": {
    "Type": "layers",
    "Layers": [
        "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
        "sha256:2105884a1756425b2188084cc1738d6a6b13293773af56f6727af1be979858ed",
        "sha256:c33745b350978d855171c996779055195b09e227844b7a03a1d795aee803dbb9"
    ]
}

Base镜像大小 622MB

镜像大小 622MB 不算太小,对比友商有些基础镜像竟然1-2G😂 简直有点离谱。

bash 复制代码
registry.xxx.com/base/oracle-jdk  8u201 1869b73a8999  2 years ago  622MB

Base镜像history信息

从构建历史可以看出占用空间主要分为三层分别是

  • centos 7 基础镜像层
  • yum install 层
  • jdk 层
bash 复制代码
docker image  history registry.xxx.com/base/oracle-jdk:8u201
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
1869b73a8999   2 years ago   /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago   /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago   /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago   /bin/sh -c #(nop)  LABEL maintainer=...           0B
<missing>      2 years ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

传统构建方式

sql 复制代码
docker build -t registry.xxx.com/layer/build:old .
Sending build context to Docker daemon  67.45MB
Step 1/8 : FROM registry.xxx.com/base/oracle-jdk:8u201
 ---> 1869b73a8999
Step 2/8 : ENV TZ=Asia/Shanghai
 ---> Running in a67423d7246b
Removing intermediate container a67423d7246b
 ---> 9304102c278e
Step 3/8 : ENV LC_ALL en_US.utf8
 ---> Running in 05bf14c10efd
Removing intermediate container 05bf14c10efd
 ---> 63fb6c823893
Step 4/8 : WORKDIR /app
 ---> Running in 095764328d18
Removing intermediate container 095764328d18
 ---> c057ab4a7d18
Step 5/8 : ADD ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
 ---> 08928447fafa
Step 6/8 : ADD ./entrypoint.sh /app/bin/entrypoint.sh
 ---> 0902efa62157
Step 7/8 : ENTRYPOINT  exec bash /app/bin/entrypoint.sh
 ---> Running in dc0eb814cfff
Removing intermediate container dc0eb814cfff
 ---> 20679a170252
Step 8/8 : RUN ln -s /app/logs /app/log && chown 1001.1001 -R /app
 ---> Running in 34159dca7464
Removing intermediate container 34159dca7464
 ---> b6043465c072
Successfully built b6043465c072
Successfully tagged registry.xxx.com/layer/build:old

构建后镜像大小 为基础镜像大小 622MB + 2*65M <= 757MB

构建后比我们预期的 jar包加基础镜像所占用的空间大😢 why?

bash 复制代码
#jar包大小
ls -lh xxx-1.0.0.jar
-rw------- 1 root root 65M Aug 16 10:33 xxx-1.0.0.jar

#镜像大小
docker image ls |grep registry.xxx.com/layer/build
registry.xxx.com/layer/build                 old          b6043465c072   59 seconds ago   757MB

成品构建history信息

查看构建成品的镜像层发现竟然有两层一样大小,也会被推送了两遍。🥲离大谱。通过分析Dockerfile是因为RUN ln -s /app/logs /app/log && chown 1001.1001 -R /app 导致的。为保证镜像安全,生产环境运行统一采用了1001账号运行。为了保证1001对workdir有绝对的读写权限。对目录递归授权导致文件属性发生改变。

在构建时认为文件发生变化产生一样大小的两层导致的。(这还是我自己当时优化引入的屎山😊)具体原因我也不太清楚docker构建时如何判定文件发生变化,我原本以为是基于MD5码。实际上在对文件属主属组改变时MD5码是不对变的。有知道的大神可以在评论区留言交流。

bash 复制代码
docker image  history  registry.xxx.com/layer/build:old
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
b6043465c072   6 minutes ago   /bin/sh -c ln -s /app/logs /app/log && chown...   67.4MB
20679a170252   6 minutes ago   /bin/sh -c #(nop)  ENTRYPOINT ["/bin/sh" "-c...   0B
0902efa62157   6 minutes ago   /bin/sh -c #(nop) ADD file:9ac19caf793524884...   128B
08928447fafa   6 minutes ago   /bin/sh -c #(nop) ADD file:c7624c195e7c047ee...   67.4MB
c057ab4a7d18   6 minutes ago   /bin/sh -c #(nop) WORKDIR /app                  0B
63fb6c823893   6 minutes ago   /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
9304102c278e   6 minutes ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
1869b73a8999   2 years ago     /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago     /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago     /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago     /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago     /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
<missing>      2 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago     /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

#镜像也推送了两层一样大小
[root@localhost old-nochown]# docker push registry.xxx.com/layer/build:old
The push refers to repository [registry.xxx.com/layer/build]
bb35157fcb0b: Pushing [=============>                                     ]  18.35MB/67.45MB
3c0641004863: Pushed
6ed0abaff975: Pushing [=====================>                             ]  28.38MB/67.45MB
aa0794231b2c: Pushed
c33745b35097: Layer already exists
2105884a1756: Layer already exists
174f56854903: Layer already exists

优化Dockerfile

原因知道了。优化思路是先创建目录并递归授权。同时构建出来的jar的权限可以通过COPY 指定1001属主属组。

bash 复制代码
FROM registry.xxx.com/base/oracle-jdk:8u201
ENV TZ=Asia/Shanghai
ENV LC_ALL en_US.utf8
RUN mkdir -pv /app/{bin,lib,logs} && ln -s /app/logs /app/log && chown 1001:1001 -R /app
WORKDIR /app
COPY  --chown=1001:1001 ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
COPY  --chown=1001:1001 ./entrypoint.sh /app/bin/entrypoint.sh
ENTRYPOINT  exec bash /app/bin/entrypoint.sh

优化后的镜像只有COPY这一层的jar包了。

bash 复制代码
docker image history registry.xxx.com/layer/build:old-mkdir
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
b9fc3a8a97f2   29 hours ago   /bin/sh -c #(nop)  ENTRYPOINT ["/bin/sh" "-c...   0B
c823448f9582   29 hours ago   /bin/sh -c #(nop) COPY --chown=1001:1001file...   128B
9a997f3962bf   29 hours ago   /bin/sh -c #(nop) COPY --chown=1001:1001file...   67.4MB
f272c4e64f87   29 hours ago   /bin/sh -c #(nop) WORKDIR /app                  0B
1a526d3df7c2   29 hours ago   /bin/sh -c mkdir -pv /app/{bin,lib,logs} && ...   9B
63fb6c823893   30 hours ago   /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
9304102c278e   30 hours ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
1869b73a8999   2 years ago    /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago    /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago    /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago    /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago    /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
<missing>      2 years ago    /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago    /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago    /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

基于spring boot 分层构建方式

探索基于分层构建原理

直接上手官方文档的demo 把官方文档demo的多阶段构建拆分一下。

bash 复制代码
cat Dockerfile
FROM registry.xxx.com/base/oracle-jdk:8u201 as builder
WORKDIR /app
COPY --chown=1001:1001 ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
RUN java -Djarmode=layertools -jar /app/lib/xxx-1.0.0.jar extract

一阶段实际就是将jar解压按照spring boot layers.idx文件中的分层方式将依赖和业务代码分层。

bash 复制代码
- "dependencies":
  - BOOT-INF/lib/library1.jar
  - BOOT-INF/lib/library2.jar
- "spring-boot-loader":
  - org/springframework/boot/loader/JarLauncher.class
  - org/springframework/boot/loader/jar/JarEntry.class
- "snapshot-dependencies":
  - BOOT-INF/lib/library3-SNAPSHOT.jar
- "application":
  - META-INF/MANIFEST.MF
  - BOOT-INF/classes/a/b/C.class

进入到容器中可以看到被解压为4个目录:

csharp 复制代码
[root@b762a63589c1 app]# ls
application  dependencies  lib  logs  snapshot-dependencies  spring-boot-loader

存储占用如下:其中不出意外dependencies也就是依赖库占用是最大的 业务代码只有可怜的304K🤔。

bash 复制代码
[root@29d87aaf64b9 app]# du -lh  --max-depth=1
304K    ./application
65M     ./dependencies
0       ./logs
20K     ./snapshot-dependencies
420K    ./spring-boot-loader
65M     ./lib
130M    .

基于分层构建构建制品镜像

在官方的demo上修改得到完整的Dockerfile。其中优化了entrypoint脚本,采用分层构建后启动应用不能采用传统的java $JAVA_OPTS -jar xxx.jar这方式启动应用。要使用java org.springframework.boot.loader.JarLauncher启动应用因此jvm参数需要通过脚本接受容器的环境变量来传入。

bash 复制代码
FROM registry.xxx.com/base/oracle-jdk:8u201 as builder
WORKDIR /app
COPY --chown=1001:1001 ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
RUN java -Djarmode=layertools -jar /app/lib/xxx-1.0.0.jar extract

FROM registry.xxx.com/base/oracle-jdk:8u201
ENV TZ=Asia/Shanghai
ENV LC_ALL en_US.utf8
RUN mkdir -pv /app/logs && ln -s /app/logs /app/log && chown 1001:1001 -R /app
WORKDIR /app
COPY --chown=1001:1001 --from=builder /app/dependencies/ ./
COPY --chown=1001:1001 --from=builder /app/spring-boot-loader/ ./
COPY --chown=1001:1001 --from=builder /app/snapshot-dependencies/ ./
COPY --chown=1001:1001 --from=builder /app/application/ ./
CMD ["exec"]
ENTRYPOINT ["bash","/app/entrypoint.sh"]

entrypoint.sh脚本使用exec将java作为容器1号进程,避免无法接受linux 信号导致java进程无法正常退出。

bash 复制代码
#!/bin/bash
if [ -f /opt/cm/before.sh ]; then
source /opt/cm/before.sh;
fi
exec java $JAVA_OPTS org.springframework.boot.loader.JarLauncher

构建镜像

sql 复制代码
[root@localhost new]# docker build -t registry.xxx.com/layer/build:new .
Sending build context to Docker daemon  67.45MB
Step 1/14 : FROM registry.xxx.com/base/oracle-jdk:8u201 as builder
 ---> 1869b73a8999
Step 2/14 : WORKDIR /app
 ---> Using cache
 ---> 6973e49f31fa
Step 3/14 : COPY --chown=1001:1001 ./xxx-1.0.0.jar /app/lib/xxx-1.0.0.jar
 ---> Using cache
 ---> c5a17d5969ea
Step 4/14 : RUN java -Djarmode=layertools -jar /app/lib/xxx-1.0.0.jar extract
 ---> Using cache
 ---> 911074c3ef21
Step 5/14 : FROM registry.xxx.com/base/oracle-jdk:8u201
 ---> 1869b73a8999
Step 6/14 : ENV TZ=Asia/Shanghai
 ---> Using cache
 ---> 9304102c278e
Step 7/14 : ENV LC_ALL en_US.utf8
 ---> Using cache
 ---> 63fb6c823893
Step 8/14 : RUN mkdir -pv /app/logs && ln -s /app/logs /app/log && chown 1001:1001 -R /app
 ---> Running in 9cac9cb86507
mkdir: created directory '/app'
mkdir: created directory '/app/logs'
Removing intermediate container 9cac9cb86507
 ---> 858e77315e6b
Step 9/14 : WORKDIR /app
 ---> Running in 81c7173692fc
Removing intermediate container 81c7173692fc
 ---> 5c19ddda3114
Step 10/14 : COPY --chown=1001:1001 --from=builder /app/dependencies/ ./
 ---> 078e3f4a199c
Step 11/14 : COPY --chown=1001:1001 --from=builder /app/spring-boot-loader/ ./
 ---> 1542209ccc8b
Step 12/14 : COPY --chown=1001:1001 --from=builder /app/snapshot-dependencies/ ./
 ---> 75a9584e0952
Step 13/14 : COPY --chown=1001:1001 --from=builder /app/application/ ./
 ---> 555270edceea
Step 14/14 : ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
 ---> Running in fe99278683a2
Removing intermediate container fe99278683a2
 ---> 2cce0deab7e2
Successfully built 2cce0deab7e2
Successfully tagged registry.xxx.com/layer/build:new

查看分层详情,可以看到jar被拆分成4层分别由copy指令创建。

bash 复制代码
[root@localhost ~]# docker image history registry.xxx.com/layer/build:new
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
2cce0deab7e2   28 hours ago   /bin/sh -c #(nop)  ENTRYPOINT ["java" "org.s...   0B
555270edceea   28 hours ago   /bin/sh -c #(nop) COPY dir:2f5975d11563ae449...   248kB
75a9584e0952   28 hours ago   /bin/sh -c #(nop) COPY dir:a3bb0870001a0ef25...   18.5kB
1542209ccc8b   28 hours ago   /bin/sh -c #(nop) COPY dir:16d00ea1f180914e2...   252kB
078e3f4a199c   28 hours ago   /bin/sh -c #(nop) COPY dir:1d3190ed598b634a5...   67.1MB
5c19ddda3114   28 hours ago   /bin/sh -c #(nop) WORKDIR /app                  0B
858e77315e6b   28 hours ago   /bin/sh -c mkdir -pv /app/logs && ln -s /app...   9B
63fb6c823893   30 hours ago   /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
9304102c278e   30 hours ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
1869b73a8999   2 years ago    /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago    /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago    /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago    /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago    /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
<missing>      2 years ago    /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago    /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago    /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

对比发现jar包被拆分了。

bash 复制代码
[root@localhost new]# diff old.info  new.info
1,16c1,18
< IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
< b9fc3a8a97f2   About an hour ago   /bin/sh -c #(nop)  ENTRYPOINT ["/bin/sh" "-c...   0B
< c823448f9582   About an hour ago   /bin/sh -c #(nop) COPY --chown=1001:1001file...   128B
< 9a997f3962bf   About an hour ago   /bin/sh -c #(nop) COPY --chown=1001:1001file...   67.4MB
< f272c4e64f87   About an hour ago   /bin/sh -c #(nop) WORKDIR /app                  0B
< 1a526d3df7c2   About an hour ago   /bin/sh -c mkdir -pv /app/{bin,lib,logs} && ...   9B
< 63fb6c823893   2 hours ago         /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
< 9304102c278e   2 hours ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
< 1869b73a8999   2 years ago         /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
< <missing>      2 years ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
< <missing>      2 years ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
< <missing>      2 years ago         /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
< <missing>      2 years ago         /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
< <missing>      2 years ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
< <missing>      2 years ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
< <missing>      2 years ago         /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB
---
> IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
> 2cce0deab7e2   8 minutes ago   /bin/sh -c #(nop)  ENTRYPOINT ["java" "org.s...   0B
> 555270edceea   8 minutes ago   /bin/sh -c #(nop) COPY dir:2f5975d11563ae449...   248kB
> 75a9584e0952   8 minutes ago   /bin/sh -c #(nop) COPY dir:a3bb0870001a0ef25...   18.5kB
> 1542209ccc8b   8 minutes ago   /bin/sh -c #(nop) COPY dir:16d00ea1f180914e2...   252kB
> 078e3f4a199c   8 minutes ago   /bin/sh -c #(nop) COPY dir:1d3190ed598b634a5...   67.1MB
> 5c19ddda3114   8 minutes ago   /bin/sh -c #(nop) WORKDIR /app                  0B
> 858e77315e6b   8 minutes ago   /bin/sh -c mkdir -pv /app/logs && ln -s /app...   9B
> 63fb6c823893   2 hours ago     /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
> 9304102c278e   2 hours ago     /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
> 1869b73a8999   2 years ago     /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
> <missing>      2 years ago     /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
> <missing>      2 years ago     /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
> <missing>      2 years ago     /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
> <missing>      2 years ago     /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
> <missing>      2 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
> <missing>      2 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
> <missing>      2 years ago     /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

推送到仓库

yaml 复制代码
[root@localhost new]# docker push registry.xxx.com/layer/build:new
The push refers to repository [registry.xxx.com/layer/build]
e5409ea62302: Pushed
7167dfa406ea: Pushed
cf7e94a2dc11: Pushed
8e261e1bae2c: Pushed
770c31a84800: Pushed
c33745b35097: Layer already exists
2105884a1756: Layer already exists
174f56854903: Layer already exists
new: digest: sha256:faef10681394c01d1c2973ed10c7c33e7289eec25f22c90d085f6eef96ce3bff size: 2001

验证模拟开发推送代码更新镜像

开发摸了一天🐟终于开发出新版本

csharp 复制代码
[root@localhost new]# md5sum  bc-1.0.1.jar  bc-1.0.0.jar
3792d3178a4e07708052b7effa9b12f8  xxx-1.0.1.jar
8ee570b94977668631355cb49c5d7cf1  xxx-1.0.0.jar

构建新版本,构建过程阶段二中使用了cache 仅更新了 application层

sql 复制代码
[root@localhost new]# docker image build -t  registry.xxx.com/layer/build:new-1.0.1 .
Sending build context to Docker daemon  134.9MB
Step 1/16 : FROM registry.xxx.com/base/oracle-jdk:8u201 as builder
 ---> 1869b73a8999
Step 2/16 : WORKDIR /app
 ---> Using cache
 ---> 6973e49f31fa
Step 3/16 : COPY --chown=1001:1001 ./xxx-1.0.1.jar /app/lib/xxx-1.0.1.jar
 ---> b219210fd8ab
Step 4/16 : RUN java -Djarmode=layertools -jar /app/lib/xxx-1.0.1.jar extract
 ---> Running in d099c10b653c
Removing intermediate container d099c10b653c
 ---> 66a8593b0291
Step 5/16 : FROM registry.xxx.com/base/oracle-jdk:8u201
 ---> 1869b73a8999
Step 6/16 : ENV TZ=Asia/Shanghai
 ---> Using cache
 ---> 9304102c278e
Step 7/16 : ENV LC_ALL en_US.utf8
 ---> Using cache
 ---> 63fb6c823893
Step 8/16 : RUN mkdir -pv /app/logs && ln -s /app/logs /app/log && chown 1001:1001 -R /app
 ---> Using cache
 ---> 858e77315e6b
Step 9/16 : WORKDIR /app
 ---> Using cache
 ---> 5c19ddda3114
 Step 10/16 : COPY --chown=1001:1001 ./entrypoint.sh /app/entrypoint.sh
 ---> Using cache
 ---> c47b74bb8cf9
Step 11/16 : COPY --chown=1001:1001 --from=builder /app/dependencies/ ./
 ---> Using cache
 ---> 078e3f4a199c
Step 12/16 : COPY --chown=1001:1001 --from=builder /app/spring-boot-loader/ ./
 ---> Using cache
 ---> 1542209ccc8b
Step 13/16 : COPY --chown=1001:1001 --from=builder /app/snapshot-dependencies/ ./
 ---> Using cache
 ---> 75a9584e0952
Step 14/16 : COPY --chown=1001:1001 --from=builder /app/application/ ./
 ---> 0f138b106caf
Step 15/16 : CMD ["exec"]
 ---> Using cache
 ---> a1170ae7a20e
Step 16/16 : ENTRYPOINT ["bash","/app/entrypoint.sh"]
 ---> Using cache
 ---> 5a6bb7613fc8
Successfully built 5a6bb7613fc8
Successfully tagged registry.xxx.com/layer/build:new-1.0.1

推送到仓库可以看到仅推送了application层 只有300K

arduino 复制代码
docker push registry.xxx.com/layer/build:new-1.0.1
The push refers to repository [registry.xxx.com/layer/build]
c33a5c6456bd: Pushed
7167dfa406ea: Layer already exists
cf7e94a2dc11: Layer already exists
8e261e1bae2c: Layer already exists
770c31a84800: Layer already exists
c33745b35097: Layer already exists
2105884a1756: Layer already exists
174f56854903: Layer already exists
new-1.0.1: digest: sha256:53647bb45f0f0bb5bb8d56f14cd40deb22f0d5e4fce1200fed1c225a516dddb5 size: 2001

验证镜像

java 复制代码
[root@localhost new]# docker run -it --rm -u 1001:1001  -e JAVA_OPTS="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintCommandLineFlags"  registry.xxx.com/layer/build:new-1.0.1

可以看到打印出了堆栈信息(容器默认是不开启的)应用成功启动😋

ruby 复制代码
[root@localhost ~]# docker run -it --rm -u 1001:1001  -e JAVA_OPTS="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintCommandLineFlags"  registry.xxx.com/layer/build:new-1.0.1
-XX:InitialHeapSize=130478208 -XX:MaxHeapSize=2087651328 -XX:+PrintCommandLineFlags -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
{Heap before GC invocations=1 (full 0):
 PSYoungGen      total 37888K, used 32768K [0x00000000d6800000, 0x00000000d9200000, 0x0000000100000000)
  eden space 32768K, 100% used [0x00000000d6800000,0x00000000d8800000,0x00000000d8800000)
  from space 5120K, 0% used [0x00000000d8d00000,0x00000000d8d00000,0x00000000d9200000)
  to   space 5120K, 0% used [0x00000000d8800000,0x00000000d8800000,0x00000000d8d00000)
 ParOldGen       total 86016K, used 0K [0x0000000083800000, 0x0000000088c00000, 0x00000000d6800000)

  eden space 32768K, 0% used [0x00000000d6800000,0x00000000d6800000,0x00000000d8800000)
  from space 5120K, 72% used [0x00000000d8800000,0x00000000d8ba1748,0x00000000d8d00000)
  to   space 5120K, 0% used [0x00000000dad00000,0x00000000dad00000,0x00000000db200000)
 ParOldGen       total 86016K, used 8K [0x0000000083800000, 0x0000000088c00000, 0x00000000d6800000)
  object space 86016K, 0% used [0x0000000083800000,0x0000000083802000,0x0000000088c00000)
 Metaspace       used 6799K, capacity 7074K, committed 7168K, reserved 1056768K
  class space    used 820K, capacity 935K, committed 1024K, reserved 1048576K
}
...
2023-08-17 20:50:42.253  INFO 1 --- [           main] org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.<init>(EndpointLinksResolver.java:58) - [] : Exposing 1 endpoint(s) beneath base path '/actuator'
2023-08-17 20:50:42.315  INFO 1 --- [           main] org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - [] : Starting ProtocolHandler ["http-nio-8082"]
2023-08-17 20:50:42.349  INFO 1 --- [           main] org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:220) - [] : Tomcat started on port(s): 8082 (http) with context path '/xxx'
2023-08-17 20:50:42.376  INFO 1 --- [           main] org.springframework.boot.StartupInfoLogger.logStarted(StartupInfoLogger.java:61) - [] : Started Application in 11.242 seconds (JVM running for 12.553)

对比两个版本可以发现只有application成hash值不一样 代码量增加了253kB-248kB=5KB

bash 复制代码
[root@localhost new]# docker image history  registry.xxx.com/layer/build:new
IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
2cce0deab7e2   About an hour ago   /bin/sh -c #(nop)  ENTRYPOINT ["java" "org.s...   0B
555270edceea   About an hour ago   /bin/sh -c #(nop) COPY dir:2f5975d11563ae449...   248kB
75a9584e0952   About an hour ago   /bin/sh -c #(nop) COPY dir:a3bb0870001a0ef25...   18.5kB
1542209ccc8b   About an hour ago   /bin/sh -c #(nop) COPY dir:16d00ea1f180914e2...   252kB
078e3f4a199c   About an hour ago   /bin/sh -c #(nop) COPY dir:1d3190ed598b634a5...   67.1MB
5c19ddda3114   About an hour ago   /bin/sh -c #(nop) WORKDIR /app                  0B
858e77315e6b   About an hour ago   /bin/sh -c mkdir -pv /app/logs && ln -s /app...   9B
63fb6c823893   3 hours ago         /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
9304102c278e   3 hours ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
1869b73a8999   2 years ago         /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago         /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago         /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
<missing>      2 years ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago         /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB
[root@localhost new]# docker image history  registry.xxx.com/layer/build:new-1.0.1
IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
76aa6233354a   40 minutes ago      /bin/sh -c #(nop)  ENTRYPOINT ["java" "org.s...   0B
0f138b106caf   40 minutes ago      /bin/sh -c #(nop) COPY dir:4d21cc5ce0d92794b...   253kB
75a9584e0952   About an hour ago   /bin/sh -c #(nop) COPY dir:a3bb0870001a0ef25...   18.5kB
1542209ccc8b   About an hour ago   /bin/sh -c #(nop) COPY dir:16d00ea1f180914e2...   252kB
078e3f4a199c   About an hour ago   /bin/sh -c #(nop) COPY dir:1d3190ed598b634a5...   67.1MB
5c19ddda3114   About an hour ago   /bin/sh -c #(nop) WORKDIR /app                  0B
858e77315e6b   About an hour ago   /bin/sh -c mkdir -pv /app/logs && ln -s /app...   9B
63fb6c823893   3 hours ago         /bin/sh -c #(nop)  ENV LC_ALL=en_US.utf8        0B
9304102c278e   3 hours ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
1869b73a8999   2 years ago         /bin/sh -c set -ex;   cd /tmp;   curl -fsSLO...   302MB
<missing>      2 years ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8 JAVA_U...   0B
<missing>      2 years ago         /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai LANG...   0B
<missing>      2 years ago         /bin/sh -c set -ex;   yum update -y;   yum i...   116MB
<missing>      2 years ago         /bin/sh -c #(nop)  LABEL maintainer=currycan...   0B
<missing>      2 years ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      2 years ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      2 years ago         /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4...   204MB

上述对开发没有恶意,大家都是辛苦勤劳上进的打工人。 哈哈哈又是摸🐟的一天 ---Author Logn

引用:[spring boot官方文档](Container Images (spring.io))

相关推荐
JH30739 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
qq_124987075312 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_12 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
2301_8187320612 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
汤姆yu16 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶16 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip17 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
JavaGuide18 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot
figo10tf18 小时前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
zhangyi_viva18 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端