随着 DevOps 文化的普及,CI/CD(持续集成与持续交付)已经成为现代软件开发中的一部分。通过自动化代码的构建、测试和部署过程,CI/CD 不仅提高了软件质量,还大幅提高了开发效率。在本文中,我们将介绍如何利用 Docker、Jenkins、Harbor 和 GitLab 实现一个完整的 CI/CD 流水线。
1. 环境准备
在开始之前,确保以下软件已安装并运行:
- Docker:用于容器化应用。
- Jenkins:用于自动化构建和部署。
- Harbor:用于管理 Docker 镜像。
- GitLab:用于版本控制与源代码管理。
可以参考官方文档安装这些工具:
2. 搭建 GitLab 代码仓库
首先,在 GitLab 上创建一个代码仓库。如果你已经有一个仓库,可以直接使用。
- 登录 GitLab,创建一个新的项目。
- 将你的代码推送到 GitLab 仓库:
git init git remote add origin https://gitlab.com/your-username/your-repo.git git add . git commit -m "Initial commit" git push -u origin master
使用docker Registry代替了harbor
CI/CD


- Git 代码版本管理系统 只能命令行去管理git
- Gitlab 基于git做了图形管理页面,企业使用gitlab做私有的代码管理仓库
- Github 公共代码管理仓库
设计流程
- 使用 Gitlab 作为代码仓库
- 使用 Harbor 作为镜像仓库
- 使用Jenkins发布系统部署
- Docker管理Jenkins+Harbor+Gitlab
工作流程
- 迁入代码push到Gitlab
- Gitlab触发webhook的push触发事件并主动通知Jenkins构建
- Jenkins在Gitlab获取源码并通过配置好的规则与shell脚本进行构建
-
- 如果是工具库,则dotnet push到私有Nuget
- 如果是Web应用,则通过dockerfile构建docker镜像并push到Docker Registry,然后由docker swarm create多节点
安装Docker
设置端口
bash
vim /usr/lib/systemd/system/docker.service
添加以下内容
perl
ExecStart=/usr/bin/dockerd -H fd:// -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --containerd=/run/containerd/containerd.sock
systemctl daemon-reload
service docker restart
安装 Docker Registry
安装Registry
安装Registry,作私有仓库
ini
docker run -d -p 6000:5000 --restart=always --name registry registry
以下命令执行有问题
bash
docker run -d -p 6000:5000 --restart=always --name registry registry --volume /root/registry:/var/lib/registry
配置修改
编辑所有需要docker registry使用的节点的daemon.json文件,确保能正常访问
bash
vim /etc/docker/daemon.json
json
{
"insecure-registries":[
"192.168.234.133:6000",
"192.168.234.133:7080"
]
}
ini
systemctl daemon-reload;
service docker restart;
如果需要推送镜像到私库确保标签(tag)前缀带有私库地址
bash
docker push 192.168.234.133:6000/testdockerswarm
使用和停止其他容器相同的docker container stop命令来停止你的registry
arduino
docker container stop registry
使用docker container rm 命令来移除此container
arduino
docker container stop registry && docker container rm -v registry
docker swarm初始化(可选)
把相关涉及到docker swarm的节点端口开启
css
firewall-cmd --permanent --zone=public --add-port=2377/tcp
firewall-cmd --permanent --zone=public --add-port=4789/udp
firewall-cmd --permanent --zone=public --add-port=7946/udp
firewall-cmd --reload
选取Server作为Manager节点,执行下面的指令后会出现docker swarm join的指令文本,复制保存下来
csharp
docker swarm init --advertise-addr 192.168.234.133
Server A和Server C为Worker节点,执行刚刚保存下来指令

sql
docker swarm join --token SWMTKN-1-0nggzpa2t3ye69rq0jhr4eid2criq40ij483s89rd7btl2lq0e-1gslrqufyv0s02lg5sw5dr9es 192.168.234.133:2377
bash
docker node ls
安装Jenkins

安装Harbor
安装GitLab
需要到jenkins配置以下信息

