Categories
程式開發

怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序?


怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序? 1

我正在用AWS lambda開發一個無服務器架構的自由職業項目。

用Jenkins和Docker實現CI/CD,並在Docker容器上運行Jenkins pipelines。我會向你展示如何一步步設置環境。

由於是蘋果電腦,我首先在電腦上安裝Docker軟件。還需Jenkins軟件。我選擇在Docker容器中運行Jenkins,因為這樣的運行環境更簡單乾淨。於是,我為Jenkins找到一個Docker鏡像版本(image)。

簡而言之,Docker把容器當作獨立的計算機來操作。

Docker會利用鏡像文件創建容器。例如,在使用的這個Docker鏡像中,包含了Linux操作系統和Jenkins軟件。當Docker用這個鏡像創建一個容器時,就相當於我們有一台計算機已經預先安裝了Linux和Jenkins。

一、設置容器

接下來,讓我們看看如何設置這個容器。一開始,我們從Docker鏡像的線上資源庫Docker hub中提取鏡像文件。

docker pull jenkins/jenkins:lts
lts: Pulling from jenkins/jenkins
844c33c7e6ea: Pull complete 
ada5d61ae65d: Pull complete 
f8427fdf4292: Pull complete 
f025bafc4ab8: Pull complete 
67b8714e1225: Pull complete 
64b12da521a3: Pull complete 
2e38df533772: Pull complete 
b1842c00e465: Pull complete 
b08450b01d3d: Pull complete 
2c6efeb9f289: Pull complete 
0805b9b9cdc4: Pull complete 
f129619fc383: Pull complete 
cd27f3a82cdf: Pull complete 
f31251f493ed: Pull complete 
2c902f1f4dfa: Pull complete 
2fe1d2cb7aab: Pull complete 
908723de775f: Pull complete 
54aa3899e429: Pull complete 
f48cf8764dc1: Pull complete 
Digest: sha256:d5069c543e80454279caacd13457d012fb32c5229b5037a163d8bf61ffa6b80b
Status: Downloaded newer image for jenkins/jenkins:lts

Docker軟件下載鏡像文件並對之解壓。現在,我們可以在自己的目錄下看到該鏡像文件。

alis-MBP:scms aliyuksel$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jenkins/jenkins     lts                 a3f949e5ebfd        2 weeks ago         582MB

然後,我們可以用這個鏡像構建一個容器並運行。使用以下命令:

docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

一旦這個容器正常啟動,我們就能使用Jenkins軟件,直到該容器關閉。但在容器關閉後會有一個問題:在下一次運行中,我們找不到之前已創建的任何pipeline或配置。

這是因為,Docker是在鏡像文件上運行容器,而鏡像文件本身是不可更改的。這就意味著,當我們在Jenkins中定義一個pipeline時,Jenkins會將它保存到容器文件系統中而不是鏡像文件中。當關閉容器時,這些信息就丟失了。

因此,我們必須使用“Volumes”來解決這個問題。

Volumes用於將虛擬容器的文件系統固化到我們的實際物理計算機文件系統中。為此,我們必須定義新的Volume以保留容器中的Jenkins_home目錄。這並不難,我們需要更改run命令如下:

docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts

這裡-v代表“Volume”。如果沒有Volume,它將自動創建一個Volume。你可以查看Docker相關文檔以了解更多信息。

簡而言之,我們用這種方法定義了名為jenkins_home的新卷,並掛載容器文件系統中的路徑至:/var/jenkins_home。之後,即使關閉容器,我們的更改也不會丟失。因為/var/jenkins_home文件夾下的所有文件都保存在Volume中。

現在,我們可以在瀏覽器上調用Jenkins的url了。這時應開啟Jenkins。我們需要初始密碼initialAdminPassword。當執行以上命令時,我們可以看到日誌,並在日誌中找到需要的initialAdminPassword

*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
fb7b0666b23f40db985817700d1d0821
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************

我們在Jenkins的頁面中輸入十六進制的密碼。之後,我們會完成以下步驟:

  • 安裝建議的插件
  • 創建第一個管理員用戶
  • Jenkins實例配置
  • 開始使用Jenkins

到這裡,我們完成本教程的第一部分。

二、實現pipeline

我們已經得到一個Jenkins的實例(instance)。

然後,開始實現pipeline。該pipeline將執行以下步驟:

  • 下面的所有步驟都將在另一個Docker容器上運行
  • 從Git(bitbucket)中提取我的項目代碼,這是用nodejs編寫的一個lambda項目。
  • 使用無服務器架構將該lambda項目部署到AWS雲上。

我們需要這個新容器的鏡像文件。這個鏡像其實是一台簡單的linux計算機。我們從Docker hub提取這個新容器的鏡像文件。

docker pull alpine

此時,我們在本地機器上已經有這個Docker鏡像文件了。但是Jenkin運行在另一個容器中。所以Jenkins需要連接這個新的Docker鏡像。

