渔笙 發表於 2021-12-13 19:29:00

基于Github Actions + Docker + Git 的DevOps方案实践教程

<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>为什么需要DevOps</li><li>如何实践DevOps<ul><li>版本控制工具(Git)<ul><li>学习使用</li><li>配置环境</li></ul></li><li>源代码仓库</li><li>一台配置好环境的云服务器<ul><li>SSH远程登录</li><li>在服务器上安装docker<ul><li>docker技术准备工作</li><li>安装docker</li></ul></li><li>使用docker安装mysql</li></ul></li><li>选择合适的CI/CD平台</li><li>在本地代码仓库中配置好dockerfile<ul><li>尝试使用docker在本地打包构建部署</li></ul></li><li>使用Github Actions自动化打包构建<ul><li>workfile详解<ul><li>actions/checkout@v2</li><li>actions/setup-dotnet@v1</li><li>docker/login-action@v1.10.0</li><li>docker/build-push-action@v2</li><li>appleboy/ssh-action@master</li></ul></li></ul></li></ul></li><li>演示效果</li><li>心得</li></ul></div><p></p>
<h1 id="为什么需要devops">为什么需要DevOps</h1>
<p>dveops的概念提出已经近十年,各种devops的实践方案已经陆续在各个开发团队应用,通过版本控制工具(Git、SVN) + 源代码仓库(Gitee、Github) +CI/CD平台(Jenkins、Github actions、Travis CI...)的DevOps方案使得开发人员的开发体验得到极大的提升,即减少了开发和运营的成本又提高了产品质量...</p>
<p>由于个人阅历不足无法继续详细阐述DevOps的优势和作用,所以我推荐了一篇blog</p>
<p>devops基础理念梳理</p>
<h1 id="如何实践devops">如何实践DevOps</h1>
<p>废话说那么多,不如实践一下见好坏,以Jenkins、Github actions、Travis CI等等CI/CD平台为中心都可以很好的做到持续集成持续部署,在码云源代码仓库中我们可以看到如下流行的devops方案</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213123551508.png" alt="image-20211213123551508" loading="lazy"></p>
<p>以及在Github中集成的Actions</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213123709387.png" alt="image-20211213123709387" loading="lazy"></p>
<p>所以我们真正搭建这样一个流水线平台到底需要使用什么技术,掌握什么工具?</p>
<p>我总结如下:</p>
<ol>
<li>掌握流行的版本控制工具(Git,SVN)基本使用方法</li>
<li>依托一个源代码仓库(Github、Gitee)</li>
<li>基本的linux运维技术(SSH远程、Docker)</li>
<li>一个CI/CD平台(Jenkins、Github Actions、Travis CI...)</li>
</ol>
<p><strong>就这么多,不需要掌握任何编程技巧!</strong></p>
<p>以上每一个技术精通都是不容易的,但是我们只需要任选其一掌握基本方法,能串起来就行。</p>
<p>我根据自己的技术栈设计了这样一个DevOps的方案</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/Untitled%20(1).png" alt="Untitled (1)" loading="lazy"></p>
<p>为此我们需要按部就班做一些准备工作</p>
<h2 id="版本控制工具git">版本控制工具(Git)</h2>
<h3 id="学习使用">学习使用</h3>
<p>学习使用方法,这里我推荐廖雪峰的Git学习网站,阮一峰-Git命令清单,阮一峰-Git原理</p>
<h3 id="配置环境">配置环境</h3>
<ol>
<li>
<p>安装软件git官网</p>
</li>
<li>
<p>检验安装</p>
<pre><code>git --version
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213131225874.png" alt="image-20211213131225874" loading="lazy"></p>
</li>
<li>
<p>配置本地用户信息</p>
<pre><code>git config --global user.name "Name"
git config --global user.email "**.com"
git config --list
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213131544008.png" alt="image-20211213131544008" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213131726959.png" alt="image-20211213131726959" loading="lazy"></p>
</li>
</ol>
<h2 id="源代码仓库">源代码仓库</h2>
<p>这里我就不赘述了,太简单了,搜索引擎找一找,如图所示,我在github上建了一个这样的仓库(空仓库就行,代码可以后加)<img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213132238551.png" alt="image-20211213132238551" loading="lazy"></p>
<p><strong>注意,本教程依托了Github Actions这样一个平台,必需使用Github,所以网络问题需要自己解决</strong></p>
<p>我们准备了如下图所示目录结构的一个基于Asp .NET Core 6 的一个图书管理系统的项目。然后将源代码推送到远程代码仓库如上图所示。(推送指令就不在详细描述,掌握了git的基本使用就会明白)</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213161812137.png" alt="image-20211213161812137" loading="lazy"></p>
<h2 id="一台配置好环境的云服务器">一台配置好环境的云服务器</h2>
<p>为此我准备了一台4g运行内存,8M带宽的腾讯云服务器。操作系统为ubuntu</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213162915469.png" alt="image-20211213162915469" loading="lazy"></p>
<h3 id="ssh远程登录">SSH远程登录</h3>
<p>你可以使用云服务器控制台提供的远程工具,也可以使用xshell之类的远程控制工具。为了之后的操作能够尽可能顺利进行,你需要会使用一些基本的linux指令,可以看看这个linux快速上手视频。</p>
<p>xshell有免费版,下载安装后如下新建一个会话</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213164150612.png" alt="image-20211213164150612" loading="lazy"></p>
<p>之后按照提示输入账户名和密码就好</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213163900427.png" alt="image-20211213163900427" loading="lazy"></p>
<h3 id="在服务器上安装docker">在服务器上安装docker</h3>
<h4 id="docker技术准备工作">docker技术准备工作</h4>
<p>这里我随便找了个视频狂胜-docker详细教程,大致看一下就能对docker有一个了解</p>
<p>一篇博客为什么要使用docker</p>
<p>我们知道一个项目要想运行起来是需要运行环境的,为了运行一个java项目我们为服务器安装对应版本的Jdk或Jre, 一个.Net应用想要运行起来需要对应版本的.Net FrameWork 或者.Net Core 的SDK,比如我们日常使用的可执行程序qq,weixin等等都是需要运行环境的,只不过windows提前安装好了各种版本的.Net Framework,使得我们安装好应用后就能直接使用。又比如在服务器上安装相应的数据库(mysql,sqlserver),管理这些开发环境是相当烦人的,但是当我们使用了docker这样一个容器化技术后库,代码即环境,可以在任何一台装有docker的服务器上运行,不需要配置任何环境。</p>
<h4 id="安装docker">安装docker</h4>
<p>菜鸟教程-ubuntu安装docker</p>
<h3 id="使用docker安装mysql">使用docker安装mysql</h3>
<p>有了docker我们安装mysql将变得easy</p>
<pre><code>docker pull mysql
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213170543918.png" alt="image-20211213170543918" loading="lazy"></p>
<p>检查一下我们拉去下来的docker镜像</p>
<pre><code>docker images
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213170707008.png" alt="image-20211213170707008" loading="lazy"></p>
<p>运行</p>
<pre><code>docker run -d --name mysql3306 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=******* mysql
</code></pre>
<p>查看一下正在运行的的服务</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213171048914.png" alt="image-20211213171048914" loading="lazy"></p>
<p>这样我们就创建按好了一个服务器上的数据库,这样的数据库不仅能用于生产环境,用来学习也是不错的,毕竟在笔记本上装数据库会比较占内存。</p>
<p>于是我就能在我的项目中配置数据库连接字符串使用这个数据库了<img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213171540367.png" alt="image-20211213171540367" loading="lazy"></p>
<p>不管这个项目在哪台主机上启动,都是可以成功运行的,毕竟数据库的Ip, 密码都是固定的。</p>
<h2 id="选择合适的cicd平台">选择合适的CI/CD平台</h2>
<p>如前文所说,我所用的是Github actions,最初我是在Asp .NET Core的官网文档上了解到的这个技术,自从github被微软收购后,Github actions就一直是微软推荐CI/CD技术。</p>
<p>Github Actions官网文档</p>
<p>想要真正理解这门技术,最好阅读一下英文版的文档,在看完“Understanding Github Actions"和”Finding and Customizing actions"这两栏的介绍后,基本上就可以上手Github Acitions了</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213172251298.png" alt="image-20211213172251298" loading="lazy"></p>
<p>推荐一篇blog,看完后你可以对其有个简单了解 阮一峰-github actions入门</p>
<h2 id="在本地代码仓库中配置好dockerfile">在本地代码仓库中配置好dockerfile</h2>
<p>在我的项目中实现如下</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213173005228.png" alt="image-20211213173005228" loading="lazy"></p>
<pre><code class="language-dockerfile">FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["BMS.csproj", "./"]
RUN dotnet restore "BMS.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "BMS.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "BMS.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "BMS.dll"]
</code></pre>
<h3 id="尝试使用docker在本地打包构建部署">尝试使用docker在本地打包构建部署</h3>
<p>我们使用docker就可以根据这个文件将项目源码按照我们想要的方式打包构建好</p>
<p>这里我们简单演示一下,进行该测试需要在本地电脑安装docker,</p>
<p>切换到有dockerfile的项目目录下使用</p>
<pre><code>docker build .
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213173429247.png" alt="image-20211213173429247" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213174130158.png" alt="image-20211213174130158" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213174331904.png" alt="image-20211213174331904" loading="lazy"></p>
<p>这个没有tag的镜像就是我们刚刚构建的</p>
<pre><code class="language-dockerfile">docker run -d --name bmstest -p 8080:80 7ab686d20640
</code></pre>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213174929024.png" alt="image-20211213174929024" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213175003600.png" alt="image-20211213175003600" loading="lazy"></p>
<p>打开游览器检查一下是否成功运行</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213175139597.png" alt="image-20211213175139597" loading="lazy"></p>
<p>成功了!</p>
<p>但是,还不够方便,虽然我们每次修改完代码运行几个命令就运行好了,别人也可以拿着我们的镜像去运行程序,但是执行的命令是固定的,我们能不能在修改完代码后就自动让其打包构建部署,事实证明是可以的,人类也是可以在偷懒中进步的。</p>
<h2 id="使用github-actions自动化打包构建">使用Github Actions自动化打包构建</h2>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213182007308.png" alt="image-20211213182007308" loading="lazy"></p>
<p>我们们在项目目录workflows下建立自己的workfile</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213182422517.png" alt="image-20211213182422517" loading="lazy"></p>
<pre><code class="language-yml">name: .NET

