f2etw / book

2014 f2e gitbook
9 stars 0 forks source link

Automated Build on Docker Hub #4

Open azole opened 9 years ago

azole commented 9 years ago

Automated Build on Docker Hub with Github and Jenkins

這個實驗的目標是利用 docker hub 的 automated build 的功能,做到每次 push request 到 github 時,就能自動建立該專案的測試 image。最後希望 dockerhub build 完之後,可以通知 Jenkins,把新 build 好的 image pull 下來,啟動進行測試。

整條路徑大約是:push -> github -> dockerhub automated build -> jenkins pull images -> run containers for test -> deploy,這只是其中一種路徑,其實也可以是以 CI 為主,例如:push -> git -> Jenkins build image -> run for test -> publish this image or deploy。

關於 docker 的基礎操作,歡迎參考這份投影片:Docker Tutorial

Part I: 建立 automated build 的 Repository

  1. 先把 docker hub 的帳號跟 github/bitbucket 的帳號 link 起來
  2. 先在 Github 建好要 auto build 的專案,例如我建立了一個 https://github.com/azole/docker-auto-build-test
  3. 在 docker hub 按下 Add Repository,選擇 Automated Build
  4. 選擇 Github 或是 Bitbucket,這邊我選擇 Github
  5. 選擇要 build 的 Repository,我選了剛剛建立的 docker-auto-build-test
  6. 接下來就會出現一個設定畫面,沒有特別的 Branch 或 Tag 要選的話,用預設值就可以了。
  7. 按下 Create Repository,這樣就建立好了,非常地簡單。
  8. 這時候到 My Repositories 看看,就會看到一個 azole/docker-auto-build-test 的 repository。
  9. 點進去看到 repo 的細節後,點到 Build Details 這個分頁,會看到 auto-build 的結果,有 id, status 跟相關的時間註記。
  10. 現在會看到一個 Error 的結果,點 build Id 進去看細節,會看到 Error 的原因是 Specified Dockerfile was not found. 非常合理,因為我們沒有在這個 github 專案中放 Dockerfile。

    Part II: 建立測試用的 nodejs 專案

參考 https://github.com/alsotang/node-lessons/tree/master/lesson6 的內容,建立了 nodejs 的專案,因為不是這邊的重點,就請大家自己參考該連結,或是參考 https://github.com/azole/docker-auto-build-test 裡頭的程式碼。

這個專案裡頭,我們做了一個小小的 fibonacci 的功能,並且利用 mocha 做了測試,還有一個 Makefile,也在 package.json 中寫了 npm test。

當我把測試專案做好的時候,做了一次 commit/push,回到 docker hub 上去看,會發現又多了一筆 Build Details 的記錄,這表示 Github 跟 Docker hub 真的有連動起來,不過狀態依舊是 Error,因為我們還是沒有 Dockerfile。

Part III: Dockerfile

FROM ubuntu

# install nodejs
RUN apt-get -qq update
RUN apt-get -y install nodejs
# 因為用 apt 的方式安裝的指令會是 nodejs,但個人習慣用 node,所以做個 link
RUN ln -s /usr/bin/nodejs /usr/bin/node
RUN apt-get -y install npm

# install git
RUN apt-get -y install git

# pull 
RUN git clone https://github.com/azole/docker-auto-build-test.git
WORKDIR /docker-auto-build-test
RUN npm install

# run test
CMD ["npm", "test"]

這個 Dockerfile 寫好後,可以自己先 build 起來測試看看,build 後 run 起來,應該會看到測試的結果。

這時候把 Dockerfile push 上 github,這時候會看到又多了一筆 Build Details,狀態是 Building,而 Dockerfile 這個分頁也已經抓到我們剛剛 push 上去的 Dockerfile 了。

稍等一段時間,就會看到狀態已經是 Finished,點進去看,也有整個 build 的過程的 logs 可以看。

Part IV: pull image and test

最後,我們測試看看,把這個 image pull 下來用用看。

 docker pull azole/docker-auto-build-test
 docker run azole/docker-auto-build-test

Part V: 優化

這個 Dockerfile 其實還可以做更好的設計,例如:

  1. 將 ubuntu update 獨立成一個 image。
  2. 再從這個更新過的 image 去安裝 git,也獨立成一個 image。
  3. 接續 2 這個 image 去安裝 nodejs,然後這些都 push 上去。
  4. automated build 這邊的 Dockerfile 就從 3 做出來的 image 去 build。

於是 Dockerfile 就只剩下這些:

FROM azole/testbase

# pull 
RUN git clone https://github.com/azole/docker-auto-build-test.git
WORKDIR /docker-auto-build-test
RUN npm install

# run test
CMD ["npm", "test"]

