Drone 一個(gè)原生支持 docker 的 CI

大概是一年前發(fā)現(xiàn)了這樣一個(gè)叫做 Drone 的開源 ci,在逐漸的嘗試過(guò)程中發(fā)現(xiàn)它的功能非常的強(qiáng)大,其 pipeline as code + docker + backing service 支持的體系基本和我理想中的 ci 一模一樣...這里就介紹一下我看到的 drone 的一些非常出彩的地方以及日常使用時(shí)一些非常有用的使用方式。

本地安裝

image

可以看到 drone 的界面非常的簡(jiǎn)潔,和其他 ci 一樣它通過(guò)和 github gitlab 或者是 gogs 這樣的 git repository 鏈接并綁定 web hook 在用戶提交新的 commit 的時(shí)候出發(fā) ci 的執(zhí)行。drone 作為一個(gè)開源的 ci 其支持 docker 方式的安裝,非常的簡(jiǎn)單:

version: '2'

services:
  drone-server:
    image: drone/drone:0.7
    ports:
      - 80:8000
    volumes:
      - /var/lib/drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_HOST=${DRONE_HOST}
      - DRONE_GITHUB=true
      - DRONE_GITHUB_CLIENT=${DRONE_GITHUB_CLIENT}
      - DRONE_GITHUB_SECRET=${DRONE_GITHUB_SECRET}
      - DRONE_SECRET=${DRONE_SECRET}

  drone-agent:
    image: drone/drone:0.7
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_SERVER=ws://drone-server:8000/ws/broker
      - DRONE_SECRET=${DRONE_SECRET}

通過(guò)這樣的 docker-compose 文件就可以在本地啟動(dòng)一個(gè) droner server 和一個(gè) drone-agent(其概念和 gocd 類似)。

drone 的亮點(diǎn)

pipeline as code

首先 drone 支持 pipeline as code 其通過(guò)一個(gè)簡(jiǎn)單的 yaml 文件就包含了一個(gè)項(xiàng)目 ci 的所有內(nèi)容了(當(dāng)然,到底簡(jiǎn)不簡(jiǎn)單要看你構(gòu)建流程的復(fù)雜程度以及你對(duì)項(xiàng)目的封裝程度)。舉一個(gè)例子:

pipeline:
  build:
    image: node:6.10.2-alpine
    commands:
      - yarn install
      - yarn run build
  publish:
    image: plugins/docker
    repo: eisenxu/realtopper-app
    secrets: [ docker_username, docker_password ]
    tags:
      - latest
      - ${DRONE_COMMIT_SHA:0:8}

這是一個(gè)采用 create-react-app 創(chuàng)建的一個(gè)前端單頁(yè)應(yīng)用項(xiàng)目。這里定義了 buildpublish 兩個(gè)階段。第一個(gè)階段 yarn installyarn run build 分別下載依賴和編譯但也應(yīng)用。第二階段 publish 采用項(xiàng)目中的 Dockerfile 構(gòu)建一個(gè) docker image 并發(fā)布到 hub.docker.com,具體兩個(gè)步驟如何進(jìn)行的細(xì)節(jié)我們?cè)诤竺鏁?huì)慢慢介紹。

原生支持 docker

上面的 yaml 中每個(gè)階段都有一個(gè) image 的字段,這個(gè) image 就是指一個(gè) docker image 也就是說(shuō) drone 下每一個(gè)階段都是在一個(gè)你所指定的 docker container 下執(zhí)行的。這樣當(dāng)然就?集成了 docker 所引入的一系列的好處:環(huán)境隔離、標(biāo)準(zhǔn)化鏡像。?并且,它是后面插件擴(kuò)展以及 backing service 可以被輕而易舉的實(shí)現(xiàn)的基礎(chǔ)。

簡(jiǎn)單易用的插件擴(kuò)展

