將Docker與pipeline一起使用

2021-01-18 IT程式設計師alian

許多組織使用Docker統一其跨機器的構建和測試環境,並提供一種用於部署應用程式的有效機制。從Pipeline 2.5及更高版本開始,Pipeline內置支持從內與Docker進行交互 Jenkinsfile。

雖然本節將介紹從a到Docker的使用基礎知識 Jenkinsfile,但不會涵蓋Docker的基礎知識,可以在Docker入門指南中進行閱讀 。

定製執行環境

Pipeline旨在輕鬆地將 Docker 映像用作單個Stage 或整個Pipeline 的執行環境 。這意味著用戶可以定義其管道所需的工具,而無需手動配置代理。幾乎任何可以 打包在Docker容器中的工具。只需對進行較小的修改即可輕鬆使用Jenkinsfile。

Jenkinsfile(聲明性管道)

pipeline { agent { docker { image 'node:7-alpine' } } stages { stage('Test') { steps { sh 'node --version' } } }}切換腳本管道 (高級)

當管道執行時,Jenkins將自動啟動指定的容器並在其中執行定義的步驟:

[Pipeline] stage[Pipeline] { (Test)[Pipeline] sh[guided-tour] Running shell script+ node --versionv7.4.0[Pipeline] }[Pipeline] // stage[Pipeline] }緩存容器數據

許多構建工具會下載外部依賴項並將其本地緩存以供將來重用。由於容器最初是使用「乾淨」文件系統創建的,因此這可能會導致管道運行速度變慢,因為它們可能無法利用後續管道運行之間的磁碟緩存。

管道支持添加傳遞給Docker的自定義參數,從而允許用戶指定 要安裝的自定義 Docker卷,可用於 在兩次管道運行之間在代理上緩存數據 。以下示例將~/.m2利用maven容器在兩次管道運行之間進行 緩存,從而避免為管道的後續運行重新下載依賴項。

Jenkinsfile(聲明性管道)

pipeline { agent { docker { image 'maven:3-alpine' args '-v $HOME/.m2:/root/.m2' } } stages { stage('Build') { steps { sh 'mvn -B' } } }}切換腳本管道 (高級)

使用多個容器

代碼庫依賴於多種不同的技術變得越來越普遍。例如,存儲庫可能同時具有基於Java的後端API實現和基於JavaScript的前端實現。結合使用Docker和Pipeline可以通過將指令與不同階段結合Jenkinsfile使用 多種技術agent {}。

Jenkinsfile(聲明性管道)

pipeline { agent none stages { stage('Back-end') { agent { docker { image 'maven:3-alpine' } } steps { sh 'mvn --version' } } stage('Front-end') { agent { docker { image 'node:7-alpine' } } steps { sh 'node --version' } } }}切換腳本管道 (高級)

使用Dockerfile

對於需要更多自定義執行環境的項目,Pipeline還支持從Dockerfile源存儲庫中構建和運行容器。與以前使用「現成」容器的方法相比,使用該agent { dockerfile true }語法Dockerfile將從Docker Hub而不是從 Docker Hub生成一個新映像。

重用上面的示例,並使用一個更自定義的示例Dockerfile:

Docker文件

FROM node:7-alpineRUN apk add -U subversion通過將其提交到源存儲庫的根目錄,Jenkinsfile可以將其更改為基於此構建容器Dockerfile,然後使用該容器運行定義的步驟:

Jenkinsfile(聲明性管道)

pipeline { agent { dockerfile true } stages { stage('Test') { steps { sh 'node --version' sh 'svn --version' } } }}該agent { dockerfile true }語法支持許多其他選項,這些選項將在「 管道語法」部分中詳細介紹 。

在Jenkins Pipeline中使用Dockerfile

指定Docker標籤

默認情況下,管道假定任何已配置的 代理都能夠運行基於Docker的管道。對於具有macOS,Windows或其他代理程序且無法運行Docker守護程序的Jenkins環境,此默認設置可能會出現問題。管道在「 管理Jenkins」頁面和「 文件夾」 級別提供了一個全局選項,用於指定要使用哪些代理(按 Label)來運行基於Docker的管道。

腳本管道的高級用法

運行「 sidecar」容器

