1、前言與初衷

本文章會涉及Docker常見命令基礎知識點結合不同場景實操一起使用。

本文章會涉及結合工作過程中部署不同環境伺服器的專案案例場景為初心進行實際細講。

本文章主要講述Docker、Jenkins、GitLab、Git、JDK、SpringBoot、Maven等技術結合實現自動化運維部署(DevOps)應用工程,適合SpringCloud部署。

初衷想法:在學習過程中遇到比較有趣的問題、然而花了點心血和時間去整理,然而進行梳理出來一份文章比較完整有知識體系的DevOps自動化構建與部署工程文章,技術知識內容比較多,而且文章內容較長,然而分了幾個章程來講述

2、什麼是DevOps?

DevOps(Development和Operations的組合詞)是一組過程、方法與系統的統稱,用於促進開發(應用程式/軟體工程)、技術運營和質量保障(QA)部門之間的溝通、協作與整合,它是一種重視“軟體開發人員(Dev)”和“IT運維技術人員(Ops)”之間溝通合作的文化、運動或慣例。透過自動化“軟體交付”和“架構變更”的流程,來使得構建、測試、釋出軟體能夠更加地快捷、頻繁和可靠。

它的出現是由於軟體行業日益清晰地認識到:為了按時交付軟體產品和服務,開發和運營工作必須緊密合作。

3 涉及軟體環境搭建內容

  • 如何在Centos7安裝JDK1.8-u121詳解
  • 如何在Centos7安裝Maven3.6.1詳解
  • 如何在Centos7安裝Git詳解
  • 如何在CentOS7與Git配置免密碼登陸詳解
  • 如何在Docker安裝GitLab詳解
  • 如何在Docker建立NetWork網路詳解
  • 如何在Docker安裝Registry私服詳解
  • 如何在Docker安裝Jenkins詳解

見附錄

特別說明

1、如何使用Maven結合Docker把SpringBoot應用編譯成可用的映象進行部署。

2、其中JDK和Maven是傳統方式進行安裝,由於本人Centos作業系統是有其他軟體依賴它們,有時候傳統方式安裝軟體會更好,這裡不過多的闡述。有些軟體在Docker安裝過程與使用過程並沒傳統方式的簡單,比如:Jenkins。

4、需要準備的工作有哪些

4.1 工程結構

  • 開啟IDEA或Eclipse新建一個SpringBoot的應用.

環境配置特別說明

注意事項:其中Gitlab、Registry、Jenkins都安裝在node1機器上面,也就是node1作為主機(master),node2作為slave(從機或副機),機器名起有意義或能區分即可,推薦起master和slave,這裡就不作過多的闡述,為了避免看文章有疑問,請看清單列表.

4.2、SpringBoot配置和程式碼詳解

4.2.1工程的pom.xml配置
<dependencies>
<!-- Springboot依賴的Jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- Springboot熱部署jar-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency> <!--yml配置檔案提示外掛-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency> <!-- spring-boot測試jar -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependencies>
<build>
<finalName>springboot</finalName>
<!-- 一定要宣告如下配置 打包xml 到Jar包 -->
<!-- <resources>
<resource>
<directory>src/main/java</directory>
是否替換資源中的屬性
<filtering>false</filtering>
</resource>
</resources>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- 預設支援jdk1.8編譯 -->
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!--docke rmaven編譯外掛-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.12</version>
<configuration>
<dockerDirectory>${project.basedir}</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.flong.SpringbootApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
4.2.2 no main manifest attribute錯誤解決
  • 配置工程主入口
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.flong.SpringbootApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
4.2.3 env環境變數檔案
  • 用於設定環境動態引數,檔案是以.env為格式
JAVA_OPTS_DEFAULT=-Xmx512m
4.2.4 Dockerfile打包工程映象細講
  • 以開發環境的Dockerfile為例,如果是測試環境則,把所有路徑包含springboot_dev改成springboot_test