還是在看上面的那個(gè)例子,?第一個(gè)階段我們?cè)?node:6.10.2-alpine 下構(gòu)建了一個(gè)單頁(yè)應(yīng)用。然后,我們采用了 plugins/docker 鏡像構(gòu)建并發(fā)布了我們的鏡像到 hub.docker.com。而這里的 plugins/docker 就是 drone 為我們提供的一個(gè)插件了。

雖說(shuō)是一個(gè)插件,但實(shí)際上用起來(lái)就和其他的? image 一樣,這個(gè)插件的功能就是幫我們利用項(xiàng)目中的 Dockerfile 構(gòu)建一個(gè)新的 docker image 并提交。除此之外還有一些其他的官方插件可供使用,詳情在這里

當(dāng)然,自己做一個(gè)插件也是非常簡(jiǎn)單的,在插件被執(zhí)行的時(shí)候,當(dāng)前目錄就是項(xiàng)目的根目錄,然后 drone 會(huì)暴露一系列的環(huán)境變量給用戶使用,我們可以采用之前的步驟所產(chǎn)生的數(shù)據(jù)或者環(huán)境變量中的內(nèi)容實(shí)現(xiàn)一個(gè)特定功能的插件。

支持 backing service

我們跑 ci 的時(shí)候難免會(huì)有一些外部的依賴,比如跑單元測(cè)試的時(shí)候可能會(huì)用到外部的數(shù)據(jù)庫(kù)。比如跑前端界面測(cè)試的時(shí)候我們會(huì)需要 selenium。drone 對(duì)這種場(chǎng)景提供了支持。

pipeline:
  test:
    image: golang
    commands:
      - go get
      - go test

services:
  database:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=test

這是官方所提供的一個(gè)數(shù)據(jù)庫(kù)的例子。通過(guò)定義一個(gè) services 字段,我們可以提供一個(gè)或者多個(gè)外部服務(wù)。

最佳實(shí)踐

對(duì) docker image 的驗(yàn)收測(cè)試

我們采用 docker 容器進(jìn)行部署的時(shí)候通常是在 docker 容器中跑單元測(cè)試然后打包鏡像并推到 registry。但是這樣的流程并不能保證我們打包好的鏡像是工作的,可能我們的 Dockerfile 寫的有問(wèn)題導(dǎo)致服務(wù)沒(méi)辦法被使用。所以,其實(shí)還可以最這種最終構(gòu)件好的鏡像做一個(gè)驗(yàn)收測(cè)試。

backing service 的機(jī)制可以讓我們這么做:

pipeline:

  build:
    image: node:6.10.2-alpine
    commands:
      - npm build

  publish_for_test:
    image: plugins/docker
    repo: test/bar
    tags: [ 1.0.0, 1.0, latest ]

  run_server:
    image: test/bar:latest
    detach: true
  
  verify:
    image: blueimp/chromedriver
    environment:
      - VNC_ENABLED=true
      - EXPOSE_X11=true
    commands:
      - nightwatch

  publish:
    image: plugins/docker
    repo: production/bar
    tags: [ 1.0.0, 1.0, latest ]
  1. 首先,我們?cè)?publish_for_test 中構(gòu)建一個(gè) test/bar:latest 的鏡像。
  2. 然后我們采用 detach 的字段表明我們?cè)谶@里把我們剛剛創(chuàng)建好的鏡像運(yùn)行起來(lái)。
  3. verify 階段,我們采用 nightwatch 對(duì)已經(jīng)運(yùn)行起來(lái)的 test/bar:latest 服務(wù)執(zhí)行驗(yàn)收測(cè)試,也就是說(shuō),這時(shí)候我們把剛剛創(chuàng)建的應(yīng)用當(dāng)做我們的 backing service
  4. 如果測(cè)試通過(guò)了,我們?cè)贅?gòu)建一個(gè)新的鏡像并 push 到生產(chǎn)環(huán)境 registry