安装Git
yum -y install git
bash
which git
然后找到Jenkins下的系统管理-全局工具配置-Git,将上面复制的git的路径放在Path to Git executable中
安装Nuget
Nuget安装
基于docker的Nuget安装
bash
docker run -d \
-p 9082:80 -p 9443:443 --restart=always\
--env NUGET_API_KEY=chengong \
-v /root/nuget/database:/var/www/db \
-v /root/nuget/packages:/var/www/packagefiles \
--name nuget-server \
sunside/simple-nuget-server
修改host
nslookup nuget.org 8.8.8.8
yaml
[root@k8s-node3 ~]# nslookup nuget.org 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: nuget.org
Address: 52.237.135.91
nslookup api.nuget.org 8.8.8.8
bash
vim /etc/hosts
52.237.135.91 nuget.org
配置端口
css
firewall-cmd --permanent --add-port=9082/tcp
firewall-cmd --permanent --add-port=9443/tcp
firewall-cmd --reload
相关指令
上传包指令,注意包名有中文会导致上传出现bad request
perl
dotnet nuget push --source http://192.168.234.133:9082/ -k chengong TestPackage.1.0.0.nupkg
删除包指令
arduino
dotnet nuget delete --source http://192.168.234.133:9082/ -k chengong TestPackage 1.0.0
如果在Windowsx系统可以通过工具上传
arduino
https://github.com/NuGetPackageExplorer/NuGetPackageExplorer
添加私有包源
在Server添加私有Nuget包源,因为在.Net Core应用 Build和Publish的时候会触发Restore指令(还原包),默认只有微软的nuget源,如果缺少了私有Nuget源会还原包失败
csharp
dotnet nuget add source http://192.168.234.133:8082 -n LocalNugetServer
NuGet微软中国
为解决国内访问NuGet服务器速度不稳定的问题 ,这里推荐使用NuGet微软官方中国国内镜像
地址:nuget.cdn.azure.cn/v3/index.js...
linux添加NuGet源的方式
bash
dotnet nuget add source https://nuget.cdn.azure.cn/v3/index.json -n nuget.org.cn
Visual Studio添加NuGet源的方式,菜单: 工具 -> NuGet包管理器 -> 程序包管理器设置
列出已有包源
bash
dotnet nuget list source

可以通过 dotnet restore -s http://192.168.234.133:8082 指令指定还原包源,但是为了避免如果服务地址变动后shell脚本会大面积的修改,还是建议通过dotnet nuget add soure指令。
查找配置文件
arduino
find / -name NuGet.Config*

