1. 程式人生 > >Docker+Maven+Jenkins在Devops中完整應用

Docker+Maven+Jenkins在Devops中完整應用

過去與現在

很早之前,當我們需要一個部署環境的時候,我們可能指的是一臺PowerEdge R710 2U伺服器,走一系列冗長的申請流程,然後上架到機房、除錯網路、安裝系統、除錯環境、最終部署應用,就這樣過去了幾個月。
接著出現了虛擬化技術,我們在一臺內部伺服器使用Citrix XenApp劃分出幾臺虛擬機器,搭建了內部需求管理系統、SVN、測試環境等等,當需要新的機器時,我們只需要再次複製出一臺虛擬機器即可,現在只需要幾個小時我們就能整理好一個環境。
到了2013年,docker出現了。當我需要搭建一個Jenkins環境時,我只需要執行兩個命令 :
docker pull jenkins/jenkins


docker run jenkins/jenkins
就可以開始使用Jenkins了,只花了我幾分鐘時間。
docker究竟是什麼,我們應該如何在軟體生產過程中使用呢?

docker基本概念

我們不打算深入的介紹docker的基礎原理,只打算從最基本的應用的場景來說明我們必須理解的部分。
一個完整的Docker有以下幾個部分組成:

  • Docker Client【客戶端】
    Docker Client是Docker架構中使用者與Docker Daemon建立通訊的客戶端。
  • Docker Daemon【守護程序】
    Daemon是Docker的守護程序,Docker Client通過命令列與Docker Damon通訊,完成Docker相關操作。
  • Docker Image【映象】
    包含了使用者定義的應用和其相關的依賴,可以理解成是一張“系統盤”。
  • Docker Container【容器】
    映象例項化之後就是容器,容器生成之後任何變化與映象無關,可以理解成是“系統盤”安裝的“系統”。

docker使用場景

我們假設的場景流程是這樣:
現在我們有一個應用,託管在Git倉庫上。管理層要求能夠完整支援自動化的devops流程,所以我們需要能夠使用CI伺服器從Git倉庫上拉取程式碼,編譯打包之後生成映象,上傳至公司的私有倉庫。最後能夠使用CI伺服器部署至應用伺服器並啟動。
進階場景:
最後一步改為使用容器編排軟體,拉取映象並且部署。並且支援灰度釋出,自動擴容(模擬場景)。

預設的環境
應用:SpringBoot + Maven
應用伺服器環境:CentOS
Git倉庫:Github
CI伺服器:Jenkins
私有倉庫:阿里雲容器映象服務
容器編排軟體:Kubernetes

實施過程

在實施過程中,我們可以不用太關心具體SpringBoot的程式碼,只是用於說明Dockerfile如何構建。所以我們忽略編寫應用,上傳Github的過程,假設目前已經有已經上傳好的應用,Jenkins也啟動完畢,我們從這裡講起。

pom.xml編寫

pom.xml中最重要的部分就是根據Dockerfile生成映象的外掛,下面給出關鍵部分的節點

 <properties>
  <java.version>1.8</java.version>
  <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
  <docker.image.prefix>software5000</docker.image.prefix>
  <docker.repository>registry.cn-hangzhou.aliyuncs.com</docker.repository>
 </properties>

 <build>
  <plugins>
   <plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.4.10</version>
    <executions>
     <execution>
      <id>default</id>
      <goals>
       <goal>build</goal>
       <goal>push</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <repository>${docker.repository}/${docker.image.prefix}/${project.artifactId}</repository>
     <tag>${project.version}</tag>
     <buildArgs>
      <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
     </buildArgs>
    </configuration>
   </plugin>
  </plugins>
 </build>

映象的打包實際上是由com.spotify.dockerfile-maven-plugin執行,重點在configuration標籤下的幾個子標籤,稍後會好好解釋。

Dockerfile

Dockerfile是最基礎的docker 映象描述檔案,可以直接訪問官方說明。

FROM openjdk:8u181-jdk-alpine
ARG workdir=/app
VOLUME ${workdir}
WORKDIR ${workdir}
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 8081
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]