我們必須在容器和Docker之間建立一座橋樑,用“Volume”定義來解決這個問題。

-v /var/run/docker.sock:/var/run/docker.sock  -v $(which docker):$(which docker) 

分析一下上面的命令。其中,docke.sock文件用於偵聽套接字(socket)。在將這些Volume添加到命令行之後,docker.sock會掛載到本地計算機(localmachine)裡的docker.sock文件中。

如果我們使用-v,並在之後指定本地計算機的真實路徑,這條命令的意思就是執行“掛載(mount)”。如果我們在-v之後使用$(),則表示運行命令。 -v $(which docker):$(which docker) 語句表示,如果“which docker”在容器上運行,Docker也會在本地計算機上運行“which container”,並將執行結果返回給容器。

必須在以上命令中添加這個參數,因為Jenkins通過運行“which docker”來查找具體運行的Docker。

我們還須改變這個文件的權限,因為缺省情況下,Jenkins用戶無法訪問這個文件。我們需要用根用戶權限(root user)連接到該容器。

執行這個命令,並運行容器。

 docker run -p 8080:8080 -p 50000:50000 --name jenkins  -v jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock  -v $(which docker):$(which docker)  jenkins/jenkins:lts

我們使用以下命令打開容器的終端窗口。簡單而言,使用根用戶權限在容器上運行bash命令,我們然後用chmod更改文件權限。

怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序? 2

這裡強調的一個重點是,同一個容器名不能被使用兩次。當關閉容器時,你必須刪除該容器。

docker container rm jenkins

在此之後,下次可以用–name命令來使用Jenkins。

我們現在可以構建pipeline了。

點擊容器終端窗口菜單下的“New Item”。為這個Item輸入一個名稱。選擇PipeLine類型並單擊OK。

怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序? 3

在屏幕上選擇PipeLine。首先,pipeline創建一個新容器,並執行容器上的所有命令。

pipeline {
   agent {
        docker { image 'alpine' }
    }
   stages {
      stage('pull project') {
         steps {
             sh 'pwd'
         }
      }
   }
}

現在可以通過Jenkins查看日誌,看到的應該類似下圖:

怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序? 4

接下來,我們需要從bitbucket中提取項目。

首先,我們應該在Jenkins上定義一個可以訪問bitbucket的用戶。

單擊菜單上的Credentials/System(證書/系統)。然後單擊屏幕上的Global Credentials(全局證書)。這時菜單會發生改變,我們可以看到Add Credentials(添加證書)的新菜單。單擊Add Credentials並定義你已經在bitbucket上預先建立的用戶。

怎樣用Jenkins、Docker和CI/CD構建無服務器應用程序? 5

這時要重點關注的是ID字段。當從bitbucket中提取出該項目時,我們將使用這個字段的值。

這時進入pipeline.的配置頁面。我們通過編寫pipeline.腳本來從bitbucket中提取出該項目。

pipeline {
   agent {
        docker { image 'alpine' }
    }
   stages {
      stage('pull project') {
         steps {
             git credentialsId : 'aliyksel', url:'https://[email protected]/allscms/scms.git'
         }
      }
   }
}

保存,並運行pipeline。點擊“Build Now”。

然後,該pipeline開始運行,並從bitbucket提取項目。

三、運行單元測試

接下來,就需要使用npm。通常可以使用npm plug-in插件。但既然需要為無服務器創建一個新的鏡像文件,我更傾向於使用新鏡像文件中的npm,而不是npm plug-in。因此,我們將創建一個包含npm和無服務器架構的鏡像文件。

首先,提取包含節點的鏡像文件。

docker pull node

之後,我們會把無服務器架構添加到這個鏡像中。

從節點運行容器。

docker run -it --name node  node bash

現在已經進入容器。我們安裝無服務器架構。

npm install serverless -g

現在我可以從這個容器創建一個新的鏡像文件。於是在本地機器上運行以下命令。

docker commit node  serverlessimg

退出該Docker容器。

exit

此時,我們已經有了一個新的無服務器鏡像,能在Jenkins中使用這個鏡像。我們也可以使用pipeline,該pipeline能將無服務器應用程序部署到AWS雲端。

你需要更改鏡像文件的名稱,並向pipeline添加以下步驟。

  agent {
        docker { image 'serverlessimg' }
    }
...
stage('pull and deploy project : scms') {
         steps {
               git credentialsId : 'aliyksel', url:'https://[email protected]/allscms/scms.git'
               sh 'npm install'
               sh 'serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
               sh 'serverless deploy'
             }
         }
      }

我們還需定義用戶信息以實現對AWS服務的訪問。如果你還沒建立自己的AWS用戶賬戶,可以查看該文檔。鑑於我已有一個AWS用戶名了。我將以如下方式設置自己的用戶證書(credentials)。

serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

至此,所有步驟完成,我們為無服務器架構創建了一個新鏡像,並部署了一個AWS應用程序。

英文原文:

Using Jenkins, Docker and CI/CD for Serverless Applications