使用 CODING 自动部署 Hyperf 项目

本篇部署不是集群部署,适合个人或小公司项目使用。

GitHub 由于是国外平台,代码拉取速度不是特别理想。所以使用了 CODING 作为代码托管平台。

Hyperf 是一款 Swoole 框架,如果是 Mac 开发可以直接在宿主机安装 Swoole 扩展进行开发,如果在 Mac 上使用 Docker 的话速度会变慢。
如果用 windows 开发,可以使用 WSL2,安装 Docker 进行开发。不过感觉还是慢,推荐使用 PhpStorm 的 Deployment 服务直接使用文件自动上传服务器,然后在服务器安装 Docker 环境进行开发。

创建基础项目#

  1. 首先我们点击右上角,创建一个项目

使用 CODING 自动部署 Hyperf 项目
进入项目后点击右上角,创建一个代码仓库

使用 CODING 自动部署 Hyperf 项目

  1. 安装 Hyperf
    安装方式
    然后和我们刚刚创建的远程仓库关联(默认大家都有这个能力)

编写构建计划#

这里先大概说下我们整体的部署流程。

首先检出分支,然后会根据分支下的 Dockerfile 生成镜像,然后推送镜像到 coding 的制品仓库。最后登录服务器拉取镜像进行部署。

流程清楚了那么我们就开始编写构建计划吧

  1. 创建构建计划
    首先我们先创建一个构建计划,构建计划就是弄一套指令,让它按照我们自己设定的规则执行
    使用 CODING 自动部署 Hyperf 项目
    然后选择构造计划模板,我们这里选择自定义模板

使用 CODING 自动部署 Hyperf 项目

按照默认配置即可,这里我们先使用在线的 Jenkinsfile,后续可以根据自己需求使用代码仓库中的 Jenkinsfile

使用 CODING 自动部署 Hyperf 项目

开始进行流程配置

使用 CODING 自动部署 Hyperf 项目

  1. 生成镜像并推送

    pipeline {
    agent any
    stages {
     stage("检出") {
       steps {
         checkout([
           $class: 'GitSCM',
           branches: [[name: GIT_BUILD_REF]],
           userRemoteConfigs: [[
             url: GIT_REPO_URL,
             credentialsId: CREDENTIALS_ID
         ]]])
       }
     }
    
    stage('生成镜像') {
       steps {
         echo '生成镜像中……'
         sh 'ls'
         sh 'docker build -t ${IMAGE_NAME} -f Dockerfile ./'
         echo '生成镜像完成'
       }
     }
    
     stage('推送镜像') {
       steps {
         echo '推送镜像中...'
         sh 'docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net'
         sh 'docker tag ${IMAGE_NAME} xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
         sh 'docker push xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
         echo '推送完成'
       }
     }
    }
    }

    我们先来看生成镜像,因为 Hyperf 官方已经在项目中写好了 Dockerfile,我们可根据自己需求更改直接使用就好。很简单就是执行了一个 docker 命令,但是里面有一个镜像名,这个我们拿出来定义一个变量然后在文件中就可以通过 ${IMAGE_NAME} 这种方式来访问了。
    定义变量:

使用 CODING 自动部署 Hyperf 项目

镜像生成了,往哪儿推送?别急,我们先保存构建计划。
然后新建一个制品库,就是存放我们 docker 镜像的地方

使用 CODING 自动部署 Hyperf 项目

创建成功后,如图

使用 CODING 自动部署 Hyperf 项目

然后复制仓库中的登录和推送命令配置到我们构造计划文件中

我们这里选择使用令牌的方式进行登录,点击这个按钮,复制生成的令牌。替换刚才的登录命令

使用 CODING 自动部署 Hyperf 项目

由于登录密码是敏感的,我们按照第一次创建环境变量的方式再次新增一个变量 ${DOCKER_TOKEN} 替换登录密码

到此为止,其实已经完成项目自动生成镜像并上传仓库。已经可以在服务器手动 Docker 镜像拉取部署了。(服务器需要已安装 Docker,不然玩儿毛)

  1. 自动部署
stage('部署') {
      steps {
        echo '部署中...'
        script {
          def remote = [:]
          remote.name = 'my-server'
          remote.allowAnyHosts = true
          // 主机地址
          remote.host = '123.123.123.132'
          remote.port = 22
          // 用户名
          remote.user = 'root'
         // credentialsId: coding登录主机的秘钥
          withCredentials([sshUserPrivateKey(credentialsId: 'coding的key', keyFileVariable: 'id_rsa')]) {
            remote.identityFile = id_rsa
            // 登录并拉取镜像
            sshCommand remote: remote, command: "docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net"
            sshCommand remote: remote, command: "docker pull xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
            // 停止旧的服务,注意加 ||true,不然第一次部署会报错
            sshCommand remote: remote, command: "docker stop ${PROJECT_NAME} || true"
            sshCommand remote: remote, command: "docker rm ${PROJECT_NAME} || true"
            // 启动新服务
            sshCommand remote: remote, command: "docker run -d --restart always -p 10090:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME} -d xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
            // 再启动一个容器,防止服务中断
            sshCommand remote: remote, command: "docker stop ${PROJECT_NAME}2 || true"
            sshCommand remote: remote, command: "docker rm ${PROJECT_NAME}2 || true"
            sshCommand remote: remote, command: "docker run -d --restart always -p 10091:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME}2 -d xxx-docker.pkg.coding.net/practice/practice/blog/${IMAGE_NAME}:latest"
          }

        }
        echo '部署完成'
      }
    }

