使用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执行启动脚本
目录
相关文章
|
5月前
|
编解码 C++
cocos2d-x C++ 工程初探
cocos2d-x C++ 工程初探
|
5月前
|
Ubuntu C++ Docker
Docker的基本指令和HTML/PYTHON/C++的简单创建示例
Docker的基本指令和HTML/PYTHON/C++的简单创建示例
|
15天前
|
Java 持续交付 项目管理
使用Maven进行项目管理:提高Java Web开发的效率
Maven 是一款强大的项目管理和构建自动化工具,广泛应用于Java社区。它通过依赖管理、构建生命周期管理、插件机制和多模块项目支持等功能,简化了项目的构建过程,提高了开发效率。本文将介绍Maven的核心功能及其在Java Web开发中的应用。
34 0
|
2月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
137 1
|
3月前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
52 1
|
3月前
|
Rust 安全 Java
Java代码规范--排版,命名.:Rust能否撼动C++的王座?
系统编程是计算机科学的核心,C++长期占据主导地位,但其内存安全问题备受诟病。Rust以安全性为核心,通过所有权和生命周期概念避免了野指针和内存泄漏。此外,Rust的并发模型和日益丰富的生态系统使其成为现代系统编程的新选择,尤其在安全性和并发性方面表现出色。尽管C++依然强大,但Rust为开发者提供了更安全、易管理的选项,未来有望推动更多系统级应用的发展。
26 0
|
4月前
|
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++ 计算斐波那契数列以提高效率。**总结** 混合编程增强性能, 但增加复杂性, 使用前需谨慎评估。
141 4
|
4月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
168 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
3月前
|
算法 Java Linux
Intellij Java JNI 调用 C++
Intellij Java JNI 调用 C++
40 0
|
4月前
|
存储 Java Maven
Maven依赖全爆红,一刷新就JAVA_HOME environment variable is not defined correctlyThis environment variable is
Maven依赖全爆红,一刷新就JAVA_HOME environment variable is not defined correctlyThis environment variable is
下一篇
无影云桌面