我們就上面的進行一下說明
FROM:是指從什麼基本映象繼承增加自定義配置。這是大部分Dockerfile的第一行程式碼,因為Docker的推薦最佳實踐中就是強調複用,複用社群或者他人已經提供的基礎映象。我們使用的是openjdk 8的基礎映象
ARG:是指Dockerfile中的引數變數,這裡就可以看到上面pom.xml中有一個buildArgs標籤,實際上就是用來在初始化Dockerfile時提供的引數。
VOLUME:是指Docker容器執行時的掛載點,用於方便容器和宿主機器之間磁碟訪問,類似共享資料夾。
WORKDIR:指定了Docker容器執行時的基礎根目錄。預設命令會從指定的目錄開始執行。
COPY/ADD:這個是構建映象時的核心命令了,會將當前宿主機器中的檔案拷貝到映象當中,比如本例中就是將打包好的jar複製到映象中。區別是ADD會自動解壓(比如war就可以解壓出來了),COPY不會。
EXPOSE:這個比較好理解,就是容器執行時,可以對外對映的埠。(當同一個容器在同一個宿主機器執行時,可以指定多個外部訪問埠)
CMD/ENTRYPOINT:這同樣也是核心命令,作用就是在啟動時自動執行的命令。但是差異如下:

  • CMD命令設定容器啟動後預設執行的命令及其引數,但CMD設定的命令能夠被docker run命令後面的命令列引數替換
  • ENTRYPOINT配置容器啟動時的執行命令(不會被忽略,一定會被執行,即使執行 docker run時指定了其他命令)

映象倉庫

映象倉庫使用了阿里雲的容器映象服務

我們在pom.xml中的屬性中有兩個變數:docker.repository 和 docker.image.prefix,如果你使用的是阿里雲,那基本docker.repository固定就是registry.cn-hangzhou.aliyuncs.com,docker.image.prefix就是你建立的名稱空間了。
接下來是要建立映象倉庫。我一開始理解的映象倉庫有錯,我以為所有的映象都是放在某一個映象倉庫下,實際上映象倉庫是指某一個映象多個版本的倉庫。所以針對我們的每個專案都要建立一個映象倉庫。

Jenkins推送倉庫和拉取部署

最終串聯的場景是這樣,當版本已經測試完畢,測試判定可以執行正式釋出動作,點選Jenkins中release任務的build按鈕。而伺服器則定時凌晨2點定時刪除本地映象並且拉取最新的映象並且啟動容器。
映象版本控制,也就是docker的tag。我們在dockerfile:build的時候,給映象打的版本是什麼,如果不標記預設就是latest。這樣推到倉庫之後再拉取整個過程只要不標記版本號即可。
根據我們之前的pom檔案,Jenkins中這樣配置就會推送至阿里雲的映象倉庫。

伺服器定時任務執行的shell指令碼,就是停止容器、刪除容器、刪除映象。

# 停止容器
docker stop eureka-server
# 刪除容器
docker rm eureka-server
# 刪除映象
docker rmi eureka-server
# 拉取映象
docker pull registry.cn-hangzhou.aliyuncs.com/software5000/eureka-server

# 執行映象
docker run -d --name=eureka-server -p 9001:8081 registry.cn-hangzhou.aliyuncs.com/software5000/eureka-server

總結

這篇文章主要是將docker,maven,jenkins整合,模擬實際工作的場景將所有流程串聯在一起,並且使用裡阿里雲的倉庫。但是在真正釋出的時候,還需要考慮CI/CD,灰度釋出等情況。我們並沒有在這裡完全解決掉。因為每個專案的環境和架構都不相同,所以還是要根據實際具體的情況來推進Devops。現在也正在研究Kubernetes的使用,現在能夠確認的有一點。Kubernetes相當於接管了整個環境,所以我們的伺服器都是需要安裝Kubernetes的客戶端,所有的應用也都變成容器化的執行方式。所以當環境切換到docker之後,再切換至Kubernetes會更簡單,後續的維護也更加輕鬆。
另外,如果本文還是看得不是很明白可以先了解一下docker的基本命令和使用方法,自己建個虛擬機器體驗一下就能明白很多事情