將使用 docker + docker compose + drone + git 實現項目自動部署
使用docker可以讓drone實現任意語言程序的構建與部署
分工
docker: 整潔迅速的部署方案
docker-compose: 組網和簡單容器編排
drone: go語言寫的基于docker的CI框架
流程預覽
代碼提交到git
git 通知drone應用
觸發(fā)drone服務器運行項目下的.drone.yml
如果沒有配置clone步驟, drone會運行默認的clone步驟, 并clone到workspace設置下的path
依次運行pipeline下的步驟, 通常是 test -> build -> publish -> ssh連接到運行服務容器的服務器 并重啟容器, 下面會依次說明pipeline各步驟.
安裝Drone
可參考drone官方文檔
官方使用docker-compose安裝, 編寫docker-compose.yml如下
docker-compose.yml
version:'2'services:? drone-server:? ? image:drone/drone:latest? ? ports:? ? ? -8082:8000? ? ? -9000? ? volumes:? ? ? -/workspace/docker/volumes/drone:/var/lib/drone/? ? restart:always? ? environment:? ? ? -DRONE_OPEN=true? ? ? -DRONE_HOST=${DRONE_HOST}? ? ? -DRONE_CODING=true? ? ? -DRONE_CODING_CLIENT=${DRONE_CODING_CLIENT}? ? ? -DRONE_CODING_URL=https://coding.net? ? ? -DRONE_CODING_SECRET=${DRONE_CODING_SECRET}? ? ? -DRONE_CODING_GIT_MACHINE=e.coding.net? ? ? -DRONE_CODING_SCOPE=user,project,project:depot? ? ? -DRONE_GITHUB_SKIP_VERIFY=false? ? ? -DRONE_SECRET=${DRONE_SECRET}? ? ? -DRONE_ADMIN=bysir? ? ? -DRONE_CODING_GIT_USERNAME=${DRONE_CODING_GIT_USERNAME}? ? ? -DRONE_CODING_GIT_PASSWORD=${DRONE_CODING_GIT_PASSWORD}? drone-agent:? ? image:drone/agent:latest? ? command:agent? ? restart:always? ? depends_on:? ? ? -drone-server? ? volumes:? ? ? -/var/run/docker.sock:/var/run/docker.sock? ? environment:? ? ? -DRONE_SERVER=drone-server:9000? ? ? -DRONE_SECRET=${DRONE_SECRET}? ? ? -DRONE_MAX_PROCS=5
備注
字段注釋
DRONE_ADMIN管理員, 名字是你版本控制的賬號名, 添加了管理員的才可以管理用戶
DRONE_OPEN是否開啟新用戶注冊
DRONE_GITHUB使用github作為版本控制
在上面你會看到其中有${DRONE_HOST}的變量,這是docker-compose支持的語法,文檔
我們需要在同級目錄下編寫一個.env文件來寫入這些變量
.env
# drone的安裝服務器, 不需要端口DRONE_HOST=http://47.94.204.137 # DRONE需要GITHUB作為應用授權, 這里填寫授權賬號密碼, 詳情看[文檔](http://docs.drone.io/install-for-github/)DRONE_GITHUB_CLIENT=xxxxDRONE_GITHUB_SECRET=xxxx# 用于drone服務器和agent之間的密鑰, 隨意填寫DRONE_SECRET=123456
現在運行docker-compose up就能運行drone了, 順利的話就不會看到報錯, 如果有報錯就按報錯提示來解決.
訪問服務器 8080端口就能看到drone的web頁面了, 使用GITHUB的賬號登陸即可, 登陸后drone會自動拉去項目目錄, 點擊項目就能開啟對這個項目的監(jiān)管.
編寫項目
需要單獨為每一個項目編寫.drone.yml文件 用來表述在代碼提交后需要執(zhí)行哪些操作.
用一個簡單的go項目說明
.drone.yml
workspace:? base: /go? path: src/github.com/bysir-zl/gokit_startpipeline:? build:? ? image: golang:1.9? ? commands:? ? ? -pwd- go env? ? ? - go version? ? ? - go build? publish:? ? ? image: plugins/docker? ? ? registry: https://index.docker.io/v1/# 倉庫repo: bysir/golang_base# docker倉庫地址# mirror: https://docker.mirrors.ustc.edu.cn# 需要使用drone cli添加secrets: http://docs.drone.io/manage-secrets/secrets: [ docker_username, docker_password ]? ? ? tags:? ? ? ? - latest? deploy:? ? ? image: appleboy/drone-ssh? ? ? host: 47.94.204.137? ? ? username: root? ? ? port: 22? ? ? secrets: [ ssh_key ]? ? ? script:? ? ? ? -cd/root/app? ? ? ? - docker-compose pull bysir/golang_base? ? ? ? - docker-compose up
workspace
其中workspace指定pipeline的工作目錄, 上例中我們會在build中pwd看到當前目錄是/go/src/github.com/bysir-zl/gokit_start, 為什么我們需要指定到/go目錄下, 因為在golang:1.9的鏡像中,go_path就是/go, 我們要go build當然要在go_path下執(zhí)行.
build
build步驟很簡單只是go build, 你好奇為什么沒有go get, 因為我將vendor目錄也一起提交了, 推薦使用go官方依賴管理工具dep
docker在構建的時候都是以一個空白鏡像golang:1.9作為基礎的, 如果不提交vendor就需要每次構建都go get, 十分耗時. 當然還有辦法就是提交一個已經按照好go包的基礎鏡像到registry里, 在build中的image就換成你提交的鏡像. 相比之下更簡單的方法就是提交vendor目錄.
publish
publish步驟就有點復雜了, 使用到了plugins/docker插件, 這個插件是drone寫的, 用于發(fā)布docker鏡像. 它的作用就是構建一個鏡像, 并push到registry.
我們需要配置的值有
registry: 倉庫registry, 如hub.docker.com的registry地址是https://index.docker.io/v1/
repo: 在docker倉庫下的項目名稱
secrets: drone用于傳遞密鑰的實現方式, 下面會詳細介紹
在plugins/docker插件中, 構建項目鏡像是通過Dockerfile來的, 所以我們還需要在項目根編寫一個Dockerfile
Dockerfile
FROM alpine:latestCOPY gokit_start /WORKDIR /ENTRYPOINT ["./gokit_start"]
其中ENTRYPOINT是容器啟動后的運行入口, "./gokit_start"是示例項目build后的二進制文件
deply
發(fā)布流程就是通過SSH登陸上要部署程序的服務器pull下剛剛publish的鏡像并啟動.
登陸SSH就需要配置ssh_key或者ssh_password, 更多詳情看appleboy/ssh這個插件的文檔, 這里推薦使用ssh_key, 我們需要在drone的secrets添加一項ssh_key值為私鑰, 然后我們將與之匹配的公鑰放在服務器上.ssh/authorized_keys里, 這樣就能使用ssh_key登陸上服務器并執(zhí)行script.
擴展閱讀: 私鑰登錄原理
為什么要生成一對秘鑰將秘鑰放在drone的ssh_key:
DroneService(A)想要登錄Service(B)并執(zhí)行命令, 在SSH登錄認證的時候需要A用私鑰簽名一段信息發(fā)送到B, B收到請求后會使用.ssh/authorized_keys中的公鑰依次驗簽, 如果驗簽成功則登錄成功.
ps: 私鑰的格式是-----BEGIN RSA PRIVATE KEY-----xxxxxxxxx-----END RSA PRIVATE KEY-----全部放在web頁面就行了, 如下
添加secrets
在publish步驟有secrets選項, 其中docker_username和docker_password是由drone注入的, 所以我們需要在drone右上角添加secrets:
添加之后如下:
secrets實現原理:
drone有一個專門存儲secrets的地方, 當pipeline中step需要secrets的時候, 會得到其值并設置為容器的環(huán)境變量
上例中drone會從數據庫拿到docker_username和docker_password并賦值給環(huán)境變量DOCKER_USERNAME和DOCKER_PASSWORD, 在plugins/docker中會使用這兩個環(huán)境變量去登陸你設置的registry:docker login -p $DOCKER_PASWORD -u $DOCKER_USERNAME $DOCKER_REGISTRY
擴展閱讀:安裝drone cli
可以使用drone的cli來添加secrets:manage-secrets
安裝方法:CLI Installation
curl -Lhttps://github.com/drone/drone-cli/releases/download/v0.8.3/drone_linux_amd64.tar.gz| tar zx
sudo install -t /usr/local/bin drone
CLI需要通過server的授權:CLI Authentication
exportDRONE_SERVER=http://47.94.204.137:8080exportDRONE_TOKEN=eyJh33OiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXh0IjoiYnlzaXItemwiLCJ0eXBlIjoidXNlciJ9.jLsJvi4PafTi-ffefe5-bYTD2N_xmIi9fg
之后就可以使用cli執(zhí)行命令
添加secrets
drone secret add? -repository bysir-zl/gokit_start? -image plugins/docker? -name docker_username? -value bysir
drone secret add? -repository bysir-zl/gokit_start? -image plugins/docker? -name docker_password? -value 123456
刪除secret
drone secret rm --repository bysir-zl/gokit_start --name docker_username
測試
現在你的項目機構應該類似于
項目
現在你可以將你寫的代碼和配置文件一起提交到git, 然后你就能看到這個項目正在構建
你可以點擊查看構建步驟
ps
終于跑起來了
我相信你沒有我這么菜
2018/04/27 更新
最近需要使用coding作為版本控制軟件
文檔說drone-server在0.8版本之后是支持coding的, 但實際不然. 實際運行起來會報錯:version control system not configured
找了很久的原因, 翻了很久源代碼發(fā)現并沒有問題, 知道發(fā)現這個詳情可看這個issue
I encounter this issue too.
When use drone from latest docker image, setting DRONE_CODING=true has no effect, result: "version control system not configured".
When build drone from git source code, It's works.
I found
gitclonegit@github.com:drone/drone-enterprise.git extras
go build -ldflags '-extldflags "-static" -X github.com/drone/drone/version.VersionDev=build.'${DRONE_BUILD_NUMBER} -o release/drone-server github.com/drone/drone/extras/cmd/drone-server
at .drone.sh,
You use drone-enterprise.git for extras to build the docker image, not the open source code.
Is that the problem?
所以我嘗試使用git上源碼重新編譯一個drone-server使用, 修改倉庫下.drone.sh如下:
#!/bin/sh# clone the extras project.set-eset-x# 由于要運行在alpine, 所以需要加GOOS=linux GOARCH=arm64 CGO_ENABLED=0# 由于drone-server使用到了sqlite3, sqlite3使用到了gcc, 所以需要-extldflags "-static"# -ldflags "-extldflags -static" at the end makes sure C code is statically linked so resulting binary truly has no dependencies even for C code.go build -ldflags'-extldflags "-static" -X github.com/drone/drone/version.VersionDev=build.'0.01 -o release/drone-server github.com/drone/drone/cmd/drone-serverGOOS=linux GOARCH=amd64 CGO_ENABLED=0? ? ? ? go build -ldflags'-X github.com/drone/drone/version.VersionDev=build.'0.01 -o release/drone-agent? ? ? ? ? ? github.com/drone/drone/cmd/drone-agentGOOS=linux GOARCH=arm64 CGO_ENABLED=0? ? ? ? go build -ldflags'-X github.com/drone/drone/version.VersionDev=build.'0.01 -o release/linux/arm64/drone-agent github.com/drone/drone/cmd/drone-agentGOOS=linux GOARCH=arm? CGO_ENABLED=0 GOARM=7 go build -ldflags'-X github.com/drone/drone/version.VersionDev=build.'0.01 -o release/linux/arm/drone-agent? github.com/drone/drone/cmd/drone-agent
重新編譯, 打包鏡像.
為了方便, 我將做好的鏡像放在了共有倉庫下:
bysir/drone-server(對于官方0.8.5的版本)
可以這樣使用:
version:'2'services:? drone-server:? ? image: bysir/drone-server? ? ports:? ? ? - 8082:8000? ? ? - 9000? ? volumes:? ? ? - /workspace/docker/volumes/drone:/var/lib/drone/? ? restart: always? ? environment:? ? ? - DRONE_OPEN=true- DRONE_HOST=${DRONE_HOST}- DRONE_CODING=true- DRONE_CODING_CLIENT=${DRONE_CODING_CLIENT}- DRONE_CODING_URL=https://zhuzi.coding.net? ? ? - DRONE_CODING_SECRET=${DRONE_CODING_SECRET}- DRONE_CODING_GIT_MACHINE=e.coding.net? ? ? - DRONE_CODING_SCOPE=user,project,project:depot? ? ? - DRONE_GITHUB_SKIP_VERIFY=false- DRONE_SECRET=${DRONE_SECRET}- DRONE_ADMIN=bysir? drone-agent:? ? image: drone/agentcommand: agent? ? restart: always? ? depends_on:? ? ? - drone-server? ? volumes:? ? ? - /var/run/docker.sock:/var/run/docker.sock? ? environment:? ? ? - DRONE_SERVER=drone-server:9000? ? ? - DRONE_SECRET=${DRONE_SECRET}
ps: 真是折騰... 不過終于好了
作者:bysir
鏈接:http://www.reibang.com/p/1e5f819f8881
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處钥顽。