使用maven assembly完美Docker化Java与C++混合工程

简介: 我们都知道基于maven的Java工程,使用`mvn package`命令即可实现构建,Docker化只需将构建结果COPY到镜像中就完成了,如果是Spring Boot工程,只需要拷贝一个jar进去。 但是,如果我们的工程是一个Java和C++混合的工程,Docker化就没有那么简单了。 C++构建的so文件不像Java构建的jar,可以直接复制到镜像中(只要镜像中的Java版本和构

我们都知道基于maven的Java工程,使用mvn package命令即可实现构建,Docker化只需将构建结果COPY到镜像中就完成了,如果是Spring Boot工程,只需要拷贝一个jar进去。

但是,如果我们的工程是一个Java和C++混合的工程,Docker化就没有那么简单了。

C++构建的so文件不像Java构建的jar,可以直接复制到镜像中(只要镜像中的Java版本和构建环境中的版本一致),so与操作系统环境上的很多因素有关,我们不敢贸然将实现构建好的so复制到镜像中。这就要求我们要将C++的源代码复制到镜像中,然后在镜像中构建,最后删除源代码。

随之而来的问题是,C++的源代码如何使用mvn命令一起打包?为什么会有这样的疑问呢?因为在持续集成/持续发布的流程中,从我们提交代码到工程以Docker镜像的形式上线,需要经历构建平台(阿里巴巴内部使用的是AONE)。我们通常用一条'`mvn'命令告诉构建平台构建Java,但面对混合工程,我们也许要写一堆脚本了。这样不优雅,这应该是我们的直觉,所以才有上述的问题。这个问题的答案是使用maven的assembly插件。

我们通过在工程根目录下的pom.xml中配置该插件:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <finalName>${YOUR_MICRO_SERVICE_NAME}</finalName>
        <appendAssemblyId>false</appendAssemblyId>
        <descriptors>
            <descriptor>src/main/assembly/assembly.xml</descriptor>
        </descriptors>
    </configuration>
</plugin>

相应的assembly.xml如下:

<assembly>
    <id>assembly</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>dir</format>
    </formats>
    <fileSets>
        <fileSet>
            <includes>
                <include>${project.basedir}/${YOUR_JAVA_SRC_DIRECTORY}/target/${YOUR_JAR}</include>
            </includes>
            <outputDirectory>/</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/${YOUR_CPP_SRC_DIRECTORY}</directory>
            <outputDirectory>/${CPP_DIRCTORY}</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

这样配置后,告诉构建平台执行mvn clean install assembly:assembly -DskipTests这个构建命令,然后到target/${YOUR_ARTIFACTID}这个构建输出目录下面tgz包即可。

这里,我踩过一个小坑。最初只在assembly.xml中定义了一个<fileSet>,然后通过定义多条<include>来打包jar和C++源代码。因为C++源代码只有一层目录:

<include>${project.basedir}/${YOUR_CPP_SRC_DIRECTORY}/*</include>

但没多久,C++的开发者根据业务逻辑,增加了一层目录,这还好,于是这个定义变成:

<include>${project.basedir}/${YOUR_CPP_SRC_DIRECTORY}/*</include>
<include>${project.basedir}/${YOUR_CPP_SRC_DIRECTORY}/*/*</include>

又没过几天,C++的源代码出现了4层目录,我石化了……所以才有了第二个<fileSet>。其实最初就应该这样设计,只是那个时间点觉得一个<fileSet>更优雅:(。

有了tgz包,我们的注意力就可以集中到Dockerfile的编写上了。依次执行如下步骤即可:

  1. 解压缩tgz
  2. 通过软连接处理32位和64位lib、so.xxx
  3. 进入C++源代码目录,执行make
  4. 复制构建好的so到/usr/lib64
  5. 删除tgz包,删除C++源代码目录
  6. 复制jar到指定位置
  7. 复制各种脚本,配置各种日志路径,修改目录或者文件的权限
  8. 使用VOLUME挂载日志等路径,以免镜像的新容器启动后丢失日志等文件
  9. 使用EXPOSE开放Docker容器的端口
  10. 使用ENV设定服务所需的环境变量
  11. 使用ENTRYPOINT执行启动脚本
目录
相关文章
|
2月前
|
Java Maven 容器
java依赖冲突解决问题之Maven在编译打包过程中对依赖的jar包如何解决
java依赖冲突解决问题之Maven在编译打包过程中对依赖的jar包如何解决
|
16天前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
58 1
|
22天前
|
Java 数据库连接 Maven
【Java笔记+踩坑】Maven高级
分模块开发、依赖传递与冲突问题、 可选依赖和排除依赖、聚合和继承、属性、多环境配置与应用、私服安装和使用
【Java笔记+踩坑】Maven高级
|
2月前
|
前端开发 Java 编译器
【前端学java】如何从前端视角快速学习Maven
【8月更文挑战第12天】如何从前端视角快速学习Maven
43 2
【前端学java】如何从前端视角快速学习Maven
|
2月前
|
前端开发 Java Maven
【前端学java】全网最详细的maven安装与IDEA集成教程!
【8月更文挑战第12天】全网最详细的maven安装与IDEA集成教程!
71 2
【前端学java】全网最详细的maven安装与IDEA集成教程!
|
2月前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
41 1
|
2月前
|
Java Android开发
如何使用IDEA创建一个简单的java工程?
这篇文章提供了使用IntelliJ IDEA创建简单Java工程的步骤,包括在`src`目录下建立两个特定的包。
如何使用IDEA创建一个简单的java工程?
|
2月前
|
Rust 安全 Java
Java代码规范--排版,命名.:Rust能否撼动C++的王座?
系统编程是计算机科学的核心,C++长期占据主导地位,但其内存安全问题备受诟病。Rust以安全性为核心,通过所有权和生命周期概念避免了野指针和内存泄漏。此外,Rust的并发模型和日益丰富的生态系统使其成为现代系统编程的新选择,尤其在安全性和并发性方面表现出色。尽管C++依然强大,但Rust为开发者提供了更安全、易管理的选项,未来有望推动更多系统级应用的发展。
17 0
|
3月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
【7月更文挑战第28天】在 Android 开发中, NDK 让 Java 与 C++ 混合编程成为可能, 从而提升应用性能。**为何选 NDK?** C++ 在执行效率与内存管理上优于 Java, 特别适合高性能需求场景。**环境搭建** 需 Android Studio 和 NDK, 工具如 CMake。**JNI** 构建 Java-C++ 交互, 通过声明 `native` 方法并在 C++ 中实现。**实战** 示例: 使用 C++ 计算斐波那契数列以提高效率。**总结** 混合编程增强性能, 但增加复杂性, 使用前需谨慎评估。
112 4
|
2月前
|
XML Java Maven
Java 中的 Maven 和 Ant 的区别
【8月更文挑战第22天】
47 0
下一篇
无影云桌面