使用Github Actions + Watchtower 实现项目CI/CD
前言
对于我们这种个人开发者,将程序部署在服务器上一般都是通过宝塔部署来确保服务能够一直存活,但是对于一个经常改来改去的项目,这是一个非常头疼的事情,需要重复地本地编译-->打开宝塔-->输入账号密码(甚至安全模式无法记住密码,需要自己输入密码)-->上传文件-->重启代码服务。
对于一个聪明的程序员来说,一切重复的工作都应该交给代码来运行,恰巧前几天,在写公司项目的时候,我的导师跟我说改完的代码直接push到github的test分支,等待几分钟代码就部署好了,这不正是我想要的自动化吗,之后查了一下这个叫项目CI/CD,公司使用的技术有Github Actions,Dokcer容器,Watchtower,来实现代码自动部署的,注意,这类技术在Watch Tower官方文档中明确写出,不建议在生产环境中使用该技术,即使他会在有新版本可以更新时,优雅地关闭正在运行的程序,但可能造成重大安全事故。
本文会从编写Dockerfile入手,学习如何推送镜像,如何编写workflow文件编写github工作流,之后配置watchtower实现代码自动更新。
本文需要前置知识:docker相关操作,Dockerfile编写。
组件介绍
首先先理解几个概念。
项目CI/CD
在互联网开发中,CI 和 CD 是两个常用的缩写词,分别代表持续集成(Continuous Integration)和持续交付/持续部署(Continuous Delivery/Continuous Deployment)。
持续集成(Continuous Integration,CI):
持续集成是一种开发实践,旨在通过频繁地将代码合并到主干分支,并进行自动化构建、测试和部署等操作,以确保团队成员的工作能够快速且无冲突地集成到共享代码库中。CI 的目标是尽早发现和解决代码集成问题,并提供可靠的构建和测试过程,以减少集成带来的风险。
在 CI 中,开发者在完成某项工作后,会将代码变更提交到版本控制系统(如 Git),触发自动化构建和测试流程。这些流程通常包括编译代码、运行单元测试、进行静态代码分析等。如果构建和测试通过,代码变更就可以合并到共享代码库,否则需要开发者修复问题。
持续交付/持续部署(Continuous Delivery/Continuous Deployment,CD):
持续交付和持续部署是指在 CI 的基础上,通过自动化流程将经过验证的代码变更交付给生产环境。
持续交付(Continuous Delivery):持续交付意味着代码变更通过了构建和测试,并已经准备好进行部署,但是部署的时机由人工决定。在持续交付中,开发团队可以随时选择将已验证的代码发布到生产环境,以快速响应用户需求或满足业务的要求。
持续部署(Continuous Deployment):持续部署是在持续交付的基础上更进一步,自动化地将经过验证的代码变更直接部署到生产环境,无需人工干预。在持续部署中,如果代码通过了构建和测试,它将立即被部署到生产环境,从而实现快速的软件发布。
总结来说,CI 是一种开发实践,旨在帮助团队更好地集成和验证代码,而 CD 则进一步强调了对代码变更的自动化交付和部署。持续集成和持续交付/持续部署的实践能够提高开发效率、减少错误,并使团队能够更快地交付高质量的软件产品。
Github Actions
GitHub Actions 是一个持续集成(Continuous integration)和持续交付(Continuous delivery)的平台,它可以做到自动化构建、测试、部署。你可以创建工作流,构建和测试每一个 pull request 或者部署合并后的代码到生产环境。GitHub Actions 可以在你的代码仓库发生某个事件时运行一个工作流。举个例子,当有人给你的项目提出issue时,可以自动通知团队成员等。GitHub 提供了 Linux、Windows、和 macOS 虚拟机运行你的工作流,当然你也可以自定义运行环境。
在本文中主要用于使用Github Actions来进行项目CI,当有代码提交到指定分支时,会自动打包容器镜像并推送到docker hub,用于更新镜像仓库的镜像。
Docker容器
一种轻量级的虚拟化技术,也是目前主流的应用部署策略
Docker容器**是一种轻量级的虚拟化技术,使用开源的应用容器引擎。
这种技术可以让开发者将应用及其依赖打包到一个可移植的容器中,然后发布到任何安装了Docker引擎的服务器上,这些服务器可以是流行的Linux或Windows机器,Docker容器提供了一种比传统虚拟机更轻量化的虚拟化方式,具有安装便捷、启停速度快的特点。
容器之间是完全隔离的,使用沙箱机制,相互之间不会有任何接口,这种隔离机制基于Linux内核的控制组(Cgroups)和命名空间(Namespaces)技术。
容器镜像是一种轻巧、可执行的独立软件包,包含运行应用程序所需的一切,如代码、运行时环境、系统工具、系统库和设置。这些镜像在运行时成为容器,使得软件具有独立性,免受外在环境差异的影响,并有助于减少在不同基础设施上运行不同软件时的冲突。
在本文中,应用程序主要使用docker容器部署,并使用docker hub作为存储仓库。
Watchtower
[Watchtower][https://github.com/containrrr/watchtower] 是一款自由开源的应用,用来监控运行中的Docker 容器,并且当它发现基础镜像被更改后,可以自动的更新容器。 若Watchtower 发现一个运行中的容器需要更新,它会以发送SIGTERM 信号的方式,优雅的结束运行中容器的运行。 它会下载新镜像,然后以最初部署时使用的方式,重启容器。
在本文中,主要使用watch tower来做镜像更新与应用重启。
编写一个应用程序
根据自己需要编写程序
编写Dockerfile文件
编写项目需要的Dockerfile
文件。
在Github仓库新建一个workflow文件
- 在Github的仓库中有一栏Actions,点击
New workflow
,会看到几个Github 预设的几个模型,这里选择Docker image
这里附上我的配置
name: Docker Image CIon:push:branches: [ "main" ] #当有push到main分支时 jobs:build:runs-on: ubuntu-latest #运行在虚拟机环境 ubuntu-lateststeps:- uses: actions/checkout@v3 #获取源码 使用的 action 是actions/checkout@v3- name: Build the Docker image #要执行job的名称 可自定义run: | #开始运行cd app/ #我的Dockerfile文件所在目录docker login -u yjddb -p ${{ secrets.DOCKER_HUB_PASSWORD }} #登录docker hub 括号内为插值表达式,用于保护docker hub密码docker buildx create --use #使用docker buildx 比docker build功能更加强大一点docker buildx build . --push --tag yjddb/compete_cloud_app_back:latest #构建镜像并推送到指定仓库,tag设置为latest
- 编写完
workflow
文件之后还需要把自己的docker密码保存在仓库中。
编写的秘钥名称需要与dockerfile中一样才可以正常被使用
- 至此github的ci工作流已经建立完成,这时候可以自己在main分支改动提交即可在actions栏中看到CI工作流。
代码可以正常编译之后即可推送到相关dockerhub上面。
使用Watch Tower 自动更新镜像
-
在服务器上安装docker
-
在自己的服务器上面 docker pull 下来自己的镜像 然后用 正确的命令方式启动镜像
-
执行docker命令拉下来镜像并启动自动更新
docker run -d \--name watchtower \-v /var/run/docker.sock:/var/run/docker.sock \containrrr/watchtower \ --interval 30 \ #每隔30s查询一次最新镜像版本nginx redis #更新指定容器--cleanup \ #清理标签为none的镜像。--remove-volumes \ #清理匿名卷
如果不加镜像指定会监控当前正在运行容器的镜像,当有新的镜像在docker hub更新时会自动更新镜像,--interval 30代表每隔30秒进行一次查看更新操作,不指定的话默认60s ,更多配置请查看官方文档
结语
至此,就可以愉快的写代码了,没有部署项目的烦恼了。