在管道中使用Docker是運行構建或一組測試可能依賴的服務的有效方法。與sidecar模式類似 ,Docker Pipeline可以「在後臺」運行一個容器,而在另一個容器中執行工作。利用這種「邊車」方法,管道可以為每個管道運行配備一個「乾淨」的容器。

考慮一個假設的集成測試套件,該套件依賴於要運行的本地MySQL資料庫。使用withRun在Docker Pipeline插件對Scripted Pipeline的支持中實現的方法, Jenkinsfile可以將MySQL作為輔助工具運行:

node { checkout scm /* * In order to communicate with the MySQL server, this Pipeline explicitly * maps the port (`3306`) to a known port on the host machine. */ docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw" -p 3306:3306') { c -> /* Wait until mysql service is up */ sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done' /* Run some tests which require MySQL */ sh 'make check' }}可以進一步利用該示例,同時使用兩個容器。一個「邊車」運行MySQL,另一個通過Docker 容器連結提供執行環境。

node { checkout scm docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c -> docker.image('mysql:5').inside("--link ${c.id}:db") { /* Wait until mysql service is up */ sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done' } docker.image('centos:7').inside("--link ${c.id}:db") { /* * Run some tests which require MySQL, and assume that it is * available on the host name `db` */ sh 'make check' } }}上面的示例使用暴露的對象withRun,該對象具有通過id屬性提供的運行容器的ID 。通過使用容器的ID,管道可以通過將自定義Docker參數傳遞給inside()方法來創建連結 。

該id屬性對於在管道退出之前檢查正在運行的Docker容器中的日誌也很有用:

sh "docker logs ${c.id}"建築容器

為了創建Docker映像,Docker Pipeline 插件還提供了build()一種Dockerfile在Pipeline運行期間從存儲庫中的創建新映像的方法 。

使用該語法的一個主要好處docker.build("my-image-name")是,腳本化管道可以將返回值用於後續的Docker Pipeline調用,例如:

node { checkout scm def customImage = docker.build("my-image:${env.BUILD_ID}") customImage.inside { sh 'make test' }}返回值還可以用於通過以下方法將Docker映像發布到 Docker Hub或自定義註冊表,push()例如:

node { checkout scm def customImage = docker.build("my-image:${env.BUILD_ID}") customImage.push()}映像「標籤」的一種常見用法是為latest最新,經過驗證的Docker映像版本指定標籤。該push()方法接受一個可選tag參數,允許管道customImage使用不同的標籤推送,例如:

node { checkout scm def customImage = docker.build("my-image:${env.BUILD_ID}") customImage.push() customImage.push('latest')}該build()方法Dockerfile默認在當前目錄中構建。可以通過提供包含路徑Dockerfile作為方法的第二個參數的目錄路徑來覆蓋它build(),例如:

node { checkout scm def testImage = docker.build("test-image", "./dockerfiles/test") testImage.inside { sh 'make test' }}test-image根據位於的Dockerfile 構建./dockerfiles/test/Dockerfile。

通過將其他參數 添加到方法的第二個參數中,可以將其他參數傳遞給 docker buildbuild()。以這種方式傳遞參數時,該字符串中的最後一個值必須是docker文件的路徑,並且應以文件夾結尾作為構建上下文)

本示例Dockerfile通過傳遞-f 標誌來覆蓋默認值:

node { checkout scm def dockerfile = 'Dockerfile.test' def customImage = docker.build("my-image:${env.BUILD_ID}", "-f ${dockerfile} ./dockerfiles") }my-image:${env.BUILD_ID}根據位於的Dockerfile 構建./dockerfiles/Dockerfile.test。

使用遠程Docker伺服器

默認情況下,Docker Pipeline插件將與本地Docker守護進程通信,該守護進程通常通過訪問/var/run/docker.sock。

要選擇非默認的Docker伺服器,例如 Docker Swarm,withServer()應使用該方法。

通過使用以下方法將URI以及可選的Jenkins中預先配置的Docker伺服器證書身份驗證的憑據ID傳遞給方法:

node { checkout scm docker.withServer('tcp://swarm.example.com:2376', 'swarm-certs') { docker.image('mysql:5').withRun('-p 3306:3306') { /* do things */ } }}inside()並build()不會與碼頭工人群伺服器正常工作,開箱即用

為了inside()正常工作,Docker伺服器和Jenkins代理必須使用相同的文件系統,以便可以安裝工作空間。

當前,Jenkins插件和Docker CLI都不會自動檢測伺服器正在遠程運行的情況。典型的症狀是嵌套sh命令的錯誤,例如

cannot create /…@tmp/durable-…/pid: Directory nonexistent當詹金斯(Jenkins)檢測到代理本身在Docker容器中運行時,它將自動將--volumes-from參數傳遞給 inside容器,以確保它可以與代理共享工作區。

此外,某些版本的Docker Swarm不支持自定義註冊表。

使用自定義註冊表

默認情況下,Docker Pipeline集成假定Docker Hub為默認的Docker Registry 。

為了使用自定義Docker註冊表,腳本化管道的用戶可以使用withRegistry()方法包裝步驟,並傳入自定義註冊表URL,例如:

node { checkout scm docker.withRegistry('https://registry.example.com') { docker.image('my-custom-image').inside { sh 'make test' } }}對於需要身份驗證的Docker註冊表,請從Jenkins主頁添加「用戶名/密碼」憑據項,並將憑據ID作為第二個參數使用withRegistry():

node { checkout scm docker.withRegistry('https://registry.example.com', 'credentials-id') { def customImage = docker.build("my-image:${env.BUILD_ID}") /* Push the container to the custom Registry */ customImage.push() }}

相關焦點

  • 使用Jenkins、Docker 構建部署 Serverless 應用
    近日,使用 Serverless 開發了一個應用。其中 CI/CD,是需要考慮的一個問題。這裡用到了 Jenkins 和 Docker。並且 Jenkins Pipeline 運行在容器中。 本文將介紹如何使用 Jenkins 和 Docker 構建並部署 Serverless 應用。
  • 雲計算核心技術Docker教程:Compose使用
    通過 Compose,您可以使用 YML 文件來配置應用程式需要的所有服務。然後,使用一個命令,就可以從 YML 文件配置中創建並啟動所有服務。Compose 使用的三個步驟:1.使用 Dockerfile 定義應用程式的環境。2.使用 docker-compose.yml 定義構成應用程式的服務,這樣它們可以在隔離環境中一起運行。
  • Docker & Singularity
    自從微軟更新了WSL2(雖然我一直在用WSL),但是發現docker只能在WSL2下使用,又是被需求更新。於是上網查了下window 家庭版的更新方法。打個補丁就好(可以參考該連結https://www.jianshu.com/p/a20c2d58eaac)。
  • 雲計算核心技術Docker教程: Docker 容器連接
    下面我們來實現通過埠連接到一個 docker 容器。我們創建了一個 python 應用的容器。命令如下:# docker run -d -P training/webapp python app.py另外,我們可以指定容器綁定的網絡地址,比如綁定 127.0.0.1。
  • 雲計算核心技術Docker教程:利用Dockerfile來創建鏡像
    在docker使用過程中,我們可以從已經創建的容器中更新鏡像,並且commit提交這個鏡像來創建新的鏡像,使用docker commit 來擴展一個鏡像比較簡單,但是不方便在一個團隊中分享此時我們可以使用 Dockerfile 指令來創建一個新的鏡像。
  • Docker 容器 9 類 48 個常見故障的處理和使用規範 | 周末送資料
    Docker是一種相對使用較簡單的容器,我們可以通過以下幾種方式獲取信息:1、通過docker run執行命令,或許返回信息2、通過docker logs 去獲取日誌,做有針對性的篩選3、通過systemctl status docker查看docker服務狀態4、通過journalctl -u docker.service
  • 雲計算核心技術Docker教程:Docker Compose的restart和rm命令詳解
    Docker-Compose restart命令可以重新啟動所有已停止並正在運行的服務,Docker-Compose rm命令可以刪除已經停止的容器,如果服務在運行,需要先docker-compose stop 停止容器。
  • 微服務部署到docker中
    打開Visual Studio 2019,創建一個ASP.NET Core Web應用程式2.使用ASP.NET Core 5.0創建一個ASP.NET Core WebAPI3. 右鍵選擇項目,選擇「添加」->「Docker支持...」
  • Docker 創建你自己的橋接網絡
    下面的例子顯示了如何創建一個橋接網絡: $ docker network create -d bridge my_bridge 參數 -d 用於告訴 Docker 在新的網絡中使用 橋接(bridge) 驅動。
  • CoreOS實踐指南(七):Docker容器管理服務
    而早在Docker誕生以前,「沙盒」的概念已經被普遍使用在Android、iOS等主流的手機系統中了。通過沙盒的隔離,應用軟體將自己所有的依賴與應用本身打包在一起,並通過SDK API提供的可控的方式訪問作業系統,軟體與系統的耦合度大大降低。這樣帶來的直接好處是,軟體之間的依賴衝突得到了很好的解決,移除一個應用軟體一般只需要很短的幾秒鐘並且徹底無痕,軟體訪問系統的安全性也更加可控。
  • 使用Gitea+Drone來搭建自己的輕量級CI/CD自動構建平臺
    Drone Server:使用drone/drone:1版本鏡像,將 drone 容器的 80 埠映射到宿主機的 7079 埠。映射容器內 /data 目錄到宿主機的 /data/drone 目錄,以便 drone 可以保留數據。配置服務自動重新啟動,並配置構建 drone 所需的環境變量。
  • 如何使用pipeline function獲得實時輸出
    很多人都知道,在普通的函數中,使用dbms_output輸出的信息,需要在伺服器執行完整個函數後一次性的返回給客戶端。但你如果需要在客戶端實時的輸出函數執行過程中的一些信息,在Oracle 9i以後則可以使用管道函數(pipeline function)。
  • Docker 引擎概述
    Docker Engine 實際上是一個客戶端伺服器(client-server)應用:一個在伺服器上長期運行的被稱為 dockerd 的進程。一個指定結構的 APIs,這個 API 被用來與 Docker 守護進程進行通信。
  • 【最新版】Docker實戰總結
    簡單的理解,docker就是一個軟體貨櫃化平臺,就像船隻、火車、卡車運輸貨櫃而不論其內部的貨物一樣,軟體容器充當軟體部署的標準單元,其中可以包含不同的代碼和依賴項。 按照這種方式容器化軟體,開發人員和 IT 專業人員只需進行極少修改或不修改,即可將其部署到不同的環境,如果出現的故障,也可以通過鏡像,快速恢復服務。
  • 雲計算核心技術Docker教程:Docker Compose的pull和push命令詳解
    Docker-Compose pull命令可以拉取docker-compose.yml或者docker-stack.yml文件中定義的服務關聯的鏡像,Docker-Compose push命令可以將服務鏡像推送到registry/repository中。
  • Docker v1.13.0 正式版發布,應用容器引擎
    在升級到 Docker 1.13 之前,必須卸載使用 Docker 1.12 安裝的插件。可通過 docker plugin rm 命令卸載插件。>可以直接使用 docker-compose.yml 進行服務部署添加 docker service 滾動升級出故障後回滾的功能增加強制再發布選項 docker service update –force允許 docker service create 映射宿主埠,而不是邊界負載均衡網絡埠
  • Docker是什麼?有什麼用途?及理論知識詳細說明
    Docker是一個虛擬環境容器,可以將你的開發環境、代碼、配置文件等一併打包到這個容器中,並發布和應用到任意平臺中。比如,你在本地用Python開發網站後臺,開發測試完成後,就可以將Python3及其依賴包、Flask及其各種插件、Mysql、Nginx等打包到一個容器中,然後部署到任意你想部署到的環境。 Docker官方文檔比較全,建議讀一下官方文檔。
  • SpringBoot+GitLab+Docker+Jenkins實現持續集成下
    該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力於在蓬勃發展的快速應用開發領域(rapid application development)成為領導者。接下來我們來編寫一個最簡單的SpringBoot入門項目。<?
  • Docker邁入雲(DockerHub)+端(Docker引擎)時代
    容器是完全使用沙箱機制,相互之間不會有任何接口(類似iPhone 的 app),性能開銷很低,可以很容易地在機器和數據中心中運行。它出現的意義可以與貨櫃的發明相比,貨櫃將貨運目標標準化,Docker 將應用程式標準化。Docker 誕生之前,程式設計師在伺服器端部署應用程式的步驟如下:安裝→配置→運行。與傳統部署模式不同,運用 Docker,程式設計師在伺服器端部署應用程式的步驟如下:複製→運行。