FROM frolvlad/alpine-oraclejdk8:slim
MAINTAINER [email protected]
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN mkdir -p /home/devsoft/springboot_dev
WORKDIR /home/devsoft/springboot_dev
EXPOSE 7011
ADD ./target/springboot.jar ./
CMD java ${JAVA_OPTS_DEFAULT} -Djava.security.egd=file:/dev/./urandom -jar springboot.jar
  • 引數說明

  • WORKDIR 工作目錄說明進入容器此時會有一個.jar是在Dockerfile的ADD新增進去
docker exec -it 容器名稱或容器id /bin/sh

或要使用sh和bash要看COMMAND,-it

docker exec -it 容器名稱或容器id/bin/bash

4.2.5 build.sh檔案shell指令碼詳解

注意點1:經過測試動態變數的【等號】不能有空格和tab鍵置位,否則獲取不了值,而且在shell指令碼程式碼裡面不支援空格格式化,支援tab置位格式化。在終端(ssh軟體端)或Jenkins客戶端shell命令,『位置變數』的引數以空格隔開。

如:sh build.sh 192.168.1.235 springboot 0.0.1 7011 /home/jenkins/workspace/springboot_dev

$IMG_NAME:$IMG_VERSION這個IMG_VERSION版本(tag)引數不指定預設latest

注意點2:通常情況下Docker是預設執行Dockerfile,但是可以自定義字尾檔案進行編譯,前提必須要-f(force)強制指定檔案進行執行

#!/usr/bin/env bash
# 動態變數的【等號】不能有空格和tab鍵置位,否則獲取不了值,而且在shell指令碼程式碼裡面不支援空格格式化,支援tab置位格式化。
# 在終端(ssh軟體端)或Jenkins客戶端shell命令,引數以空格隔開。如:sh build.sh 192.168.1.235 springboot 0.0.1 7011 /home/jenkins/workspace/springboot_dev
IMG_SERVER="$1"
IMG_NAME="$2"
IMG_VERSION="$3"
IMG_PORT="$4"
RUN_EVN="$5"
IMG_PATH="$6" echo "服務地址:$IMG_SERVER"
echo "工程映象名稱:$IMG_NAME"
echo "工程版本號:$IMG_VERSION"
echo "工程埠:$IMG_PORT"
echo "服務環境:$RUN_EVN" #私服訪問url路徑和編譯之後映象檔案存放到指定路徑固定,不動態引數進行處理傳值.
REGISTRY_URL="192.168.1.235:5000"
IMG_TAR_GZ_PATH="/home/img_tar_gz_path/" # 判斷動態引數不為空字串的時候才執行下面操作
if [ "$IMG_SERVER" != "" ] && [ "$IMG_NAME" != "" ] && [ "$IMG_VERSION" != "" ] && [ "$IMG_PORT" != "" ]; then echo " .......進入刪除 Container & Images 操作 ......."
# 清理虛懸映象,釋放磁碟空間
#docker images|grep none|awk '{print $3 }'|xargs docker rmi # 獲取容器ID
CONTAINER_ID=`docker ps -a | grep $IMG_NAME | awk '{ print $1 }'` # 獲取映象ID
IMAGE_ID=`docker images | grep $IMG_NAME | awk '{ print $3 }'` # 判斷是否存在刪除開發容器
if [[ "$CONTAINER_ID" != "" ]]; then
docker rm -f $CONTAINER_ID
fi # 判斷是否存在刪除開發映象
if [[ "$IMAGE_ID" != "" ]]; then
docker rmi -f $IMAGE_ID
fi
# $IMG_NAME:$IMG_VERSION 這個IMG_VERSION版本(tag)引數不指定預設latest,通過不同引數執行不同環境檔案
# -f 表示強制指定Dockerfile檔案進行編譯 echo " .......進入Building & Images 操作 ....... " #方法1、指定不同檔案存放預設的Dockerfile,使用-f進行強制編譯
#docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"$RUN_EVN/Dockerfile $IMG_PATH #方法2、跟據不同Dockerfile檔案的字尾進行編譯不同環境的檔案
docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"Dockerfile_$RUN_EVN $IMG_PATH # 將映象打一下標籤,然後安照標籤進行推送到私服裡面,標籤名就以服務名即可
docker tag $IMG_NAME:$IMG_VERSION $REGISTRY_URL/$IMG_NAME:$IMG_VERSION # 推映象到私服裡面
docker push $REGISTRY_URL/$IMG_NAME:$IMG_VERSION # 判斷是否存在資料夾
if [ -d "$IMG_PATH" ];then
echo "已經存在:"$IMG_PATH
else
mkdir -p $IMG_PATH
fi # 儲存編譯之後映象檔案存放到指定路徑
docker save $IMG_NAME -o $IMG_TAR_GZ_PATH/$IMG_NAME.tar.gz echo " .......進入Runing操作 ....."
docker run -d --network default_network --restart=always --env-file=./.env -e spring.profiles.active=$RUN_EVN --expose=$IMG_PORT --name=$IMG_NAME -p $IMG_PORT:$IMG_PORT $IMG_NAME:$IMG_VERSION echo " .......Build & Run Finish Success~...."
else
echo " .......Illegal Command Operation ......."
fi
4.2.6 Docker (save、load、tag、push,pull)命令使用
  • 其中push,pull一個是推,一個是拉,在某種程度下,都是對在私服上面的映象進行操作
  • docker save命令是儲存編譯的tar.gz或tar壓縮檔案,語法如:
