概述

前面早些的时候,尝试过使用gogs+webhooks的开发部署方式。本地写代码,push到gogs,然后触发webhook通知部署服务拉取git的代码到项目里面,完成上线操作。十分的简单。

经过一段时间,学习了新的东西。意识到这种方式还是偏过于原始,也不太稳定。例如,没有很好的解决依赖处理。git拉取之后,然后执行依赖的安装,这一个过程期间是肯定会影响线上的服务的。完善一些的处理应该是,在某台机器上,进行构建打包等操作。这个过程执行没问题之后,再将打包好的项目直接上传到线上服务器,完成部署。就是CI,CD的意思吧。

目前比较常见的工具是gitlab+jenkins。但是自己一个人折腾,用不上那么重的东西。因此,选择比较轻量级的gogs+drone搭建的。实践之后,效果还行。

环境 & 步骤 & 坑

本机的环境

  • OSX 10.11.6
  • MySQL 5.7.18
  • Docker for Mac 17.06.0

这里,gogs和drone都是使用Docker方式安装,很大程度降低了安装的复杂度。本机安装好Docker环境之后,新建目录,编写docker-compose文件即可。

version: '2'

services:

    gogs:
      image: gogs/gogs:latest
      restart: always
      ports:
       - "10022:22"
       - "10080:3000"
      volumes:
       - "./gogs:/data"

    drone-server:
        image: drone/drone:0.7
        ports:
          - 10081:8000
        volumes:
          - ./drone:/var/lib/drone/
          - /tmp/cache:/cache
        restart: always
        environment:
          - DRONE_OPEN=true
          - DRONE_DEBUG=false
          - DRONE_DATABASE_DRIVER=mysql
          - DRONE_DATABASE_DATASOURCE=root:123456@tcp(docker.for.mac.localhost:3306)/drone?parseTime=true
          - DRONE_GOGS=true
          - DRONE_GOGS_URL=http://docker.for.mac.localhost:10080
          - DRONE_GOGS_PRIVATE_MODE=true
          - DRONE_GOGS_SKIP_VERIFY=true
          - DRONE_SECRET=123213123123
          - DRONE_ADMIN=指定gog中的用户名
          - DRONE_HOST=docker.for.mac.localhost

    drone-agent:
        image: drone/drone:0.7
        command: agent
        restart: always
        depends_on: [ drone-server ]
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - /tmp/cache:/cache
        environment:
          - DRONE_SERVER=ws://drone-server:8000/ws/broker
          - DRONE_SECRET=123213123123
          - DRONE_HOST=docker.for.mac.localhost

接着,执行Docker命令启动

$ docker-compose up -d

这样正常的话,应该就能够跑起来了。访问http://127.0.0.1:10080,进行Gogs安装

图片

访问http://127.0.0.1:10081,进行Drone访问。

图片

虽然这里只写了一个配置文档,但是实际安装过程,过程还是非常坎坷的。

最大的坑莫过于容器宿主机通信。因为本机的数据库不是通过Docker方式安装的,因此,这里就涉及到容器访问宿主机的问题了。127.0.0.1和localhost都是指向的是容器自己本身。查看Docker文档,Mac下Docker提供了docker.for.mac.localhost这么一个东西来指向宿主机的IP。后面很多地方的容器通信,都是需要注意改成这个才能成功运行。

部署一个Laravel项目

上面安装好了环境之后,下面就是实践,编写一个项目进行测试。

在项目根目录新建.drone.yml文件,编写相关的部署等流程。当项目push到gogs时,gogs会触发webhooks向Drone发送一个请求。Drone收到这个请求之后,会根据.drone.yml的内容自动执行打包构建部署流程。

因此,我们需要在.drone.yml中定义好需要做的事情。如下,是我开发用的一个yml文件

workspace:
  base: /root
  path: src/gogs/memosa/demo

pipeline:
  restore-cache:
    image: drillster/drone-volume-cache
    restore: true
    mount:
      - ./vendor
    volumes:
      - /tmp/cache:/cache
    ttl: 7

  build:
    image: composer
    commands:
      - composer config -g repo.packagist composer https://packagist.phpcomposer.com
      - composer install --prefer-dist --no-plugins --no-scripts --optimize-autoloader --no-progress --no-interaction

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

  tests:
    image: php
    commands:
      - cp .env.staging .env
      - php artisan key:generate
      - ./vendor/bin/phpunit

  deploy:
    image: drillster/drone-rsync
    secrets: [ RSYNC_KEY ]
    user: "memosa"
    hosts: [ 你的服务器IP ]
    port: 22
    key: $RSYNC_KEY
    source: ./
    target: /work/demo
    args: "--exclude-from 'exclude.txt'"
    delete: true
    script:
      - cd /work/demo
      - ls -alh
      - pwd
      - php artisan storage:link
    # when:
    #   event: deployment
    #   environment: production

    notify:
      image: drillster/drone-email
      secrets: [EMAIL_PASSWORD]
      host: smtp.sina.com
      username: aaronx_x@sina.com
      password: $EMAIL_PASSWORD
      from: aaronx_x@sina.com
      recipients: [ 415397228@qq.com ]
      when:
        status: [ failure ]

branches: master

因为Drone是基于Docker的。因此,可以很方便的使用其他的Docker镜像,来做一些事情。Drone官方也提供了一些的插件,来方便开发者进行一些操作。上面的yml文件中,我用到了了3个Drone插件: 使用drillster/drone-volume-cache缓存vendor目录,这样不用每次都重新安装composer包;使用drillster/drone-rsync将代码部署到服务器,也就是rsync;使用drillster/drone-email,当构建失败的时候,邮件通知用户。

需要注意的地方是,使用drone-volume-cache插件,需要在项目的设定中,设置该项目Trusted;使用drone-rsync插件时,需要指定RSYNC_KEY,也就是部署的ssh_key,看文档

一张成功打包构建的图片

图片

如果顺利的话,就搭建好了一个完整的自动化开发部署环境。Gogs虽然轻量级,但是基础的一些功能还是有的。例如,分支保护这些。合理设置,也可以找到适合自己的工作流。

最后

对于这个过程,也有不完美的地方。Drone的很多插件是支持项目部署到Docker上。我这里,是传统的rsync方式,以后也可以尝试Docker化。