先把基礎環境做好,這就不用重複去 build 這些基礎的環境了,每次的 automated build 只需要從 pull 程式碼開始即可,image build 的速度會快上許多。

Part VI: 與 CI (Jenkins) 整合

目前在 Jenkins Plugins 已經可以找到幾個跟 docker 有關的 plugins,其中有一個 dockerhub plugin 看起來最符合這個實驗的情境,它可以搭配 dockerhub 的 webhooks,當 dockerhub build 好一個 image 時,通知 jenkins 去做一些事。

  1. 到 Jekins管理界面 -> 管理 Jenkins -> 管理外掛程式,切換到「可用的」,利用右上角的「過濾條件」搜尋 docker,就可以看到 dockerhub,勾選安裝。
  2. 建立 Jenkins 工作,在新增專案(或組態設定)的頁面,可以看到「建置觸發程序」裡頭多了一個「Run when a new image is built on DockerHub」,勾選起來,讓這個工作能接受來自於 dockerhub 的通知。
  3. 在建置的選項中,也可以看到多了一個「Pull Docker image from DockerHub」,在 Image ID 填上「azole/docker-auto-build-test」。每一個在步驟 2 有勾選「Run when a new image is built on DockerHub」的工作都會收到來自於 DockerHub 的通知,所以要設定這個 Image ID 來判斷是否是這個工作應該要處理的 dockerhub trigger。
  4. 現在來設定讓 DockerHub 發出通知。到 DockerHub 的網頁上,進入該 repo,網頁的右邊會有一個「Webhooks」,點選進去。按下「Add Webhook」,這邊輸入一個自己方便管理的名稱,然後在 URL1 的地方填「 http://[Jenkins Server]:8080/dockerhub-webhook/」,按下 save 後回到 Webhooks 的管理界面,可以看到剛剛新增的那組 webhook,有一個 Test 可以進行測試。
  5. 按下 Test 或執行 build 時,當 DockerHub 完成 build 的動作後,就會發送通知給 Jenkins,Jenkins 就能透過 DockerHub Plugin 來把這個新的 image pull 下來。

另外還有一個"Docker build step plugin",可以讓 jenkins 支援 docker 的命令:

  1. 到 Jekins管理界面 -> 管理 Jenkins -> 管理外掛程式,切換到「可用的」,利用右上角的「過濾條件」搜尋 docker,就可以看到 Docker build step plugin,勾選安裝。
  2. 安裝完這個 plugin 之後,請到 Jenkins -> 管理 Jenkins -> 設定系統 -> 找到 Docker Builder,這邊有一個 Docker URL 需要設定,填入 http://localhost:2375,這是連接 docker 的 remote REST API (必須先在 docker 啟動),設定完成後,可以利用 Test Connection 測試看看是否有成功。
  3. 建立 Jenkins 工作,在新增專案(或組態設定)的頁面,新增建置步驟的選項中,可以看到多了一個「Execute Docker container」的選項,選擇這個選項。
  4. 選擇 Docker Command,這裡可以看到這個 plugin 支援的 docker 命令,就看各位的需求是什麼。我這邊是要把 image pull 下來,所以選擇 pull image,在 Name of the image to pull (repository/image) 填入 azole/docker-auto-build-test,在 Registry Server Addresses 填入 registry.hub.docker.com。然後儲存這些設定。
  5. 按下「馬上建置」,就可以看到 Jenkins pull 一個 image 下來,這邊當然可以繼續做後續的動作,例如在 pull 下來後執行它。

當 DockerHub build 完後主動通知 Jenkins,Jenkins 透過 DockerHub Plugin 收到 trigger、也把 image pull 下來後,就可以透過 Docker build step plugin 來跑 container 或是做一些管理。

以上我們就完成了 push -> github -> dockerhub automated build -> jenkins pull images -> (run containers for test -> deploy) 的動作。

而 Docker build step plugin 支援的指令還不錯,也可以換個路徑嘗試,從 Jenkins 出發來控制這些,一如開頭提到的第二條路徑。


以上的範例是從無到有去建立,包括 github repo 與專案內容也是,步驟上可以視自己的情況去做,github repo, 專案內容, Dockerfile, docker hub repo 中只有 github repo 要先于 docker repo 建立,其他的順序都沒差。


補充:remote REST API 啟動方式
以 CentOS 來說,我是在 /etc/sysconfig/docker 這個檔案中加上

-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

重新啟動 docker,這樣就生效了。可以利用 curl localhost:2375/images/json 來進行測試。

DerekHung commented 9 years ago

非常感謝您的投稿!在近日內會公布此次徵稿活動的結果,敬請期待:D

kidwm commented 9 years ago

sudo apt-get install nodejs-legacy