【疑難雜癥2025-003】Java-mvn項目在gitlab-ci構建鏡像時遇到的問題和解決方案

本文由Markdown語法編輯器編輯完成.

1.背景:

之前從同事手里接手了一個java的項目,是用maven構建項目的.由于我們的服務都是基于docker來部署的,因此這個java項目也是要編譯成docker image然后發布.但是之前一直都是在開發者的本機電腦上進行構建,雖然代碼已經部署在了公司的Gitlab倉庫,但是沒有配置CI/CD. 因此,該項目每次新增需求后,我就在我自己的服務器上面,運行mvn clean && mvn install編出鏡像,然后就docker push到公司的hub上面了.

這個模式已經持續了兩三年.主要也是因為這個項目,目前基本只有我一個人在維護,而且代碼也基本穩定了,沒有太多的需求要開發.所以,每次我想把它在gitlab上面自動構建時,都因為遇到了一些問題,而放棄,轉而去做其他更緊急的事情了.但是這個問題,一直遺留著,也怪難受的.

直到最近,這個項目,也加了很多新的需求,我越來越覺得有必要,需要讓gitlab的CI來自動構建了.要不那一天我有事不在,那這個項目的修改,都不能生成鏡像了.

于是,我又一次鼓足勇氣,準備搞定這件事.大概前后經過了兩周的折騰,終于看到了gitlab上,構建成功的標識,還是蠻開心.當然過程中,也是遇到了很多很多的問題.最終在經過50多次構建后,終于是成功了.在看到構建成功的那一刻,比吃了糖還要開心.

在這里插入圖片描述

這里記錄一些主要的問題,以及解決方案,希望對后面的,有類似需求的開發者,可以借鑒一些經驗.

2. Gitlab-CI/CD構建:

按照Gitlab的要求,要想讓項目能夠實現自動構建,需要在你的項目中,添加一個.gitlab-ci.yml, 然后在gitlabci.yml里面定義好這個項目的構建步驟,以及觸發時機,和所使用的runner. 這樣當每次提交代碼到Gitlab后,便會觸發CI/CD開始工作,然后它便會按照yml中的stage, 順序依次完成所有的job, 成功后,便會在Build->Pipelines里面,顯示綠色的標識.

那么本次我在構建時遇到的主要問題是哪些呢,以下依次介紹:

2.1 修改maven鏡像,解決拉取依賴超時的問題

mvn項目在構建時,會讀取項目下面的另一個文件 settings.xml, 這個文件主要是定義在構建java項目時,從哪些倉庫拉取依賴.
這個時候,一般都可以配置國內的鏡像,這樣在拉取依賴時會比較快.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"><profiles><profile><id>multi-repos</id><repositories><repository><id>aliyunmaven</id><url>https://maven.aliyun.com/repository/public</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository><repository><id>central</id><url>https://repo.maven.apache.org/maven2</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository><repository><id>dcm4chee-online</id><url>https://www.dcm4che.org/maven2/</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories></profile></profiles><activeProfiles><activeProfile>multi-repos</activeProfile></activeProfiles>
</settings>

可以看出,我這里主要是定義了三個倉庫.

https://maven.aliyun.com/repository/public
https://repo.maven.apache.org/maven2
https://www.dcm4che.org/maven2/

配置了上面的三個倉庫地址后, maven在構建依賴時,就會從這三個倉庫中去找,哪個找到都可以, 這樣可以解決部分倉庫無法下載依賴的問題.

但是在實際構建時,還是會遇到一些jar包,拉取超時.如以下:
在這里插入圖片描述

這樣的錯誤,困擾了我很久.我在網上詢問時,一般給出的建議,都是先把需要依賴的jar包下載到本地,然后再通過mvn的指令,把它推到本地的倉庫中.這樣mvn在構建時,會優先從本地的.m2中查找,這樣就可以避免由于找不到jar包而失敗的問題了.

于是,我就先從相應的位置,把jar包下載下來,然后都拷貝到CI這臺機器的某一個目錄下面.同時在這個目錄下面,用python啟動一個http-server的服務.這樣當CI在這臺服務器構建時,就可以通過wget的方式,把包下載下來,再安裝到構建時的服務器上面了.