编辑配置
- linux
- /root/.config/NuGet
- /root/.nuget/NuGet/NuGet.Config
- /var/lib/docker/overlay2/d494d4262b85da17df3c92a072f0050ace37a2a2bf243f53531f30cdd8a4b946/diff/root/.nuget/NuGet/NuGet.Config
javascript
vim ~/.nuget/NuGet/NuGet.Config
/root/.nuget/NuGet/NuGet.Config配置文件内容调整为
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="huaweicloud.com" value="https://repo.huaweicloud.com/repository/nuget/v3/index.json" />
<add key="azure.cn" value="https://nuget.cdn.azure.cn/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources>
<add key="azure.cn" value="true" />
<add key="nuget.org" value="true" />
</disabledPackageSources>
</configuration>
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="azure.cn" value="https://nuget.cdn.azure.cn/v3/index.json" />
<add key="huaweicloud.com" value="https://repo.huaweicloud.com/repository/nuget/v3/index.json" />
<add key="disabledSources1" value="https://api.nuget.org/v3-index/repository-signatures/5.0.0/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources>
<add key="disabledSources1" value="true" />
<add key="nuget.org" value="true" />
</disabledPackageSources>
</configuration>
将/var/lib/docker/overlay2/d494d4262b85da17df3c92a072f0050ace37a2a2bf243f53531f30cdd8a4b946/diff/root/.nuget/NuGet/NuGet.Config配置文件内容调整为
bash
vim /var/lib/docker/overlay2/d494d4262b85da17df3c92a072f0050ace37a2a2bf243f53531f30cdd8a4b946/diff/root/.nuget/NuGet/NuGet.Config
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="azure.cn" value="https://nuget.cdn.azure.cn/v3/index.json" />
<add key="huaweicloud.com" value="https://repo.huaweicloud.com/repository/nuget/v3/index.json" />
<add key="disabledSources1" value="https://api.nuget.org/v3-index/repository-signatures/5.0.0/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources>
<add key="disabledSources1" value="true" />
<add key="nuget.org" value="true" />
</disabledPackageSources>
</configuration>
- win 10
makefile
C:\Users\Administrator\AppData\Roaming\NuGet
将配置文件内容调整为
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://nuget.cdn.azure.cn/v3/index.json" protocolVersion="3" />
<add key="Package source" value="D:\Nuget\Package" />
<add key="Microsoft Visual Studio Offline Packages" value="D:\Nuget\NuGetPackages" />
</packageSources>
<disabledPackageSources>
<add key="Microsoft and .NET" value="true" />
</disabledPackageSources>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<bindingRedirects>
<add key="skip" value="False" />
</bindingRedirects>
<packageManagement>
<add key="format" value="0" />
<add key="disabled" value="False" />
</packageManagement>
</configuration>
如果不配置NuGet.Config,在使用docker file时,会出现以下错误信息
bash
Started by GitLab push by longfuchu
Running as SYSTEM
Building in workspace /var/jenkins_home/workspace/webapp1
The recommended git tool is: NONE
using credential 2
> git rev-parse --resolve-git-dir /var/jenkins_home/workspace/webapp1/.git # timeout=10
Fetching changes from the remote Git repository
> git config remote.webapp1.url http://192.168.234.133:7080/net/webapp1.git # timeout=10
Fetching upstream changes from http://192.168.234.133:7080/net/webapp1.git
> git --version # timeout=10
> git --version # 'git version 2.30.2'
using GIT_ASKPASS to set credentials gitlab
> git fetch --tags --force --progress -- http://192.168.234.133:7080/net/webapp1.git +refs/heads/*:refs/remotes/webapp1/* # timeout=10
skipping resolution of commit remotes/webapp1/main, since it originates from another repository
Seen branch in repository webapp1/main
Seen 1 remote branch
> git show-ref --tags -d # timeout=10
Checking out Revision bc0e43d7c2a3146667d6b22dd7d357bd265141a0 (webapp1/main)
> git config core.sparsecheckout # timeout=10
> git checkout -f bc0e43d7c2a3146667d6b22dd7d357bd265141a0 # timeout=10
Commit message: "36"
> git rev-list --no-walk c92fa9ee9420a7f094bc53e588354997a7506832 # timeout=10
Docker Build
Docker Build: building image at path /var/jenkins_home/workspace/webapp1
Step 1/16 : FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
---> 56bc39541821
Step 2/16 : WORKDIR /app
---> Running in 7d827b313aba
Removing intermediate container 7d827b313aba
---> fadfb17d8c08
Step 3/16 : EXPOSE 80
---> Running in f0583aace3ad
Removing intermediate container f0583aace3ad
---> e608a0c27da9
Step 4/16 : FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
---> b847a4eb3c52
Step 5/16 : WORKDIR /src
---> Running in 7d7f4fcb044a
Removing intermediate container 7d7f4fcb044a
---> 07d3ca41aefc
Step 6/16 : COPY ["WebApp1.csproj", "."]
---> f46fd47e9c67
Step 7/16 : RUN dotnet restore "./WebApp1.csproj"
---> Running in d52acffd8a82
Determining projects to restore...
/src/WebApp1.csproj : error NU1301: Unable to load the service index for source https://api.nuget.org/v3/index.json.
/src/WebApp1.csproj : error NU1301: Unable to load the service index for source https://api.nuget.org/v3/index.json.
Failed to restore /src/WebApp1.csproj (in 11.34 sec).
ERROR: Build step failed with exception
com.github.dockerjava.api.exception.DockerClientException: Could not build image: The command '/bin/sh -c dotnet restore "./WebApp1.csproj"' returned a non-zero code: 1
at com.github.dockerjava.core.command.BuildImageResultCallback.getImageId(BuildImageResultCallback.java:80)
at com.github.dockerjava.core.command.BuildImageResultCallback.awaitImageId(BuildImageResultCallback.java:52)
at com.nirima.jenkins.plugins.docker.builder.DockerBuilderPublisher$Run.buildImage(DockerBuilderPublisher.java:404)
at com.nirima.jenkins.plugins.docker.builder.DockerBuilderPublisher$Run.run(DockerBuilderPublisher.java:344)
at com.nirima.jenkins.plugins.docker.builder.DockerBuilderPublisher.perform(DockerBuilderPublisher.java:486)
at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:123)
at hudson.tasks.BuildStepCompatibilityLayer.perform(BuildStepCompatibilityLayer.java:80)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:816)
at hudson.model.Build$BuildExecution.build(Build.java:199)
at hudson.model.Build$BuildExecution.doRun(Build.java:164)
at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:524)
at hudson.model.Run.execute(Run.java:1899)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:44)
at hudson.model.ResourceController.execute(ResourceController.java:107)
at hudson.model.Executor.run(Executor.java:449)
Build step 'Build / Publish Docker Image' marked build as failure
Finished: FAILURE
清空缓存
python
dotnet nuget locals http-cache --clear;
dotnet nuget locals global-packages --clear;
dotnet nuget locals temp --clear;
dotnet nuget locals plugins-cache --clear;
dotnet nuget locals all --clear;
安装.Net SDK
因为在Server安装了Jenkins,因此会基于Server的环境进行.Net的应用进行打包、发布。
NET 也可通过packages.microsoft.com获得。
检查环境
css
dotnet --list-sdks
css
dotnet --list-runtimes
在线安装
bash
rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
sudo yum install dotnet-sdk-3.1
sudo yum install dotnet-sdk-5.0
sudo yum install dotnet-sdk-6.0
离线安装
1.下载Microsoft 包签名密钥,上传服务器后添加到受信任密钥列表,并添加 Microsoft 包存储库
下载地址:Microsoft 包签名密钥
执行安装:
bash
sudo rpm -Uvh /tmp/packages-microsoft-prod.rpm
2.微软SDK下载页下载SDK二进制包
下载地址:.NET 下载(Linux、macOS 和 Windows) (microsoft.com)
3.上传服务器并进行安装(本文假定上传至根目录tmp文件夹)
bash
cd /tmp
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-6.0.301-linux-x64.tar.gz -C $HOME/dotnet && tar zxvf dotnet-sdk-3.1.420-linux-x64.tar.gz -C $HOME/dotnet
export DOTNET_ROOT=$HOME/dotnet
export PATH=$PATH:$HOME/dotnet
source /etc/profile
注意,如果手动安装 .NET Core 或发布自包含的应用,则需要确保已安装以下库:
- krb5-libs
- libicu
- openssl-libs
- zlib
如果目标运行时环境的 OpenSSL 版本为1.1 或更高版本,则需要安装 compat-openssl10。
对于使用 System.Drawing.Common 程序集的 .NET Core 应用,还需要以下依赖项:
配置环境变量
css
dotnet --info

