美文网首页程序猿的进阶屋
CI/CD初探(docker+drone)

CI/CD初探(docker+drone)

作者: StephenXP | 来源:发表于2019-05-23 17:34 被阅读34次

    将使用 docker + docker compose + drone + git 实现项目自动部署

    使用docker可以让drone实现任意语言程序的构建与部署

    分工

    docker: 整洁迅速的部署方案

    docker-compose: 组网和简单容器编排

    drone: go语言写的基于docker的CI框架

    流程预览

    代码提交到git

    git 通知drone应用

    触发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会自动拉去项目目录, 点击项目就能开启对这个项目的监管.

    编写项目

    需要单独为每一个项目编写.drone.yml文件 用来表述在代码提交后需要执行哪些操作.

    用一个简单的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下执行.

    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写的, 用于发布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

    发布流程就是通过SSH登陆上要部署程序的服务器pull下刚刚publish的镜像并启动.

    登陆SSH就需要配置ssh_key或者ssh_password, 更多详情看appleboy/ssh这个插件的文档, 这里推荐使用ssh_key, 我们需要在drone的secrets添加一项ssh_key值为私钥, 然后我们将与之匹配的公钥放在服务器上.ssh/authorized_keys里, 这样就能使用ssh_key登陆上服务器并执行script.

    扩展阅读: 私钥登录原理

    为什么要生成一对秘钥将秘钥放在drone的ssh_key:

    DroneService(A)想要登录Service(B)并执行命令, 在SSH登录认证的时候需要A用私钥签名一段信息发送到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的时候, 会得到其值并设置为容器的环境变量

    上例中drone会从数据库拿到docker_username和docker_password并赋值给环境变量DOCKER_USERNAME和DOCKER_PASSWORD, 在plugins/docker中会使用这两个环境变量去登陆你设置的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执行命令

    添加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

    找了很久的原因, 翻了很久源代码发现并没有问题, 知道发现这个详情可看这个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

    链接:https://www.jianshu.com/p/1e5f819f8881

    来源:简书

    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

        本文标题:CI/CD初探(docker+drone)

        本文链接:https://www.haomeiwen.com/subject/kfbbzqtx.html