使用 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 流水线。这种流水线不仅简化了应用的构建和部署过程,还提高了代码的质量和开发效率。随着团队规模的扩大和需求的增加,你还可以根据项目需求扩展和调整流水线配置。

相关推荐
聪明的笨猪猪22 分钟前
Java “并发工具类”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
whltaoin31 分钟前
Spring Boot 常用注解分类整理(含用法示例)
java·spring boot·后端·注解·开发技巧
唐叔在学习38 分钟前
【Git神技】三步搞定指定分支克隆,团队协作效率翻倍!
git·后端
咸菜一世43 分钟前
Scala的while语句循环
后端
嚴寒1 小时前
Halo 博客系统部署配置
后端
不会算法的小灰1 小时前
Spring Boot 实现邮件发送功能:整合 JavaMailSender 与 FreeMarker 模板
java·spring boot·后端
数据知道2 小时前
Go基础:json文件处理详解(标准库`encoding/json`)
开发语言·后端·golang·json·go语言
IT_陈寒2 小时前
Vite 5.0 性能优化实战:3 个关键配置让你的构建速度提升50%
前端·人工智能·后端
小咕聊编程2 小时前
【含文档+PPT+源码】基于SpringBoot+Vue的停车场管理系统
vue.js·spring boot·后端·毕业设计·停车场
草梅友仁3 小时前
草梅 Auth 1.9.0 发布验证码组件 | 2025 年第 40 周草梅周报
开源·github·ai编程