4

万字干货! 使用docker部署jenkins和gitlab - 王bourne

 1 year ago
source link: https://www.cnblogs.com/wbourne/p/17035591.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

万字干货! 使用docker部署jenkins和gitlab

阅读本文, 需要有基础的Git, Linux, Docker, Java, Maven, shell知识, 并最少有一台内存16G以上并已经安装好了Docker的机器.

Jenkins是是一个CI/CD工具, GitLab是一个类似与GitHub代码托管平台, 本文将实现通过docker部署Jenkins与GitLab, 并自动化发布应用: 本地机器将代码推送到GitLab, GitLab通过web hook触发Jenkins流水线, Jenkins获取GitLab的代码并生成jar包, 将jar包推送到应用服务器, 并运行jar包. 只需一个push操作, 即可自动发布应用.

综上, 我们需要三个容器, 一个Jenkins容器, 一个GitLab容器, 一个运行jar包的容器(本文称其为应用容器, 即运行java应用的容器), 以及还要有一台写Java代码的个人电脑. 部署容器的电脑(本文称其为服务器)可以是同一个个人电脑, 也可以是其他电脑或服务器, 部署容器的电脑的内存推荐16G以上, 因为GitLab比较吃内存, 配置不够可能带不动. 本文是一台个人电脑写代码, 一台服务器部署三个容器.

为了方便大家理解与阅读, 在个人电脑执行的命令, 其命令提示符为$$; 服务器的命令提示符为$; 容器内的命令提示符为>.

2168641-20230111211617720-70891514.png

2. 容器互联

因为Jenkins需要从GitLab中拉取代码, Jenkins也需要向应用服务器上传jar包, 即容器间需要通信, 所以我们需要创建一个桥接网络, 将容器都部署在桥接网络上, 容器间就可以互联互通了.

通过下面的命令, 创建一个名为my-bridge的桥接网络:

$ docker network create --driver bridge --subnet 172.12.0.0/16 --gateway 172.12.0.1 my-bridge

3. 应用容器

3.1 部署应用容器

执行下面的命令运行应用容器, 这里我们选择Ubuntu 20.04作为基础镜像, 使用其他的发行版也可以, 这里使用Ubuntu只是因为我对Ubuntu最了解.

$ docker run --interactive --tty --detach \ --name app \ --hostname app \ --restart on-failure \ --network my-bridge \ --publish 31022:22 \ --publish 31808:8080 \ --volume $PWD/app:/root/app \ ubuntu:20.04

3.2 配置SSH

Jenkins向服务器传输jar包一般是通过SSH, 所以我们还需要在应用容器中安装SSH. 运行应用也需要java, 没装java也需要安装java.

# 进入应用容器$ docker exec -it app bash # 修改apt源之前, 备份apt源> cp /etc/apt/sources.list /etc/apt/sources.list.org # 更换apt源(默认的apt源非常慢)> echo "deb http://archive.canonical.com/ubuntu focal partnerdeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ focal main restricteddeb http://mirrors.aliyun.com/ubuntu/ focal multiversedeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricteddeb http://mirrors.aliyun.com/ubuntu/ focal-security multiversedeb http://mirrors.aliyun.com/ubuntu/ focal-security universedeb http://mirrors.aliyun.com/ubuntu/ focal universedeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricteddeb http://mirrors.aliyun.com/ubuntu/ focal-updates multiversedeb http://mirrors.aliyun.com/ubuntu/ focal-updates universe" > /etc/apt/source.list # 安装SSH和java> apt update && apt install -y openssh-server openjdk-8-jdk-headless

平时我们用的服务器, SSH一般都是开机自启动, 所以我们几乎不会去启动SSH, 但是容器中都没有SSH, 更别说开机自启了, 所以安装好之后还要启动SSH.

注意: 容器内一般直接使用root用户, 默认情况下SSH不允许root用户使用密码登录, 我们需要将PermitRootLogin yes加入到SSH配置文件中, 使root用户可以通过密码登录.

# 备份ssh配置> cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org # 使root可以用密码登录> echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config # 启动ssh> /sbin/sshd # 第一次启动可能会报错, 显示/run/sshd不存在, 不存在手动新建就好了> mkdir /run/sshd # 再次启动ssh> /sbin/sshd # 修改root密码> passwd

4. Jenkins

4.1 部署Jenkins

使用docker部署Jenkins, 我们当然需要Jenkins的容器, 但是请注意, jenkins有两个官方容器: jenkinsjenkins/jenkins. jenkins在2018年就已经弃用, 不再更新, 现在应该使用jenkins/jenkins, 现在大部分镜像的命名都采用组织名称/镜像名称的格式了.

使用如下命令来启动Jenkins:

$ docker run --detach \ --user root \ --name jenkins \ --hostname jenkins \ --restart on-failure \ --network my-bridge \ --publish 37808:8080 \ --publish 37500:50000 \ --volume $PWD/jenkins:/var/jenkins_home \ jenkins/jenkins:2.385

4.2 安装插件

