idea docker 镜像生成太慢太大问题

文章目录

  • 前言
  • 一、更小的jdk基础镜像
  • [二、服务瘦包(thin jar)](#二、服务瘦包(thin jar))
    • [2.1 maven](#2.1 maven)
    • [2.2 修改dockerfile](#2.2 修改dockerfile)
    • [2.3 container run options](#2.3 container run options)
  • [三、 基础jdk镜像入手?](#三、 基础jdk镜像入手?)
  • 总结

前言

idea docker 内网应用实践遗留问题

  1. idea docker插件 build 服务镜像太慢
  2. 服务镜像太大

一、更小的jdk基础镜像

精简的jdk镜像 123MB,jdk17-alpine

二、服务瘦包(thin jar)

打包成瘦包(thin jar)在许多情况下都有明显的优势,尤其是在企业级和分布式部署环境中。以下是瘦包的一些主要好处:

  • 减小文件尺寸: 瘦包仅包含应用本身的代码和必需的资源,不包含外部依赖。这通常会导致文件尺寸比包含所有依赖的胖包(fat jar)小得多,这使得上传到服务器或存储在仓库中更快速、更高效。

  • 快速构建: 在构建过程中,由于不需要打包所有的依赖,构建瘦包通常比构建胖包要快。

  • 部署灵活性: 瘦包允许在部署时选择性地添加依赖。你可以根据不同的环境(开发、测试、生产)来管理依赖,这意味着可以有针对性地解决依赖性问题。

  • 共享依赖: 如果多个应用部署在同一服务器上,它们可以共享相同的依赖库,减少重复的依赖文件,节省空间。

  • 依赖管理: 瘦包使得依赖管理更加明确。所有的外部依赖都在构建或部署过程中被解决,这样可以更容易地处理依赖之间的冲突。

  • 更新和维护: 如果需要更新或替换某个依赖,你可以单独更新那个依赖,而不需要重新构建整个应用的胖包。

  • 资源占用: 对于基于微服务的架构,使用瘦包可以在微服务之间共享公共的运行时环境,减少了每个服务实例的资源占用。

  • 安全性: 在有严格安全要求的环境中,使用瘦包可以更容易地进行安全审计,因为你可以精确地知道哪些库是运行时必需的。

  • 与容器技术协同: 在使用容器技术(如 Docker)时,瘦包可以轻松结合基础镜像中的依赖,便于创建轻量级的容器镜像。

然而,瘦包也有它的缺点,例如可能需要额外的依赖管理工具或处理依赖传递的复杂性,因此在决定使用瘦包时,需要根据项目的具体需求和部署环境来权衡利弊。

2.1 maven

plugins 添加maven打包策略

xml 复制代码
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.12.RELEASE</version>
                <configuration>
                    <mainClass>com.cuzue.file.FileServerApplication</mainClass>
                    <layout>ZIP</layout>
                    <!-- 打增量包时需要includes部分, 要打全量包删除includes -->
                    <includes>
                        <include>
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>../lib</outputDirectory>
                            <excludeTransitive>false</excludeTransitive>
                            <stripVersion>false</stripVersion>
                            <!--complie和runtime的包都打到lib中,否则可能lib缺包-->
                            <includeScope>runtime</includeScope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

2.2 修改dockerfile

主要修改:

  • 外部lib 容器卷挂载
  • JVM使用/dev/urandom作为熵源来加快随机数的生成速度-Djava.security.egd=file:/dev/./urandom
bash 复制代码
FROM jdk-alpine:17
LABEL maintainer="cuzue 991446772@qq.com"
VOLUME ["/tmp","/mnt/upload","/server/lib"]
ADD target/*.jar file.jar
ENV SERVER_PORT="8000" XMS="1024m" XMX="1024m" NACOS_CONFIG_ADDR="nacos.server:8848" NACOS_CONFIG_SPA="intelligence-gsdss" NACOS_DISCOVERY_ADDR="nacos.server:8848" NACOS_DISCOVERY_SPA="intelligence-gsdss" MAIN_CLASS="com.cuzue.file.FileServerApplication"
ENTRYPOINT java -server -Xms$XMS -Xmx$XMX -Dserver.port=$SERVER_PORT -Dloader.path=/server/lib/ -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.server-addr=$NACOS_CONFIG_ADDR -Dspring.cloud.nacos.config.namespace=$NACOS_CONFIG_SPA -Dspring.cloud.nacos.discovery.server-addr=$NACOS_DISCOVERY_ADDR -Dspring.cloud.nacos.discovery.namespace=$NACOS_DISCOVERY_SPA -jar file.jar $MAIN_CLASS

2.3 container run options

  • 上传服务package生成的lib包到宿主机/data/server/app/lib
  • docker容器启动指定容器卷-v /data/server/app/lib:/server/lib
    容器卷指定路径,宿主机/data/server/app/lib容器路径/server/lib

三、 基础jdk镜像入手?

下一步思路多阶段构建或更好的方案,没有具体实践,不知道怎么弄,有经验的小伙伴希望可以分享一下可行性高的方案

打包镜像时不将jdk基础镜像打包到每一个服务中,类似挂载jdk容器卷可以实现,但是这种方式并不是Docker的最佳实践,且可能会导致预期之外的问题,特别是在使用不同版本的JDK或涉及到JDK内部路径变动时。

GPT的建议:

在Docker中,如果你想要避免将JDK基础镜像打包到每一个服务的镜像中,可以采用以下几种常见的方法:

  1. 使用多阶段构建(Multi-stage build):

    多阶段构建允许你在一个Dockerfile中使用多个FROM语句。你可以在一个阶段使用包含JDK的基础镜像来编译和构建应用,然后在第二个阶段只将编译后的应用复制到一个不含JDK的轻量级基础镜像中。例如:

    bash 复制代码
    # 第一阶段:构建
    FROM maven:3.6.3-jdk-11 AS builder
    WORKDIR /app
    COPY src /app/src
    COPY pom.xml /app
    RUN mvn clean package
    
    # 第二阶段:创建最终镜像
    FROM openjdk:11-jre-slim
    COPY --from=builder /app/target/my-app.jar /app/
    CMD ["java", "-jar", "/app/my-app.jar"]

    这样做的好处是你的最终镜像大小减小,因为它不包含整个JDK,只有JRE。

  2. 使用JRE基础镜像:

    如果你的应用不需要JDK中的编译工具,而只需要运行Java字节码,你可以直接使用JRE基础镜像而不是JDK。这可以减少镜像大小并缩短下载时间。

  3. 创建自定义基础镜像:

    你可以创建一个自定义的基础镜像,其中包含了JDK和你的应用通用的其他依赖。然后,你可以在构建每个服务的Docker镜像时使用这个自定义镜像作为基础。

  4. JDK资源共享:

    如果你的多个服务部署在同一台机器上,可以考虑在Docker主机上安装JDK,并通过卷(volume)共享的方式让不同的容器使用同一个JDK。

  5. 使用精简版JDK发行版:

    对于需要JDK环境的服务,可以考虑使用精简版的JDK发行版,如AdoptOpenJDK的OpenJ9、Alibaba的Dragonwell或者Amazon的Corretto等。这些发行版往往提供了更小的容器镜像。

请注意,选择哪种方法取决于你的具体需求和约束。多阶段构建是最常见的做法,因为它提供了灵活性和优化的最终镜像大小。不过,如果你的服务确实需要JDK来运行,例如它们使用JDK特定的工具或API,那么这种情况下你可能无法避免在每个服务镜像中包含JDK。

总结

GPT的建议:

如果你在使用 IntelliJ IDEA 配合 Docker 进行镜像构建时遇到速度慢的问题,可以尝试以下几种方法来改善这个情况:

  1. 优化 Dockerfile:
  • 减少镜像层数:每条 RUNCOPYADD 指令都会创建一个新的镜像层。通过组合指令来减少层数可以减少构建时间。
  • 使用 .dockerignore 文件:排除不必要的文件和目录被复制到 Docker 上下文中,减少构建时间和镜像大小。
  • 利用构建缓存:确保更改频繁的指令放在 Dockerfile 的底部,这样可以最大化地利用 Docker 缓存。
  1. 提升硬件性能:
  • Docker 镜像构建过程中可能会占用大量的 CPU 和内存资源,确保你的开发机器有足够的资源分配给 Docker。
  • 如果使用的是虚拟机或远程 Docker 守护进程,提高网络速度和分配给虚拟机的资源可能有帮助。
  1. 使用更快的网络连接:
  • 镜像构建过程中可能需要下载基础镜像和依赖,网络速度的快慢直接影响到下载速度。
  1. 设置 Docker 镜像加速器:
  • 很多地区通过 Docker 官方镜像源下载镜像可能会比较慢,使用国内的镜像加速服务可以显著提高下载速度。
  1. 减少构建上下文大小:
  • Docker 在构建镜像时,会将当前目录(即构建上下文)发送到 Docker daemon,如果当前目录很大,会导致构建过程缓慢。减少构建上下文的大小可以提高速度。
  1. 分阶段构建(Multi-stage builds):
  • 如果你的应用构建过程包括编译等多个步骤,可以使用分阶段构建来减少最终镜像的大小,从而减少上传到仓库的时间。
  1. 预先拉取基础镜像:
  • 如果构建过程需要使用到某些特定的基础镜像,提前手动拉取这些镜像可以省去构建过程中的下载时间。
  1. 关闭 IDE 的不必要插件或服务:
  • IntelliJ IDEA 中运行的其他后台任务可能会影响到 Docker 镜像构建的性能,尝试关闭不需要的插件或服务。
  1. 定期清理 Docker:
  • 定期使用 docker system prune 清理无用的 Docker 对象(例如悬空的镜像和停止的容器),可以释放磁盘空间,有时也能提高构建速度。

检查这些方面,并根据你的具体情况进行调整,应该能够帮助你提高在 IntelliJ IDEA 中使用 Docker 打包镜像的速度。如果这些方法都不奏效,可能需要更详细地分析构建过程中的瓶颈。


相关推荐
HZero.chen15 分钟前
Java 匿名类简介
java·匿名类
用户31268748772017 分钟前
Java 泛型擦除到底擦掉了什么?类型安全与桥接方法深度拆解
java
暖焰核心24 分钟前
继承全解——继承、默认成员函数、切片、隐藏与虚继承
java·前端·javascript
君顾133 分钟前
外卖CPS系统开发实战指南:从架构设计到部署全流程解析
java·开发语言·外卖
奇牙coding1231 小时前
GPT-5.5 升级 GPT-5.6 接入指南:流式调用配置与常见问题
java·网络·gpt·ai
老刘的望远镜1 小时前
AgentScope Java 从零(03):Agent 的记性默认全开,我在第 50 轮翻了车
java·开发语言·javascript
yxlalm1 小时前
5.3解决超卖问题
java·spring boot·超卖
李少兄2 小时前
Java 中只有值传递吗?
java·开发语言·python
名字还没想好☜2 小时前
Spring @EventListener 事件驱动解耦实战:同步转异步、事务绑定与顺序控制
java·数据库·后端·python·spring
一木 之林2 小时前
插件、MCP、Skill 的区别?
java·c++·人工智能