docker save 映象名 -o 路徑/映象名.tar.gz

docker save 映象名 -o 路徑/映象名.tar

docker load 命令是用於匯入使用 docker save 命令匯出的映象,此命令非常重要,由於有些客戶要求專案工程要求部署在內網,此時這個命令在無網路的內網情況下部署專案的時候就體現它重要的地位了.語法 docker load [OPTIONS],在載入的過程有點慢,因為檔案有點大,其中顯示Loady Layer [======]輸出資訊,證實映象是分層關係。

docker load -i /home/img_tar_gz_path/springboot.tar.gz

  • 引數說明

  • docker tagdocker push命令是一起結合使用,先tag後push,每個映象名和版本是以冒號區分,而docker pull根據情況使用.
# 將映象打一下標籤,然後安照標籤進行推送到私服裡面,標籤名就以服務名即可
docker tag 映象名:版本號 私服路徑/映象名:版本號
# 推映象到私服裡面
docker push私服路徑/映象名:版本號
  • 檢視映象

瀏覽器驗證docker push推送上私服的映象

4.2.7 虛懸映象
  • 在docker編譯不成功會或者是新版本覆蓋舊版本歸類為虛懸映象,生成這個個映象既沒有倉庫名,也沒有標籤,均為 <none>。一般來說,虛懸映象已經失去了存在的價值,是可以隨意刪除的。

4.2.8 不同環境的配置檔案

配置引數

不同環境配置引數內容

server:
port: 7011
runEvn: '開發環境'
server:
port: 7011
runEvn: '測試環境'
4.2.9 Controller測試程式碼
@RestController
public class SimpleController {
//讀取配置動態引數
@Value("${runEvn}")
private String runEvn; @GetMapping("/test")
public String test() {
return "this spring boot " + runEvn +" date long "
+ System.currentTimeMillis();
}
}

5、非多臺機器免密遠端登入&Jenkins部署詳解

5.1 特別說明

  • 以開發環境為例子進行說明
  • 開發環境部署目標機器是與Jenkins機器同一臺機器,一般情況,Jenkins是單獨一臺機器,這裡為了節省自身電腦記憶體,故放在同一臺機器進行演示與學習。

5.2 新建maven工程

  • 點選Jenkins的新建任務選單

5.3 引數化構建過程說明

5.3.1新增引數

5.3.2 引數說明以開發環境為案例

5.3.3 原始碼管理

5.3.4 Build編譯設定

表示忽略測試單元類進行編譯

clean install -U -Dmaven.test.skip=true

5.4 SSH Publishers設定

  • 其中SSH Server Name就是在http://jenkins地址:埠/jenkins/configure設定好進行選擇
  • Transfer Set Source file傳輸檔案的路徑,可以使用引數構建的佔位符${serverPath}獲取
  • Remote directory遠端檔案目錄,同理也引數構建的佔位符${serverPath}獲取

  • SSH Publishers shell指令碼#!/bin/bash表示告訴終端使用bash解析器進行執行,而且只有第一行bash才有效。