bash
sudo vim /etc/profile
ruby
export PATH=$PATH:/usr/share/dotnet/
export DOTNET_ROOT=/usr/share/dotnet/
注:/data/dotnet是我的存储路径,这里改成你自己的路径
端口映射
ini
# 查看防火墙状态
systemctl status firewalld
# 启动防火墙
systemctl start firewalld
# docker swarm的节点端口开启
firewall-cmd --zone=public --add-port=2376/tcp --permanent
firewall-cmd --zone=public --add-port=2377/tcp --permanent
firewall-cmd --zone=public --add-port=4789/udp --permanent
firewall-cmd --zone=public --add-port=7946/udp --permanent
# 开启6000端口
firewall-cmd --zone=public --add-port=6000/tcp --permanent
# 开启8022端口
firewall-cmd --zone=public --add-port=8022/tcp --permanent
# 开启8443端口
firewall-cmd --zone=public --add-port=8443/tcp --permanent
# 开启8060端口
firewall-cmd --zone=public --add-port=8060/tcp --permanent
# 开启8081端口
firewall-cmd --zone=public --add-port=8081/tcp --permanent
# 开启8082端口
firewall-cmd --zone=public --add-port=8082/tcp --permanent
# 开启8090端口
firewall-cmd --zone=public --add-port=8090/tcp --permanent
# 开启48080端口
firewall-cmd --zone=public --add-port=48080/tcp --permanent
# 重启防火墙才能生效
systemctl restart firewalld
# 或者重新启动防火墙
firewall-cmd --reload
# 查看已经开放的端口
firewall-cmd --list-ports
# 关闭防火墙命令:
systemctl stop firewalld
yaml
# 查看防火墙状态
sudo ufw status
# 安装防火墙
sudo sudo apt-get install ufw
# 启动防火墙
sudo ufw enable
# 开启6000端口
sudo ufw allow 6000
# 开启8022端口
sudo ufw allow 8022
# 开启8443端口
sudo ufw allow 8443
# 开启48080端口
sudo ufw allow 48080
# 开启完成,需要重启防火墙生效
sudo ufw reload
# 查看端口信息
sudo ufw status
# 关闭防火墙命令:
sudo ufw disable
Jenkins配置
API Token

