前置准备
服务器一台(CentOS 7.9 64位)
Gitee项目
部署目标
搭建Docker+Nginx+Jenkins环境,用于实现前端自动化部署的流程。具体的实现效果为开发人员在本地开发,push提交代码到指定分支,自动触发jenkins进行持续集成和自动化部署。可以设置在部署完成后通过钉钉通知,部署的成功与否,成功后会将打包后的文件上传到服务器,通过nginx反向代理展现页面,失败则会打印相关的错误日志。
友情提示:尽量选择阿里云或者腾讯云服务器,其他服务器部署时可能会出现Jenkins无法正常启动!
先从阿里云服务器开始,目前阿里云服务器是有免费使用三个月云服务器ECS的。
目前学习到4.2已足够,这里已默认配置好,这里要注意安全组配置TCP端口问题,防止ping不通所需端口
1.进入实战,连接远程数据库(后期会补充学习本地shell连接)
输入你的服务器密码直接连接
安装Docker
使用Docker之前,需要先把Docker安装好。
如果已经安装过其他版本的Docker,先把它们及依赖卸载。如果没有安装过,则不用执行下面命令。
- sudo:这是一个允许用户以其他用户身份(默认为超级用户或 root)执行命令的程序。使用 sudo 可以执行需要更高权限的命令。当你输入 sudo 命令时,系统通常会要求你输入你的用户密码以确认你有权执行该命令。
- yum:这是 Yellowdog Updater Modified 的缩写,是一个在 CentOS 等 Linux 发行版上用于自动化软件包安装、更新、删除和管理的工具。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
注意:以下这里跟菜鸟教程不同
1. 安装Docker的依赖库。
安装需要依赖库。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。
CentOS内并没有Docker相关的软件包,如果不执行下面命令,使用 yum安装Docker时,则找不到软件包。
yum install -y yum-utils device-mapper-persistent-data lvm2
2. 添加Docker CE的软件源信息
下面两个软件源,选择一个使用
这个是官方软件源,但是比较慢。
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
这个是阿里云软件源,国内的话推荐使用这个。
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3. 安装Docker CE。
注意:这里会自动安装相关的docker-ce、containerd.io、docker-ce-cli 和 docker-ce-rootless-extras 依赖,如果有询问直接 y 即可
sudo yum install docker-ce
4. 启动Docker服务。
// 设置开机自启
sudo systemctl enable docker
// 启动docker
sudo systemctl start docker
通过执行测试映像验证是否安装正确
sudo docker run hello-world
Docker相关命令
sudo systemctl restart docker // 重启Docker
sudo docker version // 查看版本
sudo docker info // 查看相关信息
sudo docker iamges // 查看安装镜像
Docker安装docker-compose
docker-compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。下载docker-compose:
注意:请先看完所有安装方法再操作
1.命令行进行下载
高速下载:
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
将可执行权限应用于二进制文件:安装完成后提升权限
sudo chmod +x /usr/local/bin/docker-compose
检查是否安装成功:
docker-compose -v
注意:以下结果说明安装失败
此时需要切换到官方github链接去安装(较慢)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
以下为下载安装过程(较慢)
2.下载二进制文件进行安装 (本人使用)
- 确定你的系统架构:
-
- 运行uname -s -m命令来确定你的系统类型和架构。例如,你可能会得到Linux x86_64这样的输出,这意味着你正在使用Linux系统,并且是64位架构。
- 访问Docker Compose的GitHub页面:
- 打开浏览器,访问Docker Compose的GitHub页面:Releases · docker/compose · GitHub
- 下载二进制文件:
- 在GitHub页面上,找到你想要安装的Docker Compose版本。注意要看是否为稳定版(Latest release)
- 点击该版本,进入该版本的详细页面。
- 在该页面上,找到适合你系统架构的二进制文件。例如,对于Linux 64位系统,你可能会看到一个名为docker-compose-Linux-x86_64的文件。(如果没有该文件则看其他版本,我的是v2.24.6)
- 将二进制文件移动到适当的位置:
- 将下载的二进制文件移动到你的系统路径中,以便你可以在任何位置运行它。通常,你可以将其移动到/usr/local/bin/目录下。
可视化操作
打开新文件管理
进入到 /usr/local/bin 目录中
把下载好的二进制文件上传到该目录
等待上传完成
上传完成后 重命名为 docker-compose
- 设置可执行权限:
- 为Docker Compose二进制文件设置可执行权限。运行以下命令:将 /usr/local/bin/docker-compose 文件设置为可执行文件,这样可以通过命令行直接执行 docker-compose 命令,而不必指定脚本的路径。
sudo chmod +x /usr/local/bin/docker-compose
- 检查是否安装成功:
docker-compose -v
安装完成!
Docker安装Nginx和Jenkins服务
安装Nginx和Jenkins
docker镜像拉取nginx和jenkins环境命令如下:
拉取最新版的 Nginx 镜像
这里我们拉取官方的最新版本的镜像:
docker pull nginx:latest
拉取jenkins
docker pull jenkins/jenkins:lts
安装完成后执行docker images可以清晰的看到当前docker下存在的镜像。
docker images
创建docker的相关目录,方便维护
这条命令 mkdir /docker 的意思是在根目录下创建一个名为 docker 的新目录。 mkdir 是“make directory”的缩写,用于创建新的目录。在这里,/docker 表示在根目录下创建一个名为 docker 的目录。这里假设一个项目中有两个端(admin 、h5端)
mkdir /docker
mkdir /docker/compose
mkdir /docker/jenkins_home
mkdir /docker/nginx
mkdir /docker/nginx/conf
mkdir /docker/html
mkdir /docker/html/admin
mkdir /docker/html/h5
/docker/compose是放置docker-compose.yml配置文件,jenkin_home是放置jenkins相关文件,/nginx/conf是放置nginx.conf配置文件,html是放置代码文件。
docker-compose.yml配置文件如下:(要新建相对应的文件)
version: '3'
networks:
frontend:
external: true
services: # 容器
docker_jenkins:
user: root # root权限
restart: always # 重启方式
image: jenkins/jenkins:lts # 使用的镜像
container_name: jenkins # 容器名称
# environment:
# - TZ=Asia/Shanghai
# - "JENKINS_OPTS=--prefix=/jenkins_home" ## 自定义 jenkins 访问前缀(上下文context)
ports: # 对外暴露的端口定义
- 8080:8080
volumes: # 卷挂载路径
- /docker/jenkins_home/:/var/jenkins_home # 挂载到容器内的jenkins_home目录
- /usr/local/bin/docker-compose:/usr/local/bin/docker-compose
docker_nginx: # nginx-dev环境
restart: always
image: nginx
container_name: nginx
ports:
- 80:80
volumes:
- /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- /docker/html:/usr/share/nginx/html
- /docker/nginx/logs:/var/log/nginx
在Docker的上下文中,特别是当使用docker-compose.yml文件来定义和运行容器时,volumes键用于挂载宿主机上的目录或文件到容器内的目录或文件。
1./docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- 这表示将宿主机上的/docker/nginx/conf/nginx.conf文件挂载到容器内的/etc/nginx/nginx.conf文件。这样,当容器启动时,它会使用宿主机上这个路径的nginx.conf文件作为Nginx的配置文件。任何对容器内/etc/nginx/nginx.conf文件的修改都会反映到宿主机上的/docker/nginx/conf/nginx.conf文件,反之亦然(注意,这里假设是双向挂载,但Docker的默认行为可能会根据文件系统的不同而有所不同)。
2./docker/html:/usr/share/nginx/html
- 这表示将宿主机上的/docker/html目录挂载到容器内的/usr/share/nginx/html目录。这通常用于存放Nginx服务的静态网页文件。当容器启动时,它会从容器内的/usr/share/nginx/html目录(实际上是宿主机上的/docker/html目录)读取这些文件来提供Web服务。任何在容器内对/usr/share/nginx/html目录的修改都会反映到宿主机上的/docker/html目录,反之亦然。
3./docker/nginx/logs:/var/log/nginx
- 这表示将宿主机上的/docker/nginx/logs目录挂载到容器内的/var/log/nginx目录。Nginx的日志文件通常存放在/var/log/nginx目录下,通过这个挂载,你可以将容器的日志保存在宿主机上,方便查看和管理。任何在容器内对/var/log/nginx目录的修改(例如新的日志文件被创建或现有日志文件的内容被更新)都会反映到宿主机上的/docker/nginx/logs目录。
nginx.conf配置
root和alias的区别
- root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。
- root的处理结果是:root路径+location路径。alias的处理结果是:使用alias路径替换location路径
- alias是一个目录别名的定义,root则是最上层目录的定义。
- 一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的。而root则可有可无。
- alias只能位于location块中。(root可以不放在location中)
# location /admin 这定义了当请求的URI以/admin开始时(例如,/admin/, /admin/page.html, /admin/some/path等)如何响应这些请求。
#alias指令指定了一个目录,Nginx将从该目录提供文件以响应匹配的URI。
#这里,/usr/share/nginx/html/h5/dist是Nginx服务器上实际存储文件的目录。
#与root指令不同,alias指令会将请求的URI路径替换为alias指定的路径。
#例如,对于请求/admin/page.html,Nginx将尝试从/usr/share/nginx/html/admin/dist/page.html提供文件,而不是从/usr/share/nginx/html/h5/dist/h5/page.html(如果使用root指令)。
# nginx.conf
# main段配置信息
user nginx; # 运行用户,默认即是nginx,可以不进行设置
worker_processes 2; # Nginx 进程数,一般设置为和 CPU 核数一样
error_log /var/log/nginx/error.log warn; # Nginx 的错误日志存放目录
pid /var/run/nginx.pid; # Nginx 服务启动时的 pid 存放位置
# events段配置信息
events {
# use epoll; # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
worker_connections 1024; # 每个进程允许最大并发数
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 设置日志模式 默认即可
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # Nginx访问日志存放位置
sendfile on; # 开启高效传输模式
tcp_nopush on; # 减少网络报文段的数量
keepalive_timeout 65; # 保持连接的时间,也叫超时时间,单位秒
gzip on;
# server段配置信息
server {
#监听的端口
listen 80; # 配置监听的端口
server_name localhost; # 配置的域名
#location目录后加"/",只能匹配目录,不加“/”不仅可以匹配目录还对目录进行模糊匹配。而proxy_pass无论加不加“/”,代理跳转地址都直接拼接。
# http://localhost/jenkins_home/xxx -> http://localhost:8080/jenkins_home/xxx
location /jenkins_home/ {
# 假设你的Jenkins服务可以通过宿主机上的8080端口访问
proxy_pass http://localhost:8080;
# 添加其他需要的Nginx指令,如proxy_set_header等
}
#假设一个项目中有 admin 端
# location /admin 这定义了当请求的URI以/h5开始时(例如,/admin/, /admin/page.html, /admin/some/path等)如何响应这些请求。
#alias指令指定了一个目录,Nginx将从该目录提供文件以响应匹配的URI。
#这里,/usr/share/nginx/html/h5/dist是Nginx服务器上实际存储文件的目录。
#与root指令不同,alias指令会将请求的URI路径替换为alias指定的路径。
#例如,对于请求/admin/page.html,Nginx将尝试从/usr/share/nginx/html/admin/dist/page.html提供文件,
#而不是从/usr/share/nginx/html/h5/dist/h5/page.html(如果使用root指令)。
location /admin {
#linux下HTML文件夹,就是你的前端项目文件夹
# root是完整路径:相当于/usr/share/nginx/html + /admin + /dist/index.html
# alias是重定向:相当于 /usr/share/nginx/html/admin/dist + /index.html
# root /usr/share/nginx/html;
#注意这里已经在docker做了挂载,所以要写映射目录,而不是硬盘目录(也就是docker下的目录)
alias /usr/share/nginx/html/admin/dist;
#输入网址(server_name:port)后,默认的访问页面
#这指定了当请求的是一个目录(如/h5/)而不是一个具体的文件时,Nginx应该提供哪个文件作为默认页面。
#在这里,如果请求的是/h5/并且/usr/share/nginx/html/h5/dist/目录中存在index.html文件,那么Nginx将提供该文件作为响应。
#使用root方式写法
#index dist/index.html;
#使用alias 写法
index index.html; # 默认首页文件
#try_files指令用于尝试不同的URI路径来服务请求,并在所有指定路径都失败时提供一个回退。 这里可以自行写一个跟index.html文件同级的文件去回退
# try_files $uri $uri/ /error.html;
}
#假设一个项目有 H5 端
location /h5 {
alias /usr/share/nginx/html/h5/dist;
index index.html;
}
}
}
环境启动
进入到 docker-compose 同级目录下运行 docker-compose (不然会报错)
cd /docker/compose
执行 docker-compose up -d 去运行 docker-compose
docker-compose up -d
查看容器运行状态
docker ps -a
分别有了相对应的端口证明运行成功
注意:一定要开启安全组相对应端口(在开头有讲),以及如果改动了nginx配置文件记得要执行 docker restart nginx 进行重启
Nginx配置
验证nginx环境
在对应目录/docker/html/admin/dist、/docker/html/h5/dist各新建一个index.html
附上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>这是一个admin测试</h1>
</body>
</html>
输入 http://服务器ip地址/admin 如果页面正常打开代表nginx配置成功
然后删除对应的dist文件夹,后续会自动生成
验证Jenkins
浏览器输入服务器地址:8080/
会提示要输入密码,密码位于docker/jenkins_home/secrets/initialAdminPassword,
Jenkins配置
安装推荐插件即可,等待安装完成
创建相关的jenkins账号(也可使用admin登录)
1.设置中文
下载 local 插件
选择【Manage Jenkins】-> 【Plugins】-> 【Plugins】->
如已安装,执行重启即可,地址栏输入http://ip:端口/restart
2.安装Publish Over SSH、NodeJS
同样的方式这里不再具体操作,【Dashboard】——>【Manage Jenkins】——>【Plugins】——>【Available plugins】,搜索Publish Over SSH、NodeJS,安装后重启。
(1)Publish Over SSH配置远程服务器
Publish Over SSH用来连接远程服务器,接下来去设置连接远程服务器验证方式,本案例采用密码验证。
找到Publish Over SSH,点击新增
在新增后出来的面板中输入信息,之后点击高级
输入密码、服务器端口,并点击Test Configuration Success进行测试,显示successs则成功,之后先点击应用,再保存
(2)NodeJS配置
【Dashboard】——>【系统管理】——>【全局工具配置】——>【NodeJS 安装】
点击新增NodeJS
配置安装NodeJS的基本信息,自定义别名、选择安装版本(可以安装多个版本),最后,先点击应用再保存。
3、添加凭据
添加凭据,也就是GitHub或者其他远程仓库的账号密码,方便之后使用。【系统管理】——>【凭证管理】
点击添加凭证
填写用户名、密码、描述
4、创建Job
第一次部署的Jenkins没用Job,创建一个,首页右边视图中,点击Create a job。
输入项目名称:测试项目,选择构建一个自由风格的软件项目,点击确定
接下来需要配置项目的一些信息
配置完成后,先应用后保存,然后返回首页,打开项目,点击立即构建
查看控制台输出
可以看到构建过程中并没有出现error,并最终显示success,此时基础构建基本完成
5.更多选项配置(根据项目自定义)
(1)勾选参数化构建过程,并配置项目不同端的选项(有些项目可能分后端、手机端等)(勾选参数化构建过程选择选项参数)
(2)代码分支选项,某个端下的代码分支,目前只做master分支,正式项目应该是dev、fixbug等分支
(3)代码环境选项,可指定某一环境进行打包构建(需要结合项目进行配置)
点击保存后可以看到有 Build with Paramerters 选项
6、构建环境
在 Jenkins 中将 Node.js 和 npm 的 bin 文件夹添加到 PATH 中,否则可能就会报错。
7、Build Steps
因为提交服务器代码是没有node_moudle,所以我们需要执行脚本去安装依赖!源码管理可以看到Build Steps模块,选择Execute NodeJS script
选择node版本,这个node版本是在上面我们已经配置过的,如果需要其他版本可通过上面操作新增NodeJs即可
配置完成之后,建议 立即构建 项目
8、shell 命令
在上图中选择增加构建步骤,在下拉框选中执行 shell
然后输入下面的指令
echo 是 Unix/Linux shell 中的一个命令,用于显示一行文本或变量的值。这个命令通常用于脚本、命令行或批处理文件中,以输出信息给用户或记录到日志文件中。同时可以打印变量
#!/bin/bash
node -v
npm -v
echo $PATH
之后去构建,可以看到我们打印的版本信息都打印出了
接下来我们脚本中执行安装node_module以及打包命令。
#!/bin/bash
node -v
npm -v
npm install
echo "依赖安装成功"
npm run build
echo "打包成功"
echo $PATH
然后先应用后保存,去 Build with Paramerters 执行 build。
并且,还可以再服务器中看到打包后的dist文件。(deploy是git项目)
9、自动部署到对应环境项目目录
上面打包到了Jenkins中的workspace中,但是我们设置的项目环境路径跟这个不同,比如${project}端项目目录是/docker/html/${project}/dist/,所以需要打包后,把dist文件内容推送到/docker/html/${project}/dist/目录下。修改一下上面的脚本,改为下面:
#!/bin/bash
node -v
npm -v
npm install
echo "依赖安装成功"
npm run build
echo "打包成功"
rm -rf dist.tar # 每次构建删除已存在的dist压缩包
tar -zcvf dist.tar ./dist #将dist文件压缩成dist.tar
echo $PATH
这个命令使用 tar 工具来创建一个 tar 归档文件(tar archive),并结合了 gzip 压缩。具体来说,这个命令做了以下几件事:
- tar:这是 Unix/Linux 系统中用于归档文件的工具。归档文件是一个或多个文件的集合,通常被压缩以节省存储空间。
- -z:这个选项告诉 tar 使用 gzip 进行压缩。因此,输出的文件(dist.tar)实际上是一个 gzip 压缩的 tar 归档文件,通常被命名为 .tar.gz 或 .tgz(尽管在这个命令中,输出文件的扩展名是 .tar)。
- -c:这个选项告诉 tar 创建一个新的归档文件。
- -v:这个选项是“verbose”的简写,意味着 tar 命令在执行过程中会显示正在归档或解归档的文件名。
- -f dist.tar:这个选项后面的参数是归档文件的名称。-f 选项告诉 tar 接下来的参数是归档文件的名称,而不是要归档或解归档的文件/目录名。
- ./dist:这是你想要归档的目录。在这个例子中,tar 会将 ./dist 目录下的所有文件和子目录都归档到 dist.tar 文件中(注意:这里虽然文件名是 dist.tar,但由于使用了 -z 选项,实际上它是一个 gzip 压缩的 tar 文件)。
然后点击增加构建步骤,选择 Send files or execute commands over SSH ,Send files or execute commands over SSH命令允许你在构建过程中通过SSH连接到远程服务器执行命令或发送文件。
然后填写源文件、目标路径、执行脚本
cd /docker/html/${project}
rm -rf dist/
tar zxvf dist.tar
rm dist.tar
打包流程是:删除之前打包的tar压缩文件dist,把本次打包的dist文件压缩,然以压缩后的dist.tar为源文件,连接到远程服务器,放到/docker/html/admin目录下。然后删除dist目录,解压刚刚远道而来的dist.tar文件,之后删除压缩包。
- Source files:准备发送的文件,该文件是相对于这个项目的workspace目录。例如要发送/docker/jenkins_home/workspace/deploy-admin/dist.tar到目标目录,则设置Source files为dist.tar
- Remove prefix:目标文件前缀添加,例如要操作src下面的某个文件,就设置成src,本案例是跟目录,无需设置
- Remote directory:目标目录,本案例要复制到admin下的dist文件,/docker/html/admin
- Exec command:最后执行的命令,可在这里进行解压,删除,复制等操作
最后再次执行立即构建。打开你的服务器地址+项目地址。可以看到刚刚部署的项目啦。
温馨提示:如果部署成功且打包到相对应目录,可能会出现访问不到assets目录资源(404),需要特殊配置打包路径(根据实际项目改动)
进阶:个性化配置
以上只是最基础的简单配置,对于单项目已足够,实际项目会出现一个项目多个端(admin、h5等),所以git代码地址也不仅仅是一个;也会出现多分支情况(dev、其他分支);包括多接口环境(dev/prod/test等);以及是否需要先提前编译好(而非直接部署/发布);钉钉通知等个性化功能。
此时使用源码管理已不能单独拉取指定的git了(目前只学习到这种),所以需要进入服务器不同端的文件夹执行git命令拉取git代码等,以及不需要直接部署,Send files or execute commands over SSH 也不再需要,而是全部 通过shell命令 去操作。
参数化构建配置在上面保持不变,额外添加的参数配置如下,不做过多操作说明,依次添加即可:
是否构建(默认勾选)
是否部署(默认勾选)
是否需要钉钉通知(默认不勾选)
温馨提示:关于钉钉群聊通知机器人配置自行百度即可,这里不做过多说明(比较简单)
注意:这里不再需要Send files or execute commands over SSH,记得去掉构建后操作,后面通过shell命令执行拷贝操作即可
jenkins配置 nginx 挂载卷
因 jenkins 跟 nginx 容器是相互独立,需要配置挂载卷,这样jenkins在打包后才能把dist文件拷贝到nginx相关的项目目录下,所以要对 docker-compose.yml 文件改写
version: '3'
networks:
frontend:
external: true
services: # 容器
docker_jenkins:
user: root # root权限
restart: always # 重启方式
image: jenkins/jenkins:latest # 使用的镜像
container_name: jenkins # 容器名称
# environment:
# - TZ=Asia/Shanghai
# - "JENKINS_OPTS=--prefix=/jenkins_home" ## 自定义 jenkins 访问前缀(上下文context)
ports: # 对外暴露的端口定义
- 8080:8080
volumes: # 卷挂载路径
- /docker/jenkins_home/:/var/jenkins_home # 挂载到容器内的jenkins_home目录
- /usr/local/bin/docker-compose:/usr/local/bin/docker-compose
#将主机上存储的已知主机公钥列表文件挂载到运行的 Docker 容器中,供容器内部的 SSH 客户端使用。
#这样做是为了避免每次启动容器时都重新建立主机与远程主机的连接,提高了安全性和便利性。
- ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro
- /docker/html:/usr/share/nginx/html # 挂载到 Nginx 容器内的某个路径
docker_nginx:
restart: always
image: nginx
container_name: nginx
ports:
- 80:80
volumes:
- /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- /docker/html:/usr/share/nginx/html
- /docker/nginx/logs:/var/log/nginx
这里注意,也要对 SSH 公钥文件挂载到 docker容器,防止每次都需要验证
配置完保存后要对docker-compose进行重启。注意!不能直接使用 docker-compose restart ,这样可能会导致挂载卷不生效。
cd /docker/compose
docker-compose down
docker-compose up -d
判断此时是否能正常访问到/usr/share/nginx/html相关目录,需要进入 jenkins 容器,输入以下代码
ls /usr/share/nginx/html
可以看到nginx下的项目目录已存在
这里做一个自我理解(可能有误):挂载卷的意义其实就是映射,真实目录(/docker下的)映射到主机(虚拟)容器(其他目录),通过操作真实目录下的目录或文件都会同步映射到主机(虚拟)目录,而反过来一样,所以在jenkins通过shell命令操作任何目录/文件,都会同步到真实目录中
jenkins配置 git 的 SSH 公钥
因为是通过shell命令去执行git操作,所以需要在jenkins容器配置好SSH仓库公钥,回到服务器终端操作页面,执行以下指令获取jenkins容器id
docker ps -a
然后进入 jenkins 容器内部并打开一个交互式的 Bash shell
docker exec -it 564c5b1f3141 /bin/bash
- docker exec:这是Docker命令的一部分,用于在运行中的容器内部执行命令。
- -it:这是两个选项的组合。-i 表示交互式操作,-t 表示分配一个终端(TTY)。这两个选项一起表示要打开一个交互式的终端来执行命令。
- 564c5b1f3141:这是容器的ID,它是要在其中执行命令的目标容器的唯一标识符。
- /bin/bash:这是要在容器内部执行的实际命令。在这种情况下,它是要启动一个Bash shell。
然后执行gitee 相关的ssh配置公钥操作,这里不做过多操作解释,跟着gitee一直操作即可
配置完检测连接是否成功!
shell命令配置
回到jenkins可视化页面中,对构建步骤shell部分进行改写
#!/bin/bash
echo $PATH
echo "当前node版本: $(node -v)"
# 项目字典
declare -A projectDic
projectDic=([admin]="XX项目后台端" [h5]="XX项目H5端")
# 当前服务器时间
starttime=`date +'%Y-%m-%d %H:%M:%S'`
# 构建
function build(){
# 判断分支文件夹是否存在
if [ -d deploy-${project} ];then
cd deploy-${project}
echo "=============== $(project)项目文件夹存在 执行pull ==============="
echo "git fetch && git checkout -f ${branch} && git pull origin ${branch}"
git fetch
git checkout -f ${branch}
git pull origin ${branch}
else
echo "=============== $(project)项目文件夹不存在 执行clone ====================="
echo "git clone -b ${branch} [email protected]:cpc0209/deploy-${project}.git"
git clone -b ${branch} [email protected]:cpc0209/deploy-${project}.git
# cd到指定项目目录下操作
cd deploy-${project}
fi
echo "=============== deploy-${project} pull/clone ok!start npm install... ====================="
# 以特权用户的身份运行 npm
npm install --unsafe-perm
echo "=============== deploy-${project} install ok! start npm run build... ====================="
# 如果是正式环境
if [ "${env}" = "prod" ]; then
npm run build
else
npm run build:${env}
fi
echo "=============== deploy-${project} build:${env} success! ====================="
}
# 部署到指定ngnix目录
function deploy(){
echo "=============== deploy-${project} deploy start... ====================="
dist_path=$WORKSPACE/deploy-${project}/dist/
#web项目路径
web_path=/usr/share/nginx/html/${project}
echo "web_path路径: $web_path"
echo "即将从 $dist_path 拷贝"
# 强制删除web项目路径
rm -rf ${web_dir}
# 重新创建一个web项目路径
mkdir -p ${web_dir}
# 把dist文件夹拷贝到 web项目路径
cp -r $dist_path $web_path
echo "copy success!"
# 给web_path添加读取权限
chmod +r ${web_path}/*
}
# 项目自动化构建成功通知
function dingNotify() {
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);
echo "=============================代码发布通知钉钉群================================"
text="${env}环境: ${projectDic[$project]}(${branch}) 已部署成功,\n 构建开始时间:${starttime}, \n 构建结束时间:${endtime}, \n 构建用时: "$((end_seconds-start_seconds))"秒"
echo "${text}"
curl -XPOST 'https://oapi.dingtalk.com/https://oapi.dingtalk.com/这里换成你的钉钉机器人' -H 'Content-Type: application/json' -d "{\"msgtype\": \"text\",\"text\": {\"content\":\"$text\"},\"at\": {\"isAtAll\": false}}"
echo "本次构建用时: "$((end_seconds-start_seconds))"秒"
echo "=============================代码发布通知完成=================================="
}
# 项目自动化构建失败通知
function dingErrorNotify() {
echo "=============================代码发布通知钉钉群================================"
text="${env}环境: ${projectDic[$project]}(${branch}) 构建失败,\n 构建时间:$(date "+%Y-%m-%d %H:%M:%S")"
echo "${text}"
curl -XPOST 'https://oapi.dingtalk.com/这里换成你的钉钉机器人' -H 'Content-Type: application/json' -d "{\"msgtype\": \"text\",\"text\": {\"content\":\"$text\"},\"at\": {\"isAtAll\": false}}"
echo "=============================代码发布通知完成=================================="
}
# 是否构建
if [ "$isBuild" == "true" ];then
build
if [ $? -eq 0 ]; then
echo "[INFO]编译成功"
else
echo "[ERROR]编译失败"
# 退出
exit -1
fi
echo "=============== ${project} 编译成功,等待部署 ====================="
fi
#是否部署
if [ "$isDeploy" == "true" ];then
deploy
if [ $? -ne 0 ];then
#部署失败则失败通知
dingErrorNotify
exit -1
fi
echo "=============== ${project} 部署完成 ====================="
#是否钉钉通知
if [ "$isSendDing" == "true" ];then
dingNotify
fi
fi
以上代码要注意的点有:
#!/bin/bash 必须要写,原因自行百度即可。
cp 命令拷贝参考Linux cp 命令 | 菜鸟教程
关于 项目环境以及构建指令 需要自行判断是否需要,部分项目只需构建正式环境。
钉钉机器人通知自行添加,按自己需求添加。其他命令不懂的可自行百度,没有太大难度。
部署成功后会有钉钉通知:
重新打开项目地址即可看到更新内容:
拓展:
同样可以通过本地ssh连接远程数据库ip,把本地dist文件发送到指定的目录下
# 连接到远程主机,删除目录内容
ssh root@$REMOTE_IP rm -rf /项目地址/
# 连接到远程主机,创建目录
ssh root@$REMOTE_IP mkdir -p /项目地址/
# 将本地文件复制到远程主机
scp -r ./dist/* root@$REMOTE_IP:/项目地址/