上部分配置参考了 Hyperf 作者文章
如何单机部署 Hyperf 项目

上面我们注意有个 credentialsId,这个是 coding 能登录我们服务器的关键。这个东西会在 condig 读取秘钥,然后使用秘钥登录我们的服务器进行操作。
所以服务器需要支持 ssh 秘钥登录。
生成方式:
点击项目设置:

使用 CODING 自动部署 Hyperf 项目

然后录入凭据,最后使用凭据 id 填入上面的 credentialsId

录入凭据的方法
最后我们还需要配置触发规则,也就是什么情况执行部署。推送到 master,或者推送新标签后触发。

使用 CODING 自动部署 Hyperf 项目

还有一点需要注意,由于自动部署需要访问我们的 docker 镜像仓库。所以我们需要把执行构建的服务器 IP 添加到 docker 镜像仓库的白名单里面。
(因为我们使用的免费的,所以使用了 coding 自己的服务器,基本够用。不够用可以够买 coding 提供的构建服务器。好像也不贵。)

首先复制构建服务器 ip

使用 CODING 自动部署 Hyperf 项目

写入到白名单

使用 CODING 自动部署 Hyperf 项目
然后新增两个 IP 到白名单

使用 CODING 自动部署 Hyperf 项目

保存即可

完整版 Jenkinsfile

pipeline {
  agent any
  stages {
    stage("检出") {
      steps {
        checkout([
          $class: 'GitSCM',
          branches: [[name: GIT_BUILD_REF]],
          userRemoteConfigs: [[
            url: GIT_REPO_URL,
            credentialsId: CREDENTIALS_ID
        ]]])
      }
    }

   stage('生成镜像') {
      steps {
        echo '生成镜像中……'
        sh 'ls'
        sh 'docker build -t ${IMAGE_NAME} -f Dockerfile ./'
        echo '生成镜像完成'
      }
    }

    stage('推送镜像') {
      steps {
        echo '推送镜像中...'
        sh 'docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net'
        sh 'docker tag ${IMAGE_NAME} xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
        sh 'docker push xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
        echo '推送完成'
      }
    }

    stage('部署') {
      steps {
        echo '部署中...'
        script {
          def remote = [:]
          remote.name = 'my-server'
          remote.allowAnyHosts = true
          // 主机地址
          remote.host = '123.123.123.132'
          remote.port = 22
          // 用户名
          remote.user = 'root'
         // credentialsId: coding登录主机的秘钥
          withCredentials([sshUserPrivateKey(credentialsId: 'coding的key', keyFileVariable: 'id_rsa')]) {
            remote.identityFile = id_rsa
            // 登录并拉取镜像
            sshCommand remote: remote, command: "docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net"
            sshCommand remote: remote, command: "docker pull xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
            // 停止旧的服务,注意加 ||true,不然第一次部署会报错
            sshCommand remote: remote, command: "docker stop ${PROJECT_NAME} || true"
            sshCommand remote: remote, command: "docker rm ${PROJECT_NAME} || true"
            // 启动新服务
            sshCommand remote: remote, command: "docker run -d --restart always -p 10090:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME} -d xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
            // 再启动一个容器,防止服务中断
            sshCommand remote: remote, command: "docker stop ${PROJECT_NAME}2 || true"
            sshCommand remote: remote, command: "docker rm ${PROJECT_NAME}2 || true"
            sshCommand remote: remote, command: "docker run -d --restart always -p 10091:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME}2 -d xxx-docker.pkg.coding.net/practice/practice/blog/${IMAGE_NAME}:latest"
          }

        }
        echo '部署完成'
      }
    }

  }
}

需要注意,执行前需要先创建好 env 文件,因为 Docker 挂载时如果源文件不存在会自动创建目录。参考 Docker 挂载文件不存在情况

.env 文件没想好有什么自动不需要创建的方式,写入到镜像环境变量中??
大家有好的思路可以交流

然后我们本地修改代码,推送到 master 或者推送标签根据自己设置的触发规则来。神奇的事情发生了。

使用 CODING 自动部署 Hyperf 项目

Nginx 配置

upstream test {
    server 127.0.0.1:10090;
    server 127.0.0.1:10091;
}
server {
    listen       80;
    server_name  www.xxx.com;
    location / {
        proxy_pass          http://test;
        proxy_set_header    Host                $host:$server_port;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Real-PORT         $remote_port;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }
}

到此,部署完成。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
讨论数量: 6

我用这个不到一分钟,镜像得弄个版本,不然一堆。

3年前 评论
congcong (楼主) 3年前
Lion- (作者) 3年前
congcong (楼主) 2年前

注意了,如果是部署阿里云主机。需要把构建服务器 IP 加入阿里云 ECS 主机的白名单。当然了也可以用阿里云云效。殊途同归的都是。

2年前 评论

mark 一下。等下实践试试

2年前 评论