美文网首页Amazing .NETAmazing Arch.NET
通过 Azure Pipelines 实现持续集成之docker

通过 Azure Pipelines 实现持续集成之docker

作者: 天天向上卡索 | 来源:发表于2019-03-02 23:54 被阅读1次

    通过 Azure Pipelines 实现持续集成之docker容器化

    Intro

    Azure DevOps Pipeline 现在对于公开的项目完全免费,这对于开源项目来讲无疑是个巨大的好消息,在 Github 的 Marketplace 里有个 Azure Pipeline,就是微软的 Azure DevOps Pipeline。

    实现 Docker 容器化的持续集成

    实现的目标:

    • push 代码自动打包 docker 镜像并上传至docker hub
    • ssh 自动部署到虚拟机上

    有了docker image 之后后面就可以按照自己的需求加以定制了,比如通过ssh部署到服务器或者进行服务通知等。

    新建 Pipeline

    可以在 Azure 的 devops 新建一个 pipelines 的项目来专门管理 Github 上的pipeline

    新建一个pipeline

    第一次使用的话,会需要进行授权

    授权之后就可以选择 Github 上的项目了,选择要配置的项目

    可以基于模板创建也可以选择下面基于已有的 yaml 文件创建

    Azure pipeline config

    这里提供一份示例,源代码在这里

    # Docker image
    # Build a Docker image to deploy, run, or push to a container registry.
    # Add steps that use Docker Compose, tag images, push to a registry, run an image, and more:
    # https://docs.microsoft.com/azure/devops/pipelines/languages/docker
    
    pool:
      vmImage: 'Ubuntu 16.04'
    
    variables:
      imageName: '$(dockerId)/activityreservation'
    
    steps:
    
    - script: |
        docker build -f Dockerfile -t $(imageName) .
        docker login -u $(dockerId) -p $(pswd)
        docker push $(imageName)
    

    pipeline 配置解析

    1. agent pool 配置

    通过 vmImage 来指定要用来执行 build 任务的 agent

    pool:
      vmImage: 'Ubuntu 16.04'
    
    1. variables

    可以通过 variables 来指定一些全局变量,这里我用了一个 imageName 的变量来设置 docker 镜像的名称

    variables:
      imageName: 'activityreservation'
    
    1. 敏感信息的存储

    要上传 docker 镜像,我这里是直接上传到 docker hub 上,需要 docker 的用户名以及密码,pipeline 可以设置一些不配置在 pipeline 配置文件里的其它配置,一些敏感信息就可以这样配置来保证安全访问

    可以将 pipeline 独有的一些配置放在 Pipeline Variables 里,一些比较通用的,别的 pipeline 也会使用的变量可以放到一个 Variable groups,然后在 pipeline 的 variables 里 link 一下对应的 Variable Group 就可以使用 group 里配置的变量了,我把 docker 的 username 和 password 配置在了一个 docker 的 Variable Group 里。

    pipeline settings
    1. docker 镜像的打包以及上传

    配置 pipeline 的 step,step 对应的就是需要 build agent 去执行的task

    steps:
    
    - script: |
        docker build -f Dockerfile -t $(imageName) .
        docker login -u $(dockerId) -p $(pswd)
        docker push $(imageName)
    

    配置上面的脚本我们就可以自动 build 并 push docker 镜像了。

    build 完成之后再去 docker hub 上查看对应的 docker 镜像就会发现 docker 镜像已经更新了。

    在 vm 上自动部署 docker 镜像

    首先要在 pipeline 上新建一个 SSH 的 Service Connection

    steps:
    
    - script: |
        docker build -f Dockerfile -t $(imageName) .
        docker login -u $(dockerId) -p $(pswd)
        docker push $(imageName)
    
    - task: SSH
      displayName: 'Run shell inline on remote machine'
      inputs:
        sshEndpoint: 'weihanli-vm'
        runOptions: inline
    
        inline: |
         containers=$(docker ps -q --filter name=activityreservation)
         if test -n "$containers"; then
          docker stop $(docker ps -q --filter name=activityreservation) >> /dev/null 2>&1
          rc=$?
          if [[ $rc != 0 ]];
          then
           echo 'failed to stop container...'
           exit $rc;
          fi
         fi
         
         containers1=$(docker ps -q -a --filter name=activityreservation)
         if test -n "$containers1"; then
          docker rm $(docker ps -q -a --filter name=activityreservation) >> /dev/null 2>&1
          rc=$?
          if [[ $rc != 0 ]];
          then
           echo 'failed to remove container...'
           exit $rc;
          fi
         fi
         
         
         docker pull $(imageName):latest >> /dev/null 2>&1
         rc=$?
         if [[ $rc != 0 ]];
         then
          echo 'failed to pull container...'
          exit $rc;
         fi
         
         docker run -d -p 7010:80 --name activityreservation --link redis:redis-server $(imageName):latest >> /dev/null 2>&1
         rc=$?
         if [[ $rc != 0 ]];
         then
          echo 'failed to run container...'
          exit $rc;
         fi
         
         danglings=$(docker images -f "dangling=true" -q)
         if test -n "$danglings"; then
          docker rmi $(docker images -f "dangling=true" -q) >> /dev/null 2>&1
          rc=$?
          if [[ $rc != 0 ]];
          then
           echo 'failed to remove danglings container...'
           exit $rc;
          fi
         fi
    

    sshEndpoint 设置为连接的名称,inline 后面是在远程执行的脚本,大概流程如下:

    1. 检查是否有指定名称的 container 在运行,如果有 stop 并 remove
    2. 拉取最新的 docker 镜像
    3. 运行 docker 容器
    4. 移除可能的悬挂镜像(名称为 none 的中间镜像)

    验证

    配置完成之后我们就可以提交代码,就会自动出发 build,自动执行我们定义的 pipeline 任务,按照上面的配置的话,就会先 build 并 push Docker 镜像到 docker hub,然后 SSH 到远程服务器,远程过去之后执行脚本,停掉并移除指定的 docker 容器(如果有)然后拉取并部署最新的docker镜像,最后清理资源,删除 docker 悬挂镜像。

    示例项目

    现在有两个项目是这种模式去自动化部署的,源代码以及 pipeline 的配置都在 Github 上

    现在这两个项目的部署模式是这样的:

    前面一个 nginx 作为反向代理,后面是直接跑在 docker 容器里

    nginx 示例配置:

    server {
          listen 80;
          listen 443;
          if ($scheme = http) {
              return  301 https://$host$request_uri;
          }
          server_name reservation.weihanli.xyz;
    
          location / {
             proxy_pass http://localhost:7010;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }
    }
    

    这里会把 reservation.weihanli.xyz 的请求转发到 localhost:7010 ,也就是这个 docker 镜像映射的本地端口

    Memo

    如果有什么问题或建议,欢迎与我联系

    相关文章

      网友评论

        本文标题:通过 Azure Pipelines 实现持续集成之docker

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