#!/bin/bash
# 建立目錄
mkdir -p ${serverPath}
# 切換目錄
cd ${serverPath}
# 執行指令碼
sh build.sh $server ${appName} ${version} ${port} ${env} ${serverPath}

5.5 構建與編譯部署專案

  • 截圖的構建引數都是在引數化構建過程配置的引數

5.6 構建&執行&&部署結果

  • 構建過程

  • 部署結果

5、多臺機器免密遠端登入&Jenkins部署流程詳解

6.1 特別說明

  • 以測試環境為例子進行說明
  • 步驟流程幾乎一樣,唯一是在SSH Publishers 和原始碼存放路徑不一樣,測試環境部署目標機器是與Jenkins機器不同一臺機器

6.2 新建maven工程

  • 點選Jenkins的新建任務選單

6.3 引數化構建過程說明

6.3.1新增引數

6.3.2 引數說明以測試環境為案例

6.3.3 原始碼管理

6.3.4 Build編譯設定

6.4 SSH Publishers設定

  1. 其中SSH Server Name就是在http://jenkins地址:埠/jenkins/configure設定好進行選擇
  2. Transfer Set Source file傳輸檔案的路徑,可以使用引數構建的佔位符${serverPath}獲取
  3. Remote directory遠端檔案目錄,同理也引數構建的佔位符${serverPath}獲取
  4. docker_server1表示與Jenkins部署同一個宿主機,使用指令碼有遠端機器shell指令碼操作免登陸操作。

  • docker_server1 Shell指令碼#!/bin/bash表示告訴終端使用bash解析器進行執行,而且只有第一行bash才有效。
#!/bin/bash
# 列印資訊
echo "使用者名稱${userName}"
echo "伺服器${server}"
echo "伺服器目錄${serverPath}"
# 遠端建立存放遠端上傳的程式碼目錄路徑
ssh $server mkdir -p ${targetServerPath}
# 遠端拷貝程式碼到目標機器指定路徑
scp -r ${serverPath}/ ${userName}@${server}:${targetServerPath}
  • docker_server2表示要部署那臺目標機器,所以它的指令碼跟docker_server1不一樣.

  • docker_server2 Shell指令碼
#!/bin/bash
# 切換檔案目錄
cd ${serverPath}
# 執行指令碼
sh build.sh ${server} ${appName} ${version} ${port} ${env} ${serverPath}

6.5 構建與編譯部署專案

  • 截圖的構建引數都是在引數化構建過程配置的引數

6.6 構建&執行&部署結果

  • 構建過程

  • 部署結果

7、總結&建議&學習

7.1總結與建議

1、此文章僅供提供參考學習指引,如需要系統得學習可以根據自身找資料去學習。

2、以上問題都是根據個人實際學習過程中遇到的問題進行一個一個問題進行梳理與總結整理,除了技術問題查很多網上資料通過進行學習之後整理與分享。

3、在學習過程中也遇到很多困難和疑點,如有問題或誤點,望各位老司機多多指出或者提出建議。本人會採納各種好建議和正確方式不斷完善現況,人在成長過程中的需要優質的養料。

4、當遇到問題的時候建議多問『谷歌 、必應、stackoverflow、度娘』這些大神。

5、建議看官方手冊更權威,由於隨著技術的發展與迭代,通常官方的文件更新較快,國內的網站資料更新較慢。

6、計算機是一門『做中學』的學科,不是會了再去做,而是做了才會。多練,常言道熟能生巧。

7、建議學什麼技術『先Know how,再Know Why』,意思就說先入門,搞一個HelloWorld,再深究的意思。

8、希望此文章能幫助你更好了解什麼(DevOps)是自動化構建映象與部署,如何在Docker+Jenkins+GitLab+Maven+SpringBoot&SpringCloud自動構建映象與部署服務應用,整個學習流程與搭建會有點小曲折,並不會那麼順利,也希望你看了此文章或者通過找資料進行親身經歷學習效果會更好。