likes
comments
collection
share

应用程序自动化部署

作者站长头像
站长
· 阅读数 57

由于前后端程序都是使用 docker 部署,每次代码更新后都需要更新镜像并新建容器,手动在虚拟机上更新非常麻烦且浪费时间,所以需要一个能够让整个流程自动化的方法。 由于代码放在了 github,所以首先想到的就是github action,借助这个可以实现:每次 push 代码自动构建镜像并 push 到 Docker Hub。

第一步:创建工作流相关文件

在项目的根目录下新建 .github/workflows/xxx.yaml文件

踩坑:

文件夹名称必须是.github/workflows,且必须放在项目根目录下,否则 github 不会将其识别为 github action 的配置文件。

第二步:创建镜像构建配置文件 build-image.yml

name: build-image
run-name: ${{ github.actor }} is building latest image
on: [push]
jobs:
  build_vue_app_image:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
      - name: Build vue_app image
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
        run: |
          docker build -t yanyue1215/vue_app .
          docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
          docker push yanyue1215/vue_app
      - name: build_resume_service
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
        run: |
          cd Backend/    # 后端代码所在目录
          docker build -t yanyue1215/resume_service .
          docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
          docker push yanyue1215/resume_service

这里的DOCKER_USERNAMEDOCKER_PASSWORD两个环境变量都是通过配置 github 该项目仓库的secrets获取到的。设置路径为Setting-Security-secrets and variables-Actions-新建仓库 secret

踩坑 1:

这里的设置并不是新建一个 secret:Name 为你的 Docker Hub 账号,Value 为 Docker Hub 的 access token。而是新建两个 secret:

NameValue
DOCKER_USERNAMEDocker Hub 账号名
DOCKER_PASSWORDDocker Hub Access Token

踩坑 2:

workflow 报错:invalid workflow file,you have error in your yaml syntax on line11 查看了下代码,发现第 11 行是设置环境变量:

env:  DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}

错误的原因是 yaml 文件中使用缩进表示层级关系,相同层级的元素必须左对齐,而这里 env下面的环境变量是 env 的下一级,但是却和它放在了同一行,所以报错了,修改为:

- name: Build vue_app image
  env:
    DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
    DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}

如此之后,每当 push 代码到对应分支后,github 就会自动构建最新镜像并推送到 Docker Hub。但是这个时候你还是需要自己去虚拟机上拉取最新镜像并重建容器,依旧很麻烦,如果这个过程也能能自动化就最好了。 一开始考虑的是是否和 umc-ui 项目一样使用MakeFile,但是最后还是希望能把更新和部署都集成到 github 的工作流程中。但是由于 github action 本身并不支持直接将应用程序部署到私人的虚拟机上,需要和其他工具相结合,

方案:在 yml 文件中编写一个部署脚本,通过 ssh 连接到虚拟机并执行对应的部署命令

第三步:创建 deploy 配置文件 deploy.yml

name: push-to-private-machine
run-name: ${{ github.actor }} is deploying
on:
  workflow_run:
    workflows: ['build-image'] #依赖的工作流程文件的名称
    types:
      - completed

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
      - name: Add known hosts
        run: | # 将虚拟机密钥添加到 GitHub Runner 的 "known_hosts" 文件中
          mkdir -p ~/.ssh
          ssh-keyscan 116.204.108.126 >> ~/.ssh/known_hosts
      - name: remove old container
        run: |
          sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "docker ps -a | grep yanyue1215/vue_app | awk '{print $1}' | xargs -r docker rm -f"
          sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "docker ps -a | grep yanyue1215/resume_service | awk '{print $1}' | xargs -r docker rm -f"
          sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "docker system prune -a"
      - name: pull latest front_image
        run: sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "docker pull yanyue1215/vue_app:latest"
      - name: pull latest backend_image
        run: sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "docker pull yanyue1215/resume_service:latest"
      - name: Deploy to Virtual Machine
        run: sshpass -p ${{ secrets.SSH_PASSWORD }} ssh root@116.204.108.126 "cd /root/resume_generator_front && /usr/local/git/bin/git pull origin master && docker-compose up -d"

踩坑 1:

ssh 连接在不使用 sshpass 密码连接的时候一直报错:permission denied(public key,password),目前还没有找到解决方法,采用 sshpass 连接作为替代方案

踩坑 2:

虚拟机上安装了 git,但是执行到git pull xx却报错:

git: command not found error:Process completed with exit code 127

猜测原因是 Github Actions 的工作流程中无法找到 git 命令。解决方案是在虚拟机上执行which git命令获取到 git 的实际位置,然后将其替换到命令中。

# 原来的命令:
git pull origin master
# 修改后的命令:
/usr/local/git/bin/git pull origin master

在此基础上,我希望两个 workflow 有明确的先后执行顺序,即部署应该在镜像构建已经完成的基础上执行,否则会造成流程混乱。

workflow 的顺序执行有两种方式:

  1. 将两个 workflow 放在同一个 yaml 文件中,通过依赖关系来定义他们之间的顺序
jobs:
  build-images:
    # xxxx
  deploy:
    needs: build-images
    # xxx
  1. 将两个 workflow 放在不同的 yaml 文件中,通过workflow_run达到顺序执行的目的
# build-image.yml 不做任何修改
# deploy,.yml
name: deploy
on:
  workflow_run:
    workflows: ['build-image']
    types:
      - completed

此方案中,deploy.yml会监听workflow_run事件,并指定依赖的工作流程为build-image

踩坑:

第一个流程执行完之后并没有执行自动化部署。给出的原因是需要两个工作流程文件的名称正确且匹配 解决方案是将所有 yml 文件和他们里面的name值保持一致

转载自:https://juejin.cn/post/7270798922150084664
评论
请登录