插件管理
管理Jenkins->系统配置-->插件管理-->

分别搜索Git Parameter/Git/Pipeline/docker/Config File Provider/Gitlab Hook /Gitlab/Push Over SSH,选中点击安装。

- Git:拉取代码
- Git Parameter:Git参数化构建
- Pipeline:流水线
- GitLab:
- Config File Provider:存储配置文件
- Extended Choice Parameter:扩展选择框参数,支持多选
- Docker-build-stepVersion
- CloudBees Docker Build and Publish plugin: docker插件
如果无法顺利安装则到plugins.jenkins.io/下载插件手动上传。
修改时区
bash
docker exec -it 81 /bin/bash
执行下面命令
bash
tzselect
4
9
1
1
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
##查看时间
date -R
gitlab插件配置
需要到jenkins配置以下信息
Connection name为gitlab的登录账号

docker插件配置
该配置提供给任务构建配置的"Build / Publish Docker Image"配置选择。
- 需要安装插件CloudBees Docker Build and Publish、docker-build-stepVersion
- 需要开启2376端口
- 需要修改docker.service
bash
vim /usr/lib/systemd/system/docker.service
添加以下内容
perl
ExecStart=/usr/bin/dockerd -H fd:// -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --containerd=/run/containerd/containerd.sock
systemctl daemon-reload
service docker restart
系统管理-->节点管理-->集群配置




生成 SSH Key
生成key
bash
cd /var/lib/jenkins
ssh-keygen -t rsa
输入文件名为jenkins_rsa,输入密码(为空)

会在目录/root/.ssh生成id_rsa私钥、id_rsa.pub公钥,将公钥的内容写入到同目录下的authorized_keys文件(jenkins连接多台服务器,将公钥写入到相应服务器的authorized_keys文件即可)
公钥文件
将公钥写入authorized_keys文件
bash
cd /root/.ssh/
bash
cat /var/lib/jenkins/jenkins_rsa.pub >> authorized_keys
bash
chmod 600 authorized_keys
验证SSH Key
css
ssh -p 8081 root@192.168.234.133
配置私钥凭证
在jenkins的linux虚拟机上执行如下命令查看私钥
bash
cd /var/lib/jenkins
bash
mv jenkins_rsa /root/.ssh/
bash
cat /root/.ssh/jenkins_rsa
登录jenkins配置凭据,系统管理-->


类型选择:SSH Username with private key
Username: 一般是linux虚拟机上配置的用户


将私钥 复制到key处,然后点击确定即可。
在jenkins系统配置中,配置SSH remote hosts,如果提示不能连接,请检查服务器sshd文件配置
配置SSH remote hosts
系统管理-->系统管理--下拉菜单选择"SSH remote hosts",


按以下截图配置,Credentials选择刚刚配置的jenkins ssh