如下圖所示,我把在mvn構建時,提示無法下載的jar包等,提前下載下來,cp到CI所部署的這臺服務器,比如指定一個目錄,mvn-build.
然后在當前目錄下,運行python3 http.server 9008,
這樣便可以在瀏覽器上面下載CI服務器上面的文件,同時也可以在構建時,通過
wget -P /app http://172.16.10.28:9008/clib_jiio-1.2-pre-dr-b04.zip, 將服務器上面的文件,下載拷貝到/app目錄下面.

在這里插入圖片描述

為此,我專門先制作了一個用于mvn構建的鏡像,里面都把需要本地安裝的jar包,都提前安裝到這個鏡像里面.然后便可以通過mvn的構建了.

我用于構建mvn編譯環境的鏡像的Dockerfile是這樣寫的:


# 構建時的基礎鏡像為, ubuntu 24.04
FROM ubuntu:24.04 # Set environment variables, 定義環境變量.
ENV DEBIAN_FRONTEND=noninteractive
ENV MAVEN_VERSION=3.8.4
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
ENV MAVEN_HOME=/opt/maven
ENV PATH=$MAVEN_HOME/bin:$PATH# 添加代理,這樣在從官網一些依賴時,可以優化速度,解決timeout的問題.
RUN export https_proxy=http://192.168.110.201:10500;export http_proxy=http://192.168.110.201:10500;export all_proxy=http://192.168.110.201:10500;# Install dependencies
RUN apt-get update && \apt-get install -y openjdk-8-jdk wget curl unzip && \rm -rf /var/lib/apt/lists/*# Install Maven
RUN wget https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/${MAVEN_VERSION}/apache-maven-${MAVEN_VERSION}-bin.tar.gz && \tar xzf apache-maven-${MAVEN_VERSION}-bin.tar.gz -C /opt && \ln -s /opt/apache-maven-${MAVEN_VERSION} /opt/maven && \rm apache-maven-${MAVEN_VERSION}-bin.tar.gz# Set working directory
WORKDIR /app# 我提前把從官網下載的jar,zip包等,拷貝到gitlab-ci所在的服務器,如172.16.10.28. 
# 通過wget下載了文件后,然后運行 mvn install:install-file, 然后指定文件的groupId, artifactId, version, packaging(文件格式, .jar,.zip,.so等), file是它在本地的路徑.
RUN wget -P /app http://172.16.10.28:9008/clib_jiio-1.2-pre-dr-b04.zip && \mvn install:install-file \-DgroupId=com.sun.media \-DartifactId=clib_jiio \-Dversion=1.2-pre-dr-b04 \-Dpackaging=zip \-Dfile=clib_jiio-1.2-pre-dr-b04.zipRUN wget -P /app http://172.16.10.28:9008/weasis-core-img-4.3.0.jar && \mvn install:install-file \-DgroupId=org.weasis.core \-DartifactId=weasis-core-img \-Dversion=4.3.0 \-Dpackaging=jar \-Dfile=weasis-core-img-4.3.0.jarRUN wget -P /app http://172.16.10.28:9008/libopencv_java-4.3.0-dcm-linux-x86-64.so && \mvn install:install-file \-DgroupId=org.weasis.thirdparty.org.opencv \-DartifactId=libopencv_java \-Dversion=4.3.0-dcm \-Dpackaging=so \-Dclassifier=linux-x86-64 \-Dfile=libopencv_java-4.3.0-dcm-linux-x86-64.so# 通過運行ls, 可以查看是否已經將相關的包,安裝到了構建的runner里面的.m2倉庫里面.
RUN ls ~/.m2/repository/com/sun/media/clib_jiio/1.2-pre-dr-b04/clib_jiio-1.2-pre-dr-b04.zip && \ls ~/.m2/repository/org/weasis/core/weasis-core-img/4.3.0/weasis-core-img-4.3.0.jar && \ls ~/.m2/repository/org/weasis/thirdparty/org/opencv/libopencv_java/4.3.0-dcm/libopencv_java-4.3.0-dcm-linux-x86-64.so# Default command
CMD ["mvn", "-version"]

然后根據以上的Dockerfile, 就可以生成一個基礎的鏡像, 運行:

docker build -t myproject/dev/ubuntu24.04-jdk8-maven384:20250429 .

運行以后,就會生成一個鏡像,然后:

docker push  myproject/dev/ubuntu24.04-jdk8-maven384:20250429

就可以把它作為我們接下來要基于mvn, 構建java包時的基礎環境了.

以上可以作為gitlab-ci.yml的第一個stage, 我們可以把這個stage命名為build. 它的主要任務,就是基于項目的pom.xml, 基于mvn, 構建出一個項目的jar包來.

這個時候,gitlab-ci.yml里面,大概是這樣的:

# 定義緩存,加快依賴下載速度
cache:paths:- ~/.m2/repository# 定義不同的階段
stages:- build# 編譯階段
build:stage: buildimage: myproject/dev/ubuntu24.04-jdk8-maven384:20250429script:- rm -rf ~/.m2/repository/org/apache/maven/plugins/maven-clean-plugin- export MAVEN_OPTS="-Dhttp.proxyHost=192.168.110.201 -Dhttp.proxyPort=10500"- export https_proxy=http://192.168.110.201:10500;export http_proxy=http://192.168.110.201:10500;export all_proxy=http://192.168.110.201:10500;- mvn -s settings.xml clean install- ls -lh /builds/cloud/target/mypacs-1.5.1jar only:- tags

2.2 解決gitlab-ci的兩個階段無法共享jar包的問題

第一個階段,在按上述的步驟執行后,就已經成功地編譯出了項目所需要的jar包.
那么接下來,就是如何把第一步生成的jar包,在一個image中里面啟動了.

我之前的想法是,既然都已經生成了jar包了,那我就直接把它放在啟動目錄里面,就可以啟動了.因此我的Dockerfile是這么寫的:

FROM xxx.com/vendor/openjdk-8WORKDIR /usr/share/project/RUN mkdir -p ./lib
COPY ./extra/* /usr/share/project/lib/
COPY target/project-1.5.1.jar /usr/share/project/project.jar
ADD conf.yml /usr/share/project/conf.ymlENV TZ=Asia/ShanghaiENTRYPOINT ["java", "-Djava.library.path=/usr/share/project/lib/", "-jar", "/usr/share/project/project.jar"]

這樣,再運行docker build就可以完成了.但是在實際執行的時候,遇到了第二個問題.就是在執行
COPY target/project-1.5.1.jar /usr/share/project/project.jar的時候,提示這個project-1.5.1.jar Not found. 因此COPY這條指令運行失敗了.

在這里插入圖片描述
這個報錯的大概含義就是,在copy階段時,找不到制定路徑下面的這個xxx.jar包,導致COPY失敗,CI無法繼續構建.

我嘗試了好幾次,修改這個COPY jar包的源路徑,但是接連好幾次都失敗了.

后來在請教Deepseek后,找到了問題的解決方案.
這個也是在CI/CD構建過程中,最長遇到的問題,就是因為第一步和第二步的工作目錄不同,導致第二步是找不到第一步mvn build出來的jar包的.
在這里插入圖片描述

在gitlab-ci.yml中,增加這個關鍵字: artifacts. 這個關鍵字的作用是什么呢?

在 GitLab CI/CD 中,artifacts 是一個非常重要的功能,主要用于在不同 Job 或 Stage 之間傳遞文件或目錄,并可以保留構建產物供后續使用或下載。以下是它的核心作用及使用場景:

(1) 跨 Job/Stage 傳遞文件
默認情況下,每個 Job 運行在獨立的環境中,前一個 Job 生成的文件不會自動傳遞給下一個 Job。

artifacts 允許將指定文件或目錄保存下來,供后續的 Job 使用。

build:stage: buildscript:- mvn package  # 生成 target/app.jarartifacts:paths:- target/app.jar  # 保存 app.jar 供后續 Job 使用deploy:stage: deployscript:- ls -l  # 可以看到 target/app.jar 被自動下載- scp target/app.jar user@server:/deploy/

(2) 保留構建產物供下載
可以在 GitLab 的 Pipeline 頁面直接下載 artifacts(如編譯后的二進制文件、日志、測試報告等)。

適用于:
打包后的應用(.jar、.war、.exe)
測試報告(junit.xml、coverage.html)
日志文件(build.log、debug.log).

比如當我在gitlab-ci.yml的第一個Job后面,加上artifacts, 便會將mvn編譯出來的jar包保存下來,而且還可以直接從Gitlab的pipeline的頁面上,下載構建出來的jar包.
在這里插入圖片描述

在這里插入圖片描述
從上面紅框內的關鍵字可以看出: 當構建完成后,由于加了artifacts關鍵字,它會Uploading文件到服務器上,供后續需要該文件的job使用.

點擊右側紅色框內的按鈕,可以直接下載編譯出來的jar包,或者瀏覽artifacts指定目錄下面的文件.
而這個路徑里面的文件,在該pipeline后續的job里面,都是可以直接讀取和應用的.這樣也就解決了,原來多個job之間,由于各自的工作目錄不同,而導致無法共享文件的問題.

2.3 artifacts關鍵字的應用

在這里插入圖片描述
在這里插入圖片描述在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/80301.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/80301.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/80301.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【RT-Thread Studio】nor flash配置Fal分區

前置條件&#xff1a;【RT-Thread Studio】W25Q128配置 添加 FAL軟件包 配置SFUD驅動程序&#xff0c;使用FAL的設備為W25Q128 將fal_cfg.h和fal_flash_sfud_port.c提取出來&#xff0c;放到自己創建的fal_porting目錄。 修改 fal_flash_sfud_port.c struct fal_flash_dev n…

Spring MVC 視圖解析器 (ViewResolver) 如何配置? Spring Boot 是如何自動配置常見視圖解析器的?

我們來詳細分析一下視圖解析器 (ViewResolver) 的配置以及 Spring Boot 是如何自動配置它們的。 視圖解析器 (ViewResolver) 是什么&#xff1f; 在 Spring MVC 中&#xff0c;當控制器 (Controller) 方法處理完請求并返回一個邏輯視圖名 (String) 時&#xff0c;DispatcherS…

理解網站導航文件:robots.txt、sitemap.xml與LLMs.txt的全面解析

在當今數字化時代&#xff0c;網站不僅需要為人類用戶提供良好的瀏覽體驗&#xff0c;還需要考慮搜索引擎和人工智能系統的可訪問性。本文將深入探討三種關鍵的網站導航文件&#xff1a;傳統的robots.txt和sitemap.xml&#xff0c;以及新興的LLMs.txt&#xff0c;分析它們的功能…

leetcode 349. Intersection of Two Arrays

題目描述 題目限制0 < nums1[i], nums2[i] < 1000&#xff0c;所以可以開辟一個1001個元素的數組來做哈希表。 class Solution { public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> table(1001,0…

【軟件工程】軟件多缺陷定位方法總結

軟件多缺陷定位(Multi-Fault Localization)是軟件工程中的一個重要研究方向,旨在同時定位代碼中存在的多個缺陷(Bug)。由于多個缺陷可能相互干擾(如掩蓋錯誤行為),導致傳統單缺陷定位方法效果下降,因此需要針對多缺陷場景的特殊性設計方法。以下是常見的多缺陷定位方法…

【數據結構入門訓練DAY-30】數的劃分

文章目錄 前言一、題目二、解題思路結語 前言 本次訓練內容 訓練DFS。訓練解題思維。 一、題目 將整數n分成k份&#xff0c;且每份不能為空&#xff0c;任意兩份不能相同(不考慮順序)。 例如&#xff1a;n7&#xff0c;k3&#xff0c;下面三種分法被認為是相同的。 {1&a…

OpenCV進階操作:圖像直方圖、直方圖均衡化

文章目錄 一、圖像直方圖二、圖像直方圖的作用三、使用matplotlib方法繪制直方圖2.使用opencv的方法繪制直方圖&#xff08;劃分16個小的子亮度區間&#xff09;3、繪制彩色圖像的直方圖 四、直方圖均衡化1、繪制原圖的直方圖2、繪制經過直方圖均衡化后的圖片的直方圖3、自適應…

Open CASCADE學習|Geom2d_BezierCurve 類

概述 Open CASCADE 提供了幾何建模的強大工具集,其中 Geom2d_BezierCurve 類用于表示二維貝塞爾曲線。貝塞爾曲線在計算機圖形學和計算機輔助設計(CAD)中具有廣泛應用,本文將詳細介紹 Geom2d_BezierCurve 類及其使用方法。 貝塞爾曲線簡介 貝塞爾曲線是一種參數曲線,廣泛…

muduo源碼解析

1.對類進行禁止拷貝 class noncopyable {public:noncopyable(const noncopyable&) delete;void operator(const noncopyable&) delete;protected:noncopyable() default;~noncopyable() default; }; 2.日志 使用枚舉定義日志等級 enum LogLevel{TRACE,DEBUG,IN…

互聯網大廠Java面試實錄:Spring Boot與微服務架構在電商場景中的應用解析

&#x1f4aa;&#x1f3fb; 1. Python基礎專欄&#xff0c;基礎知識一網打盡&#xff0c;9.9元買不了吃虧&#xff0c;買不了上當。 Python從入門到精通 &#x1f601; 2. 畢業設計專欄&#xff0c;畢業季咱們不慌忙&#xff0c;幾百款畢業設計等你選。 ?? 3. Python爬蟲專欄…

關于匯編語言與程序設計——單總線溫度采集與顯示的應用

一、實驗要求 (1)握碼管的使用方式 (2)掌握DS18B20溫度傳感器的工作原理 (3)掌握單總線通信方式實現 MCU與DS18B20數據傳輸 二、設計思路 1.整體思路 通過編寫數碼管顯示程序和單總線溫度采集程序&#xff0c;結合溫度傳感報警&#xff0c;利用手指觸碰傳感器&#xff0c;當…

用html+js+css實現的戰略小游戲

效果圖: 兄弟們&#xff0c;話不多說&#xff0c;直接上代碼 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

Navicat BI 數據分析功能上線 | 數據洞察新方法

Navicat 17.2 版本一經發布&#xff0c;便以 AI 助手賦能智能交互、Snowflake 支持拓展數據連接版圖、拓展對關系型、維度以及數據倉庫 2.0 建模方法的支持等新特性與功能抓住了用戶的目光&#xff0c;但其中一項低調且實用的更新 - 在 BI 數據預覽中深度集成數據分析工具&…

【ts】defineProps數組的類型聲明

第一種&#xff1a;使用Record<string, unknown> Record<string, unknown>表示一個對象&#xff0c;鍵是string類型&#xff0c;值是未知的 import { defineProps, PropType } from vue;const props defineProps({dataList: {type: Array as PropType<Record…

OpenCv實戰筆記(4)基于opencv實現ORB特征匹配檢測

一、原理作用 ORB 原理&#xff08;Oriented FAST and Rotated BRIEF&#xff09;&#xff1a; 特征點檢測&#xff1a;使用 FAST 算法檢測角點&#xff08;關鍵點&#xff09;。 方向計算&#xff1a;為每個關鍵點分配主方向&#xff0c;增強旋轉不變性。 特征描述&#xff1a…

Unreal 從入門到精通之VR常用操作

文章目錄 前言1.如何設置VRPawn視角的位置。2.如何播放視頻3.如何播放VR全景視頻。4.如何打開和關閉VR模式。前言 我們使用Unreal5 開發VR 項目的時候,會遇到很多常見問題。 比如: 1.如何設置VRPawn視角的位置。 2.如何播放視頻。 3.如何播放VR全景視頻。 4.如何打開和關閉V…

[論文閱讀]Deep Cross Network for Ad Click Predictions

摘要 特征工程是許多預測模型成功的關鍵。然而&#xff0c;這個過程是困難的&#xff0c;甚至需要手動特征工程或窮舉搜索。DNN能夠自動學習特征交互&#xff1b;然而&#xff0c;它們隱式地生成所有的交互&#xff0c;并且不一定有效地學習所有類型的交叉特征。在本文中&…

數據庫(MySQL)基礎

一、登錄數據庫 在linux系統中登錄數據庫的指令 mysql -h 127.48.0.236 -P 3306 -u root -p -h&#xff1a;填寫IP地址&#xff0c;指明要連接的主機。如果不加該字段表示本地主機-P&#xff1a;填寫端口號&#xff0c;指明進程。 如果不加該字段會使用默認的端口號。-u&…

遠程調試---在電腦上devtools調試運行在手機上的應用

1、啟動項目–以vite項目為例:先ipconfig查看ip地址 ,然后在vite中配置host為ip地址 2、手機上查看項目:保證手機和電腦在同一局域網, 在手機瀏覽器打開我們vite啟動的項目地址, 3、使用chii進行遠程調試 (1) 安裝 npm install chii -g (2)啟動 chii start -p 8080 (3)在…

【程序員AI入門:開發】11.從零構建智能問答引擎:LangChain + RAG 實戰手冊

1、技術選型 組件推薦方案說明文本嵌入模型sentence-transformers/all-MiniLM-L6-v2輕量級且效果較好的開源模型向量數據庫FAISS高效的本地向量檢索庫大語言模型GPT-3.5/開源LLM&#xff08;如ChatGLM3&#xff09;根據資源選擇云端或本地模型文檔處理框架LangChain簡化RAG流程…