启动Jenkins后, 使用浏览器输入服务器地址:37808进入Jenkins界面, 默认的用户为admin, 密码的话我们有两种方式知道密码

  • 网页会提示我们密码储存在/var/jenkins_home/secrets/initialAdminPassword, 所以我们查看这个文件就行了, 使用docker exec -t jenkins cat /var/jenkins_home/secrets/initialAdminPassword即不进入容器查看文件
  • Jenkins的启动日志中也有密码所在文件的路径以及密码, 使用docker logs jenkins查看Jenkins的日志, 也能找到密码

接下来选择安装推荐的插件就好了

2168641-20230110001820207-361333526.png

然后点击右下角的使用admin账户继续

2168641-20230110001827854-967559364.png

接下来我们还要做一些准备工作, 比如安装插件, 配置mavan, 配置ssh...... 配置好之后我们才会正式的构建项目.

进入主页后, 点击 Manage Jenkins -> Manage Plugins -> Available plugins, 安装以下三个插件:

  • Publish Over SSH
  • Maven Integration
  • Build Authorization Token Root
2168641-20230110001835078-1993271322.png
2168641-20230110002234291-1683011331.png

4.3 安装maven

Jenkins默认是没有maven的, 所以我们还需要安装maven, 使用docker exec -it jenkins bash进入到容器, 再查看下系统