如果提示不能连接,请检查服务器sshd文件配置。
配置Publish over SSH
在把SSH配置好后,点击系统管理-->系统管理--下拉菜单选择Publish over SSH;
在【SSH Servers】模块把服务器地址、账号密码填进去保存,因为后续会使用到。



点击新增Service按钮,输入Jenkins所在服务器的IP,及账号,远程目录

接着点击Test configuration测试下连接是否成功,如下:

如果测试配置不是Success,则按以下操作继续


在Passphrase / Password维护输入Jenkins所在服务器的UserName(root)用户名对应的密码,如下:

新建任务
到首页面板点击【新建任务】-选择【构建一个自由风格的软件项目】(FreeStyle Project)。
自由风格的项目更多是使用shell脚本结合相应平台的指令实现自动化,因此建议大家对shell脚本有个初步的认识与学习,虽然Jenkins也提供了对应平台语言的一些插件,但是只要您熟悉了shell就会发现它的灵活性与便捷性。

接下来我们只要关注3个模块,源码管理、构建触发器、构建
任务构建配置
新建完任务后,需要对该任务进行构建配置。
General
参数化构建过程配置,分别添加两个字符串参数ImageName,Version


源码构建
源码构建,填写您要自动发布的项目的源码地址,并输入账号密码。
Repository URL输入gitlab的项目访问地址,Credentials选择一个或新增一个gitlab的有效账号

无法连接仓库:Command "git ls-remote -h -- http://192.168.234.133:48080/net/WebApp1.git HEAD" returned status code 128:
stdout:
stderr: remote: HTTP Basic: Access denied
fatal: Authentication failed for 'http://192.168.234.133:48080/net/WebApp1.git/'


构建触发器
构建触发器,这里勾选Build when a chenge ......,把URL 复制记录下来,等下在Gitlab需要使用到。这里就是与Gitlab webhook做了联动,可以理解成Jenkins开放了一个接口,让Gitlab被push代码后会主动告诉Jenkins做一次自动化构建。

构建
这里其实就是执行shell脚本完成发布。这里得注意下我是用ssh,因为我的Jenkins是使用了docker安装的,如果我使用了【构建】模块里的【执行shell】就会在Jenkins环境里进行编译、打包,同时也需要安装相应的环境 例如dotnet sdk等。值得注意的是,我的环境与Jenkins挂载的都是在了Server这个宿主环境,因此通过Jenkins的SSH Publishers连到Jenkins的宿主服务器(Server),执行相应的shell脚本从Jenkins挂载的目录进行构建镜像。当然有同学想在Jenkins环境先打包然后通过SSH的Transfers模块进行文件传也是可以的。
Send files or execute commands over SSH

构建步骤选择"Send files or execute commands over SSH"


bash
# 工作空间目录
mkdir -p /root/jenkins/jenkins_home/workspace/webapp1
# 执行脚本目录
mkdir -p /root/jenkins/jenkins_home/workspace/build/webapp1
bash
#!/bin/bash
echo '清除原webapp1容器执行开始'
docker stop webapp1
docker rmi webapp1
echo '清除原webapp1容器执行结束'
echo '脚本开始执行'
base_path=/root/jenkins/jenkins_home/workspace/webapp1
project_name=webapp1
project_path=$base_path/webapp1
publish_path=$project_path/bin/Release/netcoreapp6.0/publish
cd $project_path
rm -rf $project_path/bin
dotnet publish -c Release && (
cd $publish_path &&
docker stop $project_name
docker rm $project_name
docker image rm $project_name
docker build -t $project_name . &&
docker run -d -p 5000:80 -e ASPNETCORE_ENVIRONMENT="Development" --name $project_name $project_name &&
echo '发布成功:'$project_path'' ||
echo '发布失败:'$project_path''
) || echo '发布失败:'$project_path''
echo '脚本执行结束'
将build.sh保存到/root/jenkins/jenkins_home/workspace/build/WebApp1目录下。
Remote directory输入/,Exec command输入以下内容
bash
sh /root/jenkins/jenkins_home/workspace/build/webapp1/build.sh
Build / Publish Docker Image
Directory for Dockerfile:./
Cloud:选择自己在jenkins配置的docker
Image: <math xmlns="http://www.w3.org/1998/Math/MathML"> I m a g e N a m e : ImageName: </math>ImageName:Version
构建脚本(没用到那)
Nuget脚本
这个是工具库发布到私有Nuget的脚本
bash
#脚本开始执行
echo '脚本开始执行'
base_path=/root/jenkins/jenkins_home/workspace/TestNuget
nuget_url=http://192.168.234.133:8081/
nuget_api_key=chengong
project_path=$base_path/TestNuget
package_path=$project_path/bin/Debug
cd $project_path
rm -rf $package_path/*.nupkg
dotnet pack $project_path &&
dotnet nuget push --source $nuget_url -k $nuget_api_key $package_path/*.nupkg >/dev/null
if [ $? -eq 0 ]; then
echo '发布成功:'$project_path''
else
echo '发布失败:'$project_path''
fi
echo '脚本执行结束'
Web应用
下面这个是Web应用发布到单台服务器的脚本
bash
#!/bin/bash
echo '清除原webapp1容器执行开始'
docker stop webapp1
docker rmi webapp1
echo '清除原webapp1容器执行结束'
echo '脚本开始执行'
base_path=/root/jenkins/jenkins_home/workspace/webapp1
project_name=webapp1
project_path=$base_path/webapp1
publish_path=$project_path/bin/Release/netcoreapp6.0/publish
cd $project_path
rm -rf $project_path/bin
dotnet publish -c Release && (
cd $publish_path &&
docker stop $project_name
docker rm $project_name
docker image rm $project_name
docker build -t $project_name . &&
docker run -d -p 5000:80 -e ASPNETCORE_ENVIRONMENT="Development" --name $project_name $project_name &&
echo '发布成功:'$project_path'' ||
echo '发布失败:'$project_path''
) || echo '发布失败:'$project_path''
echo '脚本执行结束'
下面这个是通过Docker Swarm把Web应用发布到多台服务器
bash
#!/bin/bash
echo '脚本开始执行'
base_path=/root/jenkins/jenkins_home/workspace/webapp1
project_name=webapp1
project_path=$base_path/webapp1
publish_path=$project_path/bin/Release/netcoreapp6.0/publish
private_registry_url=192.168.234.133:6000
version=`date "+%Y%m%d%H%M%S"`
cd $project_path
rm -rf $project_path/bin
dotnet publish -c Release && (
(
cd $publish_path
docker service rm testdockerswarm
docker images | grep $private_registry_url/$project_name | awk '{print $3}' | xargs docker rmi
docker build -t $private_registry_url/$project_name:$version ./
docker push $private_registry_url/$project_name:$version
) &&
docker service create -d -p 5000:80 --replicas 2 -e ASPNETCORE_ENVIRONMENT="Development" --constraint=" node.role==worker" --name $project_name $private_registry_url/$project_name:$version &&
echo '发布成功:'$project_path'' ||
echo '发布失败:'$project_path''
) || echo '发布失败:'$project_path''
echo '脚本执行结束'
上面脚本有一处地址得注意下我指定了--constraint=" node.role==worker" 也就是woker节点才会部署应用,因为我定义了ServerA和C是Web服务器。当然各位可以按照自己的需要处理。
Dockerfile
bash
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
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 ["WebApp1.csproj", "."]
COPY ["nuget.config", "."]
RUN dotnet restore "./WebApp1.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "WebApp1.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebApp1.csproj" -c Release -o /app/publish
ENV TZ=Asia/Shanghai
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApp1.dll"]
nuget.config
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="huaweicloud.com" value="https://repo.huaweicloud.com/repository/nuget/v3/index.json" />
<add key="azure.cn" value="https://nuget.cdn.azure.cn/v3/index.json" />
</packageSources>
<disabledPackageSources>
<add key="huaweicloud.com" value="true" />
</disabledPackageSources>
</configuration>
gitlab配置
默认情况下gitlab不允许在本地调用,因此我们需要设置本地调用
创建项目
创建一个私有的WebApp1项目
参数配置
出站请求
设置-->网络-->出站请求
勾选----Allow requests to the local network from web hooks and services
并编辑触发webhook的本地服务器地址
以上设置解决webhook内部请求失败的问题
Webhooks
进入一个Project,点击【Setting】-【Webhooks】,把刚刚在Jenkins的复制下来的Url填写进去,勾选相应的触发事件后保存。
jenkins的配置url
分别输入jenkins 的url=http://192.168.234.133:8081/project/WebApp1及api token=110fbb87488254464129c23fe4c73d0d42
设置成功后使用test选择触发事件进行测试
如果测试报http 403:
-
安装插件:gitlab/gitlab hook/Build Authorization Token Root Plugin
-
系统管理-->configure global security -->去掉勾选 防止跨站点请求伪造(可能)
-
系统管理-->系统设置-->去掉 Enable authentication for '/project' end-point
-
打开jenkins,选择系统管理-系统配置,找到Gitlab选项,取消gitlab认证
推送代码
在另外一台机器上安装git,将项目的源码包上传
以上就是本篇的内容了,完成了部署后,可以在Jenkins点击【立刻构建】和在Gitlab迁入一次代码查看运行效果。
配置 Jenkins 构建流程
-
在 Jenkins 中创建一个新的 Pipeline 作业。
-
在 Pipeline Script 部分,配置流水线脚本,内容如下`pipeline { agent any
environment { REGISTRY = "harbor.example.com/your-project" IMAGE_NAME = "your-image-name" GITLAB_CI_TOKEN = credentials('gitlab-ci-token') // 用于从 GitLab 拉取代码 }
stages { stage('Checkout') { steps { git 'gitlab.com/your-userna...' } }
javascriptstage('Build Docker Image') { steps { script { docker.build("${REGISTRY}/${IMAGE_NAME}:${BUILD_ID}") } } } stage('Push Docker Image') { steps { script { docker.withRegistry('https://harbor.example.com', 'harbor-credentials') { docker.image("${REGISTRY}/${IMAGE_NAME}:${BUILD_ID}").push() } } } } stage('Deploy to Production') { steps { // 此处填写部署命令,取决于你的生产环境配置 sh 'docker-compose up -d' } }
} } `
配置 GitLab CI/CD 集成
- 在 GitLab 项目中创建一个
.gitlab-ci.yml
文件,配置 GitLab CI/CD 管道: `stages:
- build
- deploy
variables: REGISTRY: "harbor.example.com/your-project" IMAGE_NAME: "your-image-name"
build: stage: build script: - docker build -t <math xmlns="http://www.w3.org/1998/Math/MathML"> R E G I S T R Y / REGISTRY/ </math>REGISTRY/IMAGE_NAME: <math xmlns="http://www.w3.org/1998/Math/MathML"> C I C O M M I T R E F N A M E . − d o c k e r l o g i n − u CI_COMMIT_REF_NAME . - docker login -u </math>CICOMMITREFNAME.−dockerlogin−uCI_REGISTRY_USER -p <math xmlns="http://www.w3.org/1998/Math/MathML"> C I R E G I S T R Y P A S S W O R D h a r b o r . e x a m p l e . c o m − d o c k e r p u s h CI_REGISTRY_PASSWORD harbor.example.com - docker push </math>CIREGISTRYPASSWORDharbor.example.com−dockerpushREGISTRY/ <math xmlns="http://www.w3.org/1998/Math/MathML"> I M A G E N A M E : IMAGE_NAME: </math>IMAGENAME:CI_COMMIT_REF_NAME
deploy: stage: deploy script: - docker-compose up -d `
8. 流水线工作流
- 每次代码推送到 GitLab 时,GitLab 会触发 CI/CD 流程。
- Jenkins 会拉取最新代码,构建 Docker 镜像,并推送到 Harbor。
- 一旦镜像推送成功,Jenkins 会自动部署到生产环境。
9. 总结
通过结合 Docker、Jenkins、Harbor 和 GitLab,可以实现一个高效、自动化的 CI/CD 流水线。这种流水线不仅简化了应用的构建和部署过程,还提高了代码的质量和开发效率。随着团队规模的扩大和需求的增加,你还可以根据项目需求扩展和调整流水线配置。