env:
IMAGE_NAME:test

on:
push:
    branches: [ master ]
pull_request:
    branches: [ master ]

jobs:
build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
      dotnet-version: 6.0.x
    - name: Restore dependencies
      run: dotnet restore
    - name: Test
      run: dotnet test --no-build --verbosity normal
    - name: Docker Login
      uses: docker/login-action@v1.10.0
      with:
      username: ${{ secrets.DOCKER_USERNAME }}
      password: ${{ secrets.DOCKERHUB_TOKEN }}
    - name: Build and Push
      uses: docker/build-push-action@v2
      with:
      tags: horaoen/app:latest
      push: true
      context: ./BMS
    - name: deploy
      uses: appleboy/ssh-action@master
      with:
      host: ${{ secrets.HOST }}
      username: ${{ secrets.HOST_USERNAME }}
      key: ${{ secrets.HOST_SSHKEY }}
      script: |
          docker stop bms-container
          docker rm bms-container
          docker rmi horaoen/app:latest
          docker pull horaoen/app:latest
          docker run -d --name bms-container -p 8080:80 horaoen/app
</code></pre>
<p>可以看到这里的yml文件引用了几个变量,这些是有关用户安全的东西不能直接写在配置文件中,需要在github 的仓库中设置</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213182841482.png" alt="image-20211213182841482" loading="lazy"></p>
<p>添加自己需要的密钥</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213182952946.png" alt="image-20211213182952946" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213182911695.png" alt="image-20211213182911695" loading="lazy"></p>
<h3 id="workfile详解">workfile详解</h3>
<p>关于上面这个dotnet.yml的Github Actions的配置文件怎么写的需要先了解Github Actions的基本原理</p>
<p>然后掌握一下几个Actions的使用</p>
<p>其实这些actions用户下项目,基本格式是users/repository,是一些别人写好的脚本,通过重复利用别人写好的脚本,我们可以很方便的做许多事</p>
<h4 id="actionscheckoutv2">actions/checkout@v2</h4>
<p>这个是用于将远程仓库中的源代码拉取到workfile自动化构建脚本运行的服务器,在我们这里是github提供的ubutu latest(这在配置文件中写的有)</p>
<h4 id="actionssetup-dotnetv1">actions/setup-dotnet@v1</h4>
<p>这个是用于搭建项目的基本环境</p>
<h4 id="dockerlogin-actionv1100">docker/login-action@v1.10.0</h4>
<p>docke官方给的antion,用于登录docker以便我们后续上传docker镜像到自己的镜像仓库</p>
<h4 id="dockerbuild-push-actionv2">docker/build-push-action@v2</h4>
<p>构建docker镜像,推送到自己的docker镜像仓库,这个context参数是比较难理解的,实际上是相对以远程代码仓库的根路径的Dockerfile的路径<img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213184619882.png" alt="image-20211213184619882" loading="lazy"></p>
<p>在这个aciton的官网文档中介绍到,Dockerfile的文件路径默认在context/Dockerfile 下,所以这个配置很重要不能配错。</p>
<h4 id="appleboyssh-actionmaster">appleboy/ssh-action@master</h4>
<p>在我们成功将docker镜像推送到镜像仓库后,需要ssh连接我们自己要部署项目的服务器,然后在其上运行一系列docker commond去部署项目。</p>
<p>其它参数一目了然,唯独这个稍微麻烦,它是我们将要连接到的服务器的ssh私钥,在这个action的官网中给出了教程<img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213185043823.png" alt="image-20211213185043823" loading="lazy"></p>
<p>官网文档</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213185346575.png" alt="image-20211213185346575" loading="lazy"></p>
<p>可以照着教程,其实你已经看到这里就说明具备解决这个问题的能力,详细步骤可以查一下博客怎么配置ssh密钥。需要注意的是复制尽量用指令去复制,错一个字符都不行</p>
<p><font color="red">私钥一定要把上下分割线也复制上,巨坑!!!</font></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213185848449.png" alt="image-20211213185848449" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213185905667.png" alt="image-20211213185905667" loading="lazy"></p>
<h1 id="演示效果">演示效果</h1>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213190350169.png" alt="image-20211213190350169" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213190411877.png" alt="image-20211213190411877" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213190549952.png" alt="image-20211213190549952" loading="lazy"></p>
<p>查看项目</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213190823418.png" alt="image-20211213190823418" loading="lazy"></p>
<p>我们发现有乱码,这里正好模拟实际项目中的bug,现在我们修改代码修复bug</p>
<p>实际上改一下encoding就好了,然后重新提交代码</p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213191453683.png" alt="image-20211213191453683" loading="lazy"></p>
<p><img src="https://gitee.com/horaoen/blogImage/raw/master/img/image-20211213192103688.png" alt="image-20211213192103688" loading="lazy"></p>
<p>成功了!!</p>
<h1 id="心得">心得</h1>
<p>显然从结果来看,这很方便,但是学习技术的过程是很痛苦的,如果把学习过程放到比较条件中去是不公平的,学习一次收益很久,但是不做改变就会一直麻烦。</p>
<p>评论区可以留言,我会尽力解答。</p><br><br>
来源:https://www.cnblogs.com/horaoen/p/15684842.html
頁: [1]
查看完整版本: 基于Github Actions + Docker + Git 的DevOps方案实践教程