> cat /etc/*releasePRETTY_NAME="Debian GNU/Linux 11 (bullseye)"NAME="Debian GNU/Linux"VERSION_ID="11"VERSION="11 (bullseye)"VERSION_CODENAME=bullseyeID=debianHOME_URL="https://www.debian.org/"SUPPORT_URL="https://www.debian.org/support"BUG_REPORT_URL="https://bugs.debian.org/"

这里使用的是Debian, 先换下apt源, 不然会很慢

# 备份apt源> cp /etc/apt/sources.list /etc/apt/sources.list.org # 更换apt源> echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-freedeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-freedeb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-freedeb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free" > /etc/apt/sources.list

然后执行apt update && apt install maven安装maven, 安装好后运行mvn -v查看maven版本, 有对应的输出说明已经安装好了

# 注意, 此处显示了 Maven home> mvn -vApache Maven 3.6.3Maven home: /usr/share/mavenJava version: 11.0.17, vendor: Eclipse Adoptium, runtime: /opt/java/openjdkDefault locale: en, platform encoding: UTF-8OS name: "linux", version: "3.10.0-1160.80.1.el7.x86_64", arch: "amd64", family: "unix"

4.4 配置maven

安装好之后, 还要告诉Jenkins安装好了Maven, 点击主页的 Manage Jenkins -> Global Tool Configuration -> Maven -> 新增Maven 新增一个maven

  • Name 只是一个标识, 可以随便取. 假如安装了多个版本的maven的话, 在Name上有所区分就好了
  • Maven home 填写mvn -v的输出
  • 取消勾选自动安装
2168641-20230110001849220-747698845.png

4.5 配置远程服务器

远程服务器指的是, Jenkins构建好jar包之后, 上传jar到的服务器, 同样也需要配置, 在主页点击Manage Jenkins -> Configure System

找到 Publish over SSH, 点击新增

  • Name 随便取, 只是一个标识
  • Hostname 为应用服务器地址, 因为我们用的是docker桥接网络, 所以不需要输入IP, 直接填应用容器的名字即可
  • Username 为应用服务器用户名
  • Remote Directory 表示远程目录(应用服务器), 默认为/root,
  • 勾选上 Use password authentication, or use a different key, 不然没地方输密码
  • Passphrase/Password 表示应用服务器密码
2168641-20230110001856693-1895996166.png

右下角有个Test Connecttion, 可以测试连接, 能看到Success就说明配置没问题了

2168641-20230110001940912-1591420609.png

5. GitLab

5.1 部署GitLab

执行下面的命令运行GitLab容器. 请注意, 如果不使用默认的端口, 除了使用--publish映射端口外, 还需要在环境变量GITLAB_OMNIBUS_CONFIG中注明端口.

$ docker run --detach \ --env GITLAB_OMNIBUS_CONFIG="external_url='http://127.0.0.1:35080'; gitlab_rails['gitlab_ssh_host'] = '127.0.0.1'; gitlab_rails['gitlab_shell_ssh_port'] = 35022" \ --memory 12GB \ --memory-swap 16GB \ --name gitlab \ --hostname gitlab \ --restart on-failure \ --network my-bridge \ --publish 35080:80 \ --publish 35022:22 \ --volume $PWD/gitlab/config:/etc/gitlab \ --volume $PWD/gitlab/logs:/var/log/gitlab \ --volume $PWD/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:15.6.3-ce.0

5.2 配置GitLab

Gitlab启动需要几分钟, 启动好之后浏览器输入 http://服务器地址:35080 进入Gitlab的登录页面, 默认用户名为root, 密码通过docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password查看.

在主页点击 头像 -> Preferences -> SSH Keys 可以配置SSH密钥.

在主页点击 头像 -> Preferences -> Password 可以修改密码.

5.3 上传项目

GitLab配置好之后就可以推送代码了, 在推送代码前, 需要GitLab有对应的项目, 我们先来新建一个项目,
点击主页右上角加号 -> New project -> Create blank project新建一个项目.

接下来推送代码. 大家可以推送自己的项目; 我也准备了一个简单的Spring Boot项目, 地址为 https://github.com/yuanpeilin/spring-boot-demo, 项目比较简单, 就一个类, 访问URL:8080/hello就能返回当前时间.

这里比较简单不做过多描述, 唯一需要注意的是, 我给了一个GitHub地址, 如果用的是我的GitHub项目, 不注意的话推送到GitLab会失败, 因为从GitHub clone已经用了origin这个名字了, 推送到GitLab要换个名字, 下述三条命令中的origin随便改个名字, 把三条命令的origin改成一样的就行.

2168641-20230110002000539-1385697936.png

$$ git remote add origin ssh://[email protected]:35022/root/gitlab-test.git $$ git remote set-url origin ssh://[email protected]:35022/root/gitlab-test.git $$ git push -u origin HEAD

6.1 手动触发Jenkins

在Jenkins主页点击 新建项目 -> 构建一个maven项目

2168641-20230110002010867-2043917127.png

接下来就到了配置界面模块

  • 源码管理要选择Git
  • Repository URL要填从GitLab复制来的HTTP形式URL, 例如http://gitlab/root/spring-boot-demo.git, 填完之后点击下空白的地方, 可能会有报错, 这是因为git仓库可能被设置为私有的, 要有权限才能访问
  • 点击下方的Credentials模块的添加GitLab的用户名和密码, 再次点击空白处, 红色的报错已经消失了
2168641-20230110002022857-1164546186.png

2168641-20230110002026686-1885231039.png

下一步配置post step模块, 这是在Jenkins构建好jar包后执行的操作, 点击Add post-build step选择Send build artifacts over SSH

  • SSH Server选择配置远程服务器配置的应用服务器, jar包会传到这个服务器上
  • Source files选择jar包相对路径, 用我的项目的话是target/spring-boot-demo-1.0.jar
  • Remove prefix填入target, 就会自动移除target目录, 之上传jar包, 不然传到应用服务器会将target目录也一起上传, 且jar包也在target目录下
  • Remote directory填入/app, 会在配置远程服务器配置的Remote Directory的基础上追加, 本文中最终的路径为/root/app/, jar包在应用服务器的路径为/root/app/spring-boot-demo-1.0.jar
  • Exec command填入 bash /root/app/start.sh, 这是在执行了上面的步骤后会执行的命令

在到应用容器中写入以下内容到 /root/app/start.sh

#!/bin/bash BASE_HOME=/root/appJAR_NAME=spring-boot-demo-1.0.jarLOG_NAME=app.log# 停止应用ps -ef | grep $JAR_NAME | grep -v grep | awk '{print $2}' | xargs -i kill {}# 备份日志if [ -f $BASE_HOME/$LOG_NAME ]; then mv $BASE_HOME/$LOG_NAME $BASE_HOME/$LOG_NAME.`date +%Y%m%d%H%M%S`fi# 备份jar包if [ -f $BASE_HOME/$JAR_NAME ]; then cp $BASE_HOME/$JAR_NAME $BASE_HOME/$JAR_NAME.`date +%Y%m%d%H%M%S`fi# 启动应用nohup java -jar $BASE_HOME/$JAR_NAME &>$BASE_HOME/$LOG_NAME &
2168641-20230110002050257-1986759416.png

点击保存后, 点击左边的立即构建, 再到浏览器里面输入 http://服务器地址/hello , 能看到返回了, 就说明应用已经启动好了.

6.2 通过GitLab自动出发Jenkins构建

点击Jenkins主页的 Item -> 配置 -> 构建触发器, 勾选上触发远程构建, 填入token, 随便填入一个值就可以, 这里设置为aabbcc

2168641-20230110002057946-808405097.png
2168641-20230111003602794-76236692.png

配置Token的下方提示了我们可以用JENKINS_URL/job/spring-boot-demo/build?token=TOKEN_NAME触发, 现在我们再开启一个无痕窗口, 输入服务器地址:37808/job/spring-boot-demo/build?token=aabbcc, 发现要登录?!

之前我们安装了一个Build Authorization Token Root插件, 这是因为默认情况下远程出发jenkins需要登录, 有了这个插件不需要登录也可以出发Jenkins构建. 再到浏览器开个无痕窗口, 根据这个插件的文档, 我们访问的地址与上面有所区别, 访问 http://服务器地址:37808/buildByToken/build?job=spring-boot-demo&token=aabbcc , 然后我们回到Jenkins会发现已经在构建项目了.

现在就简单了, 回到Gitlab, 在主页点击头像 -> Settings -> Web Hooks, 在URL中填入http://服务器地址:37808/buildByToken/build?job=spring-boot-demo&token=aabbcc, 并取消勾选 Enable SSL verification, 点击保存就可以了.

2168641-20230110002108647-107786554.png

现在再随便改点代码, 执行git push 远程仓库名, 将代码推送到GitLab后, GitLab会自动往配置的地址发生请求, Jenkins就会出发构建, 构建好了后就会自动换包并重启应用, 至此, 大功告成!!!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK