Ubuntu & GitLab CI & Docker & ASP.NET Core 2.0 自动化发布和部署(1)
<p>相关博文:</p><ul>
<li>Ubuntu 简单安装和配置 GitLab</li>
<li>Ubuntu 简单安装 Docker</li>
<li>Ubuntu Docker 简单安装 GitLab</li>
<li>Ubuntu Docker 安装和配置 GitLab CI 持续集成</li>
</ul>
<p>服务器版本 Ubuntu 16.04 LTS。</p>
<p>经过上面四篇博文中的相关安装和配置,我们主要完成了两个容器的创建和运行:<code>gitlab</code>和<code>gitlab-runner</code>(GitLab 站点和 GitLab CI 服务):</p>
<pre><code class="language-bash">$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
696d559ce382 gitlab/gitlab-runner:latest "/usr/bin/dumb-ini..." 5 days ago Up 25 minutes gitlab-runner
ff95f354200d gitlab/gitlab-ce:latest "/assets/wrapper" 7 days ago Up 6 days (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:8888->22/tcp gitlab
</code></pre>
<p>本篇博文目的:使用 GitLab CI 脚本编译 ASP.NET Core 2.0 程序,然后将编译后的文件传输到服务器上,最后使用 SSH 连接服务器,并运行程序,完成发布和部署。</p>
<p>简单来说,就是我们每次使用<code>git push</code>提交完代码,自动完成发布和部署。</p>
<p>我们再理一下实现上面目的关键点:</p>
<ol>
<li>创建一个 ASP.NET Core 2.0 示例程序</li>
<li>完善并正确的<code>.gitlab-ci.yml</code>文件配置</li>
<li>GitLab CI 服务器使用<code>ssh</code>连接到测试服务器(在 Docker 中)</li>
<li>使用<code>scp</code>进行服务器之间的文件传输</li>
<li>使用<code>supervisor</code>进行站点程序的进程管理</li>
</ol>
<p>我花了很长时间配置第三步,其实最后解决也很简单,当然都是马后炮的结论😁,下面我们分别来进行操作。</p>
<h2 id="1-创建-aspnet-core-20-示例程序">1. 创建 ASP.NET Core 2.0 示例程序</h2>
<p>我自己创建示例程序:http://40.125.206.47/team/hwapp</p>
<p>注:服务器快过期了,大家可以随便搞😂。</p>
<p>自己创建的话,也很简单,官方教程:https://www.microsoft.com/net/core#linuxubuntu</p>
<p>我再搬运下命令(安装 .NET Core 2.0,并创建 ASP.NET Core 2.0 示例程序):</p>
<pre><code class="language-bash">$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
$ sudo sh -c 'echo "deb https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.0.0
$ dotnet new webapi -o hwapp
$ cd hwapp
</code></pre>
<p>最后,绑定下 ASP.NET Core 2.0 程序端口:</p>
<pre><code class="language-cs">public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel() //add code
.UseUrls($"http://*:8088") //add code
.UseStartup<hwapp.Startup>()
.Build();
}
</code></pre>
<h2 id="2-gitlab-ciyml-文件配置">2. .gitlab-ci.yml 文件配置</h2>
<p>我的<code>.gitlab-ci.yml</code>文件配置(http://40.125.206.47/team/hwapp/blob/master/.gitlab-ci.yml):</p>
<pre><code class="language-yml">image: microsoft/aspnetcore-build
stages:
- build
- deploy_dev
before_script:
# Install ssh-agent if not already installed, it is required by Docker.
# (change apt-get to yum if you use a CentOS-based image)
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# Run ssh-agent (inside the build environment)
- eval $(ssh-agent -s)
# Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
# error: https://gitlab.com/gitlab-examples/ssh-private-key/issues/1
# - echo "$SSH_PRIVATE_KEY_DEV"
- ssh-add <(echo "$SSH_PRIVATE_KEY_DEV")
# For Docker builds disable host key checking. Be aware that by adding that
# you are suspectible to man-in-the-middle attacks.
# WARNING: Use this only with the Docker executor, if you use it with shell
# you will overwrite your user's SSH config.
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
build_job:
stage: build
only:
- master
script:
- dotnet restore
- dotnet build
deploy_dev_job:
stage: deploy_dev
environment:
name: development
only:
- master
script:
# 发布程序并部署运行
- dotnet publish -c Release --output bin/publish
- scp -r bin/publish root@$DEPLOY_SERVER_DEV:/home/xishuai/wwwroot/hwapp
- ssh root@$DEPLOY_SERVER_DEV "supervisorctl restart hwapp && curl http://localhost:8088/api/values"
</code></pre>
<p>上面是我最终调试成功后的<code>.gitlab-ci.yml</code>文件配置,其实整个的构建和发布流程,从上面的配置中都可以看出。</p>
<p>这里记录下一些东西:</p>
<p>配置一开始的<code>image</code>,设置的是我们用于构建的镜像(也就是说后面所有的脚本执行,都是在基于这个镜像创建的容器中),如果不设置的话,默认使用的是我们一开始配置 GitLab CI 填写的 Docker Image,也可以手动编辑<code>vim /srv/gitlab-runner/config/config.toml</code>进行修改,我这里使用的是<code>microsoft/aspnetcore-build</code>镜像,只用于 ASP.NET Core 应用程序的编译和构建。</p>
<p><code>stage</code>可以理解为台阶,每走一步相当于<code>job</code>,当然,这里的台阶可以走很多步,需要注意的是,每上一个台阶或者每走一步,都必须基于上一个台阶或上一步执行成功,<code>before_script</code>执行在这些步骤之前,可以理解为准备工作。</p>
<p><code>environment</code>将执行的<code>job</code>归纳为哪一种执行环境,你可以设置开发环境和正式环境,我们可以通过通过后台进行查看:</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172757577-1215640944.png" alt="" loading="lazy"></p>
<h2 id="3-gitlab-ci-服务器使用-ssh-连接到测试服务器">3. GitLab CI 服务器使用 SSH 连接到测试服务器</h2>
<p>什么意思呢?就是我们需要在 GitLab CI 构建环境中,使用 SSH 连接到测试服务器,这样我们才可以做接下来的一些操作。</p>
<p>官方配置:SSH keys when using the Docker executor </p>
<p><code>.gitlab-ci.yml</code>示例配置:</p>
<pre><code class="language-yml">before_script:
# Install ssh-agent if not already installed, it is required by Docker.
# (change apt-get to yum if you use a CentOS-based image)
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# Run ssh-agent (inside the build environment)
- eval $(ssh-agent -s)
# Add the SSH key stored in SSH_PRIVATE_KEY_DEV variable to the agent store
- ssh-add <(echo "$SSH_PRIVATE_KEY_DEV")
# For Docker builds disable host key checking. Be aware that by adding that
# you are suspectible to man-in-the-middle attacks.
# WARNING: Use this only with the Docker executor, if you use it with shell
# you will overwrite your user's SSH config.
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
# In order to properly check the server's host key, assuming you created the
# SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines
# instead.
# - mkdir -p ~/.ssh
# - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'
</code></pre>
<p>在进行配置之前,我们需要理一下这个步骤,要不然思路容易混乱,会造成一些问题,可以参考这篇文章:Fixing 'Enter passphrase for /dev/fd/63' in a Gitlab CI job</p>
<p>需要强调一点:别在 GitLab CI 容器中进行 SSH 配置,因为 CI 构建脚本执行在另外的容器中,并且这个容器是动态进行创建的,也没办法在这个动态容器中进行配置(指的是手动生成 RSA 密钥)。</p>
<p>所以,我们只能手动生成 RSA 密钥,然后强制添加到容器中的 SSH 配置中(通过 RSA 密钥内容)。</p>
<p>配置步骤:</p>
<p>首先,在任何一台服务器上,创建 RSA 无密码的密钥:</p>
<pre><code>$ ssh-keygen -t rsa -P ''
$ cat /root/.ssh/id_rsa
</code></pre>
<p>然后复制 RSA 密钥内容,添加到<code>/Project/Settings/Pipelines</code>的<code>Secret variables</code>配置中(命名为<code>SSH_PRIVATE_KEY_DEV</code>):</p>
<img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172823671-1736641179.png" style="width: 900px">
<p>这里需要<strong>特别注意</strong>,复制内容为(包含开头和结尾的注释信息):</p>
<pre><code>-----BEGIN RSA PRIVATE KEY-----
xxxxxxx
-----END RSA PRIVATE KEY-----
</code></pre>
<p>我一开始复制没有包含注释信息,然后就一直报下面的错误:</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172848249-350300683.png" alt="" loading="lazy"></p>
<p>错误代码:</p>
<pre><code class="language-bash">$ ssh-add <(echo "$SSH_PRIVATE_KEY_DEV")
Enter passphrase for /dev/fd/63: ERROR: Job failed: exit code 1
</code></pre>
<p>这里的<code>$SSH_PRIVATE_KEY_DEV</code>,就是上面我们在<code>Secret variables</code>中,添加的 RSA 密钥内容。</p>
<p>错误信息就是说需要输入 RSA 密钥的密码,但我创建的确实是无密码的 RSA 密钥,也就是说这个密钥是无效的,我被这个问题折磨了好几天😭,其他人的记录:</p>
<ul>
<li>"Enter passphrase for /dev/fd/63" error(有我的回复😏)</li>
<li>"Enter passphrase for /dev/fd/63" error</li>
<li>https://gitlab.com/gitlab-examples/ssh-private-key/-/jobs/376082(受这个兄弟的启发)</li>
</ul>
<p>配置好这一步之后,然后重新测试下,我们就可以看到下面的执行信息了:</p>
<pre><code class="language-bash">$ ssh-add <(echo "$SSH_PRIVATE_KEY_DEV")
Identity added: /dev/fd/63 (/dev/fd/63)
</code></pre>
<p>接着我们需要将这个 RSA 密钥对应的公钥,上传到<strong>需要连接到的服务器</strong>(也就是我们的测试服务器),命令如下:</p>
<pre><code class="language-bash">$ ssh-copy-id root@40.125.201.75
</code></pre>
<p>到此,GitLab CI 中 SSH 的配置基本上完成了,你可以在<code>.gitlab-ci.yml</code>中添加连接脚本,进行测试:</p>
<pre><code class="language-yml">- ssh root@$DEPLOY_SERVER_DEV "ls && cd /"
</code></pre>
<p>一开始,我们说到使用<code>scp</code>进行服务器之间的文件传输,因为<code>scp</code>可以基于 SSH 连接进行传输文件,所以我们直接进行文件传输了,示例代码:</p>
<pre><code class="language-yml">- scp -r bin/publish root@$DEPLOY_SERVER_DEV:/home/xishuai/wwwroot/hwapp
</code></pre>
<p><code>scp</code>命令参考:http://www.runoob.com/linux/linux-comm-scp.html</p>
<h2 id="4-使用-supervisor-进行站点程序的进程管理">4. 使用 Supervisor 进行站点程序的进程管理</h2>
<p>可以参考之前的文章:Ubuntu 安装和使用 Supervisor(进程管理)</p>
<p>这里贴一下,<code>supervisorctl</code>的常用命令:</p>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>supervisorctl stop program_name</td>
<td>停止某个进程</td>
</tr>
<tr>
<td>supervisorctl start program_name</td>
<td>启动某个进程</td>
</tr>
<tr>
<td>supervisorctl restart program_name</td>
<td>重启某个进程</td>
</tr>
<tr>
<td>supervisorctl stop all</td>
<td>停止全部进程</td>
</tr>
<tr>
<td>supervisorctl reload</td>
<td>载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程</td>
</tr>
<tr>
<td>supervisorctl update</td>
<td>根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启</td>
</tr>
</tbody>
</table>
<h2 id="5-最终效果">5. 最终效果</h2>
<p>Pipelines 管道(地址:http://40.125.206.47/team/hwapp/pipelines)</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172901765-262319739.png" alt="" loading="lazy"></p>
<p>Build_Job 构建任务(地址:http://40.125.206.47/team/hwapp/-/jobs/113)</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172927405-20901709.png" alt="" loading="lazy"></p>
<p>Deploy_Dev_Job 发布和部署任务(地址:http://40.125.206.47/team/hwapp/-/jobs/115)</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201708/435188-20170831172939062-198096621.png" alt="" loading="lazy"></p>
<hr>
<p>写在最后:</p>
<ul>
<li><strong>GitLab CI & ASP.NET Core 2.0 发布和部署(完成)</strong>:使用 CI 脚本编译程序,然后将编译后的文件传输到服务器上,最后运行程序,完成发布和部署。</li>
<li><strong>GitLab CI & ASP.NET Core 2.0 & Docker 发布和部署(下篇)</strong>:项目中添加<code>Dockerfile</code>文件,使用 CI 脚本构建自定义镜像,然后在服务器上拉取并创建相应容器,最后启动容器,完成发布和部署。</li>
</ul>
</div>
<div id="MySignature" role="contentinfo">
<div id="xishuai_qianming2">
作者:田园里的蟋蟀
<br>微信公众号:<strong>你好架构</strong>
<br>出处:http://www.cnblogs.com/xishuai/
<br>
公众号会不定时的分享有关架构的方方面面,包含并不局限于:Microservices(微服务)、Service Mesh(服务网格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持续集成/持续部署)、DevOps等等。
<br>
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
</div>
<br>
<div class="jiathis_style">
<span class="jiathis_txt">分享到:</span>
QQ空间
新浪微博
腾讯微博
微信
更多
</div><br><br>
来源:https://www.cnblogs.com/xishuai/p/ubuntu-gitlab-ci-docker-aspnet-core-part-1.html
頁:
[1]