Jenkins+Docker 部署方案
开始新的方案前,先复习一下上面的内容建议用云处理器学习,重装什么都简单,按小时购买成本也不高.




什么是CICD
CI / CD的采用改变了开发人员和测试人员如何发布软件。

最初是瀑布模型,后来是敏捷开发,现在是DevOps,这是现代开发人员构建出色的产品的技术路线。随着DevOps的兴起,出现了持续集成(Continuous Integration)、持续交付(Continuous Delivery)、持续部署(Continuous Deployment)的新方法。传统的软件开发和交付方法正在迅速变得过时。从历史上看,在敏捷时代,大多数公司会每月,每季度,每两年甚至每年发布部署/发布软件。然而,现在,在DevOps时代,每周,每天,甚至每天多次是常态。当SaaS正在占领世界时,尤其如此,您可以轻松地动态更新应用程序,而无需强迫客户下载新组件。很多时候,他们甚至都不会意识到正在发生变化。开发团队通过软件交付流水线(Pipeline)实现自动化,以缩短交付周期,大多数团队都有自动化流程来检查代码并部署到新环境。今天,我们将介绍什么是CI / CD / CD,以及现代软件公司如何使用工具将部署代码的流程自动化。持续集成的重点是将各个开发人员的工作集合到一个代码仓库中。通常,每天都要进行几次,主要目的是尽早发现集成错误,使团队更加紧密结合,更好地协作。持续交付的目的是最小化部署或释放过程中固有的摩擦。它的实现通常能够将构建部署的每个步骤自动化,以便任何时刻能够安全地完成代码发布(理想情况下)。持续部署是一种更高程度的自动化,无论何时对代码进行重大更改,都会自动进行构建/部署。这些阶段中的每一个都是交付管道的一部分 。在Humble和Farley的书《持续交付:可靠的软件版本中,通过构建,测试和部署自动化》,解释“对软件的每次更改,都会在发布过程中经历一个复杂的过程。该过程涉及构建软件,然后通过多个测试和部署阶段进行这些构建。反过来,这需要许多人之间的合作,也许需要几个团队之间的合作。部署管道对此过程进行建模,并且它在持续集成和发布管理工具中的实现,使您能够在从版本控制转移到各种测试和部署,以向用户发布时查看和控制每个更改的进度。”

软件交付流水线
持续集成(CI)
通过持续集成,开发人员能够频繁将其代码集成到公共代码仓库的主分支中。开开发人员能够在任何时候多次向仓库提交作品,而不是独立地开发每个功能模块并在开发周期结束时一一提交。这里的一个重要想法是让开发人员更快,更频繁地做到这一点,从而降低集成成本。实际情况中,开发人员在集成时经常会发现新代码和已有代码存在冲突。如果集成较早并更加频繁,那么冲突将更容易解决且执行成本更低。当然,还有一些权衡。此流程变更不提供任何额外的质量保证。实际上,许多组织发现这种集成变得更加昂贵,因为它们依赖于手动过程来确保新代码不会引入新的错误,并且不会破坏现有代码。为了减少集成任务期间的摩擦,持续集成依赖于测试套件和自动化测试执行。然而,要认识到自动化测试和持续测试是完全不同的这一点很重要,我们会在文章结尾处详细说明。CI 的目标是将集成简化成一个简单、易于重复的日常开发任务,这将有助于降低总体构建成本,并在周期的早期发现缺陷。要想有效地使用 CI 必须转变开发团队的习惯,要鼓励频繁迭代构建,并且在发现 bug 的早期积极解决。
持续交付(CD)
实际上是 CI 的扩展,其中软件交付流程进一步自动化,以便随时轻松地部署到生成环境中。CD 集中依赖于部署流水线,团队通过流水线自动化测试和部署过程。此流水线是一个自动化系统,可以针对构建执行一组渐进的测试套件。CD 具有高度的自动化,并且在一些云计算环境中也易于配置。在流水线的每个阶段,如果构建无法通过关键测试会向团队发出警报。否则,将继续进入下一个测试,并在连续通过测试后自动进入下一个阶段。流水线的最后一个部分会将构建部署到和生产环境等效的环境中。这是一个整体的过程,因为构建、部署和环境都是一起执行和测试的,它能让构建在实际的生产环境可部署和可验证。AWS上提供了现代CI / CD管道的可靠展示。亚马逊是云计算提供商之一,提供令人印象深刻的CI / CD 管道环境,并提供一个演练过程,您可以从其中选择众多开发资源,并将它们链接在一个易于配置且易于监控的管道中。
许多人认为持续交付的吸引力主要在于,它自动化了从提交代码到仓库,再到测试和发布产品过程的所有步骤。这是构建和测试过程细致的自动化,但是如何发布以及发布什么仍然是需要人工操作,持续部署可以改变这一点。
持续部署(CD)
持续部署扩展了持续交付,以便软件构建,在通过所有测试时自动部署。在这样的流程中,不需要人为决定何时及如何投入生产环境。CI/CD 系统的最后一步将在构建后的组件/包退出流水线时自动部署。此类自动部署可以配置为快速向客户分发组件、功能模块或修复补丁,并准确说明当前提供的内容。采用持续部署的组织可以将新功能快速传递给用户,得到用户对于新版本的快速反馈,并且可以迅速处理任何明显的缺陷。用户对无用或者误解需求的功能的快速反馈有助于团队规划投入,避免将精力集中于不容易产生回报的地方。随着 DevOps 的发展,新的用来实现 CI/CD 流水线的自动化工具也在不断涌现。这些工具通常能与各种开发工具配合,包括像 GitHub 这样的代码仓库和 Jira 这样的 bug 跟踪工具。此外,随着 SaaS 这种交付方式变得更受欢迎,许多工具都可以在现代开发人员运行应用程序的云环境中运行,例如 GCP 和 AWS。最受欢迎的自动化工具是 Jenkins(以前的 Hudson),这是一个由数百名贡献者和商业公司 Cloudbees 支持的开源项目。Cloudbees 甚至聘请了 Jenkins 的创始人,并提供了一些 Jenkins 培训项目和附加组件。除了开源项目之外,还有一些更现代化的商业产品例如 CircleCI,Codeship 和 Shippable。这些产品各有优缺点,我鼓励开发人员在开发流程中一一尝试它们,以了解它们在您的环境中的工作方式,以及它们如何与您的工具、云平台、容器系统等协作。
什么Jenkins
Jenkins 是一个可扩展的持续集成引擎。
创建自己的Jenkins容器
DockerHub
Jenkins容器安装
构建流水线
构建自动发布
Docker部署Vue 前端工程Jenkins 持续集成(CI)工具创建Jenkins 容器
创建Dockerfile
FROM jenkins/jenkins# 说明该镜像的制作者和联系方式MAINTAINER nine ninthmrj@vip.qq.com# Switch to root to install .NET Core SDKUSER root# Show distro information!RUN uname -a && cat /etc/*release# Based on instructiions at https://www.microsoft.com/net/download/linux-package-manager/debian9/sdk-current# Install dependency for .NET Core 3.1/5/6RUN apt-get updateRUN apt-get install -y curl libunwind8 gettext apt-transport-https# Based on instructions at https://www.microsoft.com/net/download/linux-package-manager/debian9/sdk-current# Install microsoft.qpgRUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpgRUN mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpgRUN sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/dotnetdev.list'# Install the .NET Core framework Choose one Because I need several versions here, I installed three SDKsRUN apt-get updateRUN apt-get install -y dotnet-sdk-3.1RUN apt-get install -y dotnet-sdk-5.0RUN apt-get install -y dotnet-sdk-6.0# Install the npmRUN apt-get install -y curl \&& curl -sL https://deb.nodesource.com/setup_14.x | bash - \&& apt-get install -y nodejs \&& curl -L https://www.npmjs.com/install.sh | sh# Install cnpmRUN npm install cnpm -g# Install yarnRUN npm install -g yarnRUN npm -vRUN cnpm -vRUN yarn --version# Switch back to the jenkins user.USER jenkins
构建镜像(build)
# 进入home目录(假设home目录为空)$ cd /home# 创建一个dockerfile文件,用于创建自己的Jenkins容器$ touch Dockerfile# 编辑文件,vi、vim熟练的或者linux数量的直接进行操作,# 本人不才,我用finalshell直接粘贴过去的,反正实现把上面的命令复制过去就行$ vi Dockerfile# 在jenkinsdockerfile目录下进行,确认是否在此目录,enter 创建容器# 不指定文件构建镜像,此时规定Dockerfile的名称一定是Dockerfile,其他名字无法构建容器,或者使用指定文件构建镜像$ docker build -t jenkinsdockerfile .# 指定文件构建镜像 -t 镜像名称 jamnine/jenkins -f 指定文件生成镜像$ docker build -t jamnine/jenkins -f /home/JenkinsDockerfile .----------漫长等待.....大概十五分钟吧,以下这段为实例示例----------[root@nine home]# docker build -t jenkinsdockerfile .Sending build context to Docker daemon 16.9kBStep 1/20 : FROM jenkins/jenkinslatest: Pulling from jenkins/jenkinse4d61adff207: Pull completeeacef06daf30: Pull completeca581b0141a3: Pull completed872c65909bb: Pull completebcce550e05a9: Pull complete3461f061a833: Pull complete3b6f8a58a68d: Pull complete6d47f55855ba: Pull completebaa80a92c8e4: Pull complete39889d888af7: Pull complete18b5e0e36b4c: Pull completea53e22d026ad: Pull completea281963da5b5: Pull complete2366689c95a7: Pull complete27cbe8a0f233: Pull completefffccee1c284: Pull completea6afec98241f: Pull completeDigest: sha256:a5215b81a7f6e111ed6625b342521145e24c232891615be29ce3a251a631feacStatus: Downloaded newer image for jenkins/jenkins:latest---> f7d565ddb272Step 2/20 : MAINTAINER nine ninthmrj@vip.qq.com---> [Warning] IPv4 forwarding is disabled. Networking will not work.---> Running in 47cecef5c92cRemoving intermediate container 47cecef5c92c---> 13dd258b38bcStep 3/20 : USER root..........后续省略..........----------容器创建---结束------------------------------
创建容器
# 查看创建好的镜像$ docker images-----------------------示例-----------------------------[root@nine]:# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEjamnine/jenkins latest 20fd31570796 2 hours ago 1.93GBjamnine/jenkins net-6.0 7bc780e637ba 3 hours ago 1.23GBjamnine/jenkins net-5.0 2111cd8eef2b 4 hours ago 1.13GBjamnine/jenkins net-core-3.1 1281c5c8b81c 5 hours ago 1.08GBjenkins/jenkins latest f7d565ddb272 7 days ago 460MBlaozhangisphi/jenkins_with_dnt-cnpm_by_docker latest 1cd6e938cd08 16 months ago 1.72GB-----------------------示例-----------------------------# 如果你是第一次使用build,当然只有一个容器,这里我是有6个容器jamnine/jenkins # 镜像名字,docker 上传(docker仓库)规范 jamnine/jenkins 前面为作者名/镜像名latest # 镜像标签,一个镜像可以有多个不同标签,相当于一个版本20fd31570796 # 镜像的缩略ID(ID唯一,但是缩略ID可能会重复,确定唯一性可以使用镜像名称:标签)2 hours ago # 创建于两小时前1.93GB # 大小1.93GB# 创建你的第一个容器$ docker run -u root -it -d -p 8099:8080 --name jenkinsnine \-e TZ=Asia/Shanghai \-v /etc/localtime:/etc/localtime \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-v /home/jenkinsnine/jenkins_home:/var/jenkins_home \jamnine/jenkins# 注解--------------------------------------------------------------------------------------------------------------------rm 命令选项,等价于在容器退出后,执行 $ docker rm -v ,测试可写,生产环境记住去掉-p 3000:8080 端口映射 容器端口3000映射到宿主机8080--name jenkins 容器名称-v /etc/localtime:/etc/localtime 挂载在宿主机,后面为具体挂载路径 冒号":"前面的目录是宿主机目录,后面的目录是容器内目录路径不能为相对路径,需要以/开头laozhangisphi/jenkins_with_dnt-cnpm_by_docker 最后一句代表了镜像名称,这里没有多个tag,直接写镜像名称即可,latest可省略,如果是要创建jamnine/jenkin 的容器,不写tag则创建latest镜像的容器,否则改写tag,如6.0则是 jamnine/jenkin:net-6.0-i 以交互模式运行容器,通常与 -t 同时使用;-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用;-d 后台运行容器,并返回容器ID;-e TZ=Asia/Shanghai 解决Jenkins时区问题# 注解------------------------------------------------------------------------------------------------------------------# 查看容器$ docker ps$ docker ps -a-a 显示所有容器,不带-a显示正在运行的容器docker exec jenkinsnine cat /var/jenkins_home/secrets/initialAdminPassword[root@nine ~]# docker exec jenkinsnine cat /var/jenkins_home/secrets/initialAdminPassword619506eb3e0546e68c20bc2f52de3d35# 补充下复制的知识从容器复制到宿主机:docker cp 容器名字/ID:容器路径 宿主机本地路径从宿主机复制到容器:docker cp 宿主机本地路径 容器名字/ID:容器路径# 那我们把容器删除,挂载的还会存在吗?答案存在的;这也是为什么要挂载的原因;但尽可能重要的数据库还是不要用docker启动不要将数据储存在容器中,这也是 Docker 官方容器使用技巧中的一条。容器随时可以停止、或者删除。当容器被rm掉,容器里的数据将会丢失。为了避免数据丢失,用户可以使用数据卷挂载来存储数据。但是容器的 Volumes 设计是围绕 Union FS 镜像层提供持久存储,数据安全缺乏保证。如果容器突然崩溃,数据库未正常关闭,可能会损坏数据。另外,容器里共享数据卷组,对物理机硬件损伤也比较大。# 这里的时区有点问题,具体可以在Jenkins里面执行$ System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')
测试容器
[root@localhost ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@localhost ~]# docker run -u root -it -d -p 8099:8080 --name jenkinsnine \> -v /etc/localtime:/etc/localtime \> -v /usr/bin/docker:/usr/bin/docker \> -v /var/run/docker.sock:/var/run/docker.sock \> -v /home/jenkinsnine/jenkins_home:/var/jenkins_home \> jamnine/jenkinsWARNING: IPv4 forwarding is disabled. Networking will not work.c5d0fd961901b673ceb7beb9766836ce938ce43fd6641de0b7a5ebca7d0aeb1adocker: Error response from daemon: driver failed programming external connectivity on endpoint jenkinsnine (81aaf37c44e24f28201ebf45cd6a6b6dd5bd78ea89506a9da6ba1bc828e81cf6): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8099 -j DNAT --to-destination 172.17.0.2:8080 ! -i docker0: iptables: No chain/target/match by that name.(exit status 1)).
推送镜像到DockerHub
推送Jenkins 容器到DockrHub
docker tag 用于给镜像打标签,语法如下:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
① 比如我现在有一个 centos 镜像:
[root@localhost ~]$ docker imagesREPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c2 weeks ago 202MB
② 我对 centos 进行开发,开发了第一个版本,我就可以对这个版本打标签,打完标签后会生成新的镜像:
[root@localhost ~]$ docker tag centos centos:v1
[root@localhost ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c2weeks ago 202MB centos v1 1e1148e4cc2c2 weeks ago 202MB
③ 我继续对 centos 进行开发,开发了第二个版本,继续打标签:
[root@localhost ~]$ docker tag centos centos:v2
[root@localhost ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c2weeks ago 202MB centos v1 1e1148e4cc2c2weeks ago 202MB centos v2 1e1148e4cc2c2 weeks ago 202MB
④ 以此类推,每开发一个版本打一个标签,如果以后我想回滚版本,就可以使用指定标签的镜像来创建容器:
[root@localhost ~]$ docker run -itd centos:v1
Jenkins DockrHub变更记录
变更记录
记录每次修订的内容,方便追溯。
最近更新时间:2022-03-22
2022-03
增加Net 6.0 SDK编译Web API项目
其他组件常规升级
根据SDK不同划分几个标签
|
版本号 |
标签 |
作者 |
不同组件 |
发布日期 |
|
1.2.0 |
latest |
Jamnine(何拾玖) |
Core SKD 3.1/5/6 |
2022-03-23 |
|
1.2.0 |
v1.2.0-net-3.1-5-6 |
Jamnine(何拾玖) |
Core SKD 3.1/5/6 |
2022-03-23 |
|
1.2.0 |
v1.2.0-net-6.0 |
Jamnine(何拾玖) |
Core SKD 6 |
2022-03-23 |
|
1.2.0 |
v1.2.0-net-5.0 |
Jamnine(何拾玖) |
Core SKD 5 |
2022-03-23 |
|
1.2.0 |
v1.2.0-net-core-3 |
Jamnine(何拾玖) |
Core SKD 3.1 |
2022-03-22 |
●注:latest等同 tag:v1.2.0-net-3.1-5-6
●共同组件
|
1.2.0共同组件 |
Jenkins 2.339|Core SKD 3.1/5/6|NodeJs 14.19.1|Git 2.30.2 |
2021-05
增加yarn编译前端项目使用
添加Git拉取代码
增加Net 5.0 SDK编译Web API项目
其他组件常规升级
|
版本号 |
标签 |
作者 |
不同组件 |
发布日期 |
|
1.1.0 |
v1.1.0- |
Jamnine(何 |
Core SKD 3.1/5 |
05-05 |
|
1.1 |
v1.1.0- |
Jamnine(何 |
Core SKD 5 |
2021-5 |
|
1.1 |
v1.1.0- |
Jamnine(何 |
Core SKD 3.1 |
202105 |
●共同组件
|
1.1共同组件 |
Jenkins 2.257|Core SKD 3.1/5|NodeJs 14.16.1|Git 2.11.0 |
2020-11
制作第一个容器
包含Jenkins 2.266Core SKD 3.1NodeJs 14.15.0Git 2.11.0
npm 6.14.8cnpm 6.1.1linux linux x64 3.10.0-957.21.3.el7.x86_64
CICD初体验,编译Web API Core版本,Vue 2.x 项目
|
版本号 |
标签 |
作者 |
不同组件 |
发布日期 |
|
1.0.0 |
v1.0.0-net-core- |
Jamnine(何拾玖) |
Core SKD 3.1 |
2020-11 |
●共同组件
|
1.0.0共同组件 |
Jenkins 2.266|Core SKD 3.1|NodeJs 14.15.0|Git 2.11.0 |
使用Docker安装Jenkins
Jenkin基本使用
docker中jenkins修改时区
1root身份进入jenkins容器docker exec -it -u root my_jenkins /bin/bash
2修改容器内系统时区。此时可以date查看系统时间已经修改过来,但是jenkins内部时间没有改变。cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
3既然docker容器的时间正确了,但是jenkins的时间还是不对的,说明jenkins的时区使用的不是/etc/localtime,而是另有他处。在jenkins-》系统管理-》系统信息中可以看到有关时区的是user.timezone属性值是Etc/UTC。哪里存放的这个值呢,应该是/etc/timezone了。所以尝试下/etc/timezone的设置。echo Asia/Shanghai > /etc/timezone
4重启jenkins,观察右下角时间已经正确。http://localhost:8080/restart
定

Jenkins 创建 Core 项目自动集成