當(dāng)然,這里的 publish_for_test 其實(shí)最好的辦法是只構(gòu)建鏡像而不提交鏡像,然后在本地啟動(dòng)這個(gè)鏡像。不過(guò)這種使用本地鏡像的方式并沒(méi)有使用過(guò),而且也沒(méi)有那種只構(gòu)建不提交或者只提交已經(jīng)存在的鏡像的插件,以后可以自己進(jìn)一步做一些優(yōu)化。

用 drone 部署多個(gè)階段的環(huán)境

雖然 drone 沒(méi)有 GoCD 里的 deployment pipeline 的概念,但是它可以通過(guò)指定特殊的 deployment 的事件實(shí)現(xiàn)手動(dòng)激活的多環(huán)境部署。

pipeline:
  build:
    image: golang
    commands:
      - go build
      - go test

  publish:
    image: plugins/docker
    registry: registry.heroku.com
    repo: registry.heroku.com/my-staging-app/web
    when:
+     event: deployment
+     environment: staging

  publish_to_prod:
    image: plugins/docker
    registry: registry.heroku.com
    repo: registry.heroku.com/my-production-app/web
    when:
+     event: deployment
+     environment: production

可以看到通過(guò)指定 eventenvironment 可以指定兩個(gè)不同的環(huán)境:staging 和 production。然后,通過(guò) drone 所提供的命令行可以實(shí)現(xiàn)手工部署到不同的環(huán)境。

drone deploy octocat/hello-world 24 staging

這里是將構(gòu)建 24 號(hào)部署到 staging 環(huán)境。

使用插件為構(gòu)建增加緩存

每次構(gòu)建都從遠(yuǎn)端獲取依賴真是非常費(fèi)流量費(fèi)時(shí)間,最好可以不要重復(fù)下載。drone 就以插件的方式支持了這樣的功能。

pipeline:
  restore-cache:
    image: drillster/drone-volume-cache
    restore: true
    mount:
      - ./node_modules
    volumes:
      - /tmp/cache:/cache

  build:
    image: node
    commands:
      - npm install

  rebuild-cache:
    image: drillster/drone-volume-cache
    rebuild: true
    mount:
      - ./node_modules
    volumes:
      - /tmp/cache:/cache

第一階段 restore-cache/tmp/cache 下該項(xiàng)目的緩存拷貝到 ./node_modules。第三階段將 ./node_modules 的內(nèi)容拷貝會(huì) /tmp/cache 詳細(xì)的內(nèi)容見緩存。

當(dāng)前的狀態(tài)

目前 drone 剛剛開始了商業(yè)化之路,并且在瘋狂的更新中,整體社區(qū)非常的活躍 star 也已經(jīng)過(guò)萬(wàn)了,非常期待它未來(lái)的發(fā)展。

相關(guān)資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Docker — 云時(shí)代的程序分發(fā)方式 要說(shuō)最近一年云計(jì)算業(yè)界有什么大事件?Google Compute Engi...
    ahohoho閱讀 15,844評(píng)論 15 147
  • docker基本概念 1. Image Definition 鏡像 Image 就是一堆只讀層 read-only...
    慢清塵閱讀 9,003評(píng)論 1 21
  • 寫這篇文章主要是為了今后畢業(yè)論文素材上的整理,同時(shí)對(duì)docker進(jìn)行鞏固溫習(xí)。大綱: docker簡(jiǎn)介docker...
    胡圖仙人閱讀 7,766評(píng)論 2 96
  • 1. UIView是iOS系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都是繼承自它。它本身完全是由CoreAnimatio...
    STONEsh閱讀 758評(píng)論 0 8
  • 李永梅 語(yǔ)桐媽媽 智慧父母三期 堅(jiān)持分享第640天(焦點(diǎn)講師班二期 分享550天 20171030) 面對(duì)工作...
    李永梅閱讀 334評(píng)論 0 0

友情鏈接更多精彩內(nèi)容