使用 Docker、Jenkins、Harbor 和 GitLab 构建 CI/CD 流水线

随着 DevOps 文化的普及,CI/CD(持续集成与持续交付)已经成为现代软件开发中的一部分。通过自动化代码的构建、测试和部署过程,CI/CD 不仅提高了软件质量,还大幅提高了开发效率。在本文中,我们将介绍如何利用 Docker、Jenkins、Harbor 和 GitLab 实现一个完整的 CI/CD 流水线。

1. 环境准备

在开始之前,确保以下软件已安装并运行:

  • Docker:用于容器化应用。
  • Jenkins:用于自动化构建和部署。
  • Harbor:用于管理 Docker 镜像。
  • GitLab:用于版本控制与源代码管理。

可以参考官方文档安装这些工具:

2. 搭建 GitLab 代码仓库

首先,在 GitLab 上创建一个代码仓库。如果你已经有一个仓库,可以直接使用。

  1. 登录 GitLab,创建一个新的项目。
  2. 将你的代码推送到 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

工作流程

  1. 迁入代码push到Gitlab
  2. Gitlab触发webhook的push触发事件并主动通知Jenkins构建
  3. Jenkins在Gitlab获取源码并通过配置好的规则与shell脚本进行构建
    • 如果是工具库,则dotnet push到私有Nuget
    • 如果是Web应用,则通过dockerfile构建docker镜像并push到Docker Registry,然后由docker swarm create多节点

安装Docker

请参考安装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

请参考Docker部署Jenkins

安装Harbor

请参考Docker部署harbor

安装GitLab

请参考Docker部署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

创建build.sh

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 构建流程

  1. 在 Jenkins 中创建一个新的 Pipeline 作业。

  2. 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...' } }

    javascript 复制代码
    stage('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 集成

  1. 在 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. 流水线工作流

  1. 每次代码推送到 GitLab 时,GitLab 会触发 CI/CD 流程。
  2. Jenkins 会拉取最新代码,构建 Docker 镜像,并推送到 Harbor。
  3. 一旦镜像推送成功,Jenkins 会自动部署到生产环境。

9. 总结

通过结合 Docker、Jenkins、Harbor 和 GitLab,可以实现一个高效、自动化的 CI/CD 流水线。这种流水线不仅简化了应用的构建和部署过程,还提高了代码的质量和开发效率。随着团队规模的扩大和需求的增加,你还可以根据项目需求扩展和调整流水线配置。

相关推荐
bobz9658 分钟前
ovs 桥接了 bond0.1234, 链路层功能还在,但 IP 层功能无法使用
后端
穷儒公羊8 分钟前
第二章 设计模式故事会之策略模式:魔王城里的勇者传说
python·程序人生·设计模式·面试·跳槽·策略模式·设计规范
似水流年流不尽思念17 分钟前
Spring Bean有哪些生命周期回调方法?有哪几种实现方式?
后端·spring·面试
Moonbit24 分钟前
提交即有奖!MGPIC 游戏赛道官方推荐框架上线,直播同步解读赛题。 MoonBit MoonBit
后端·微信·程序员
郝同学的测开笔记24 分钟前
打通回家之路:OpenVPN,你的企业网络万能钥匙(一)
运维·后端·测试
whitepure24 分钟前
万字详解Java代码块
java·后端
云心雨禅1 小时前
VPS一键测试脚本NodeQuality,无痕体验+自动导出,服务器测试更轻松
运维·服务器·github
SimonKing1 小时前
Spring Boot Admin:一站式监控微服务,这个运维神器真香!
java·后端·程序员
uhakadotcom1 小时前
如何安装和使用开源的Meilisearch
后端·面试·github
高松燈1 小时前
自动拆箱 导致的空指针问题复盘
后端