前言

本文介绍使用docker+nginx+jenkins将hexo博客部署至云服务器。

博客提交云服务器流程:

  1. 本地电脑hexo三连,或者githubaction三连部署到github。
  2. jenkins监测到github项目主页更新,拉取更新后的文件到vps的jenkins工作目录,然后持续集部署更新文件。Jenkins(概念篇):Jenkins 简介_ron jenkins 什么意思
  3. vps本地脚本把jenkins工作目录更新的文件传输到nginx工作目录。

准备工作

可以部署到githubpage的hexo博客;vps云服务器;

vps安装docker,docker-compose

安装git

1
sudo apt-get install git

docker安装jenkins和nginx

创建目录

1
2
3
4
5
6
7
8
9
cd /root/data/docker_data/jenkins         
mkdir compose
mkdir jenkins_home
mkdir nginx
mkdir nginx/conf
mkdir html
mkdir html/dev
mkdir html/release
mkdir html/pro

创建docker-compose.ymlnginx.conf配置文件

1
2
3
4
5
cd /root/data/docker_data/jenkins/compose
touch docker-compose.yml

cd /root/data/docker_data/jenkins/nginx/conf
touch nginx.conf

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
version: '3'
services: # 集合
docker_jenkins:
user: root # 为了避免一些权限问题 在这我使用了root
restart: always # 重启方式
image: jenkins/jenkins:lts # 指定服务所使用的镜像 在这里我选择了 LTS (长期支持)
container_name: jenkins # 容器名称
ports: # 对外暴露的端口定义,8888可修改
- 8888:8080 # 访问Jenkins服务端口
- 50000:50000
volumes: # 卷挂载路径
- ../jenkins_home/:/var/jenkins_home # 这是我们一开始创建的目录挂载到容器内的jenkins_home目录
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker # 这是为了我们可以在容器内使用docker命令
- /usr/local/bin/docker-compose:/usr/local/bin/docker-compose
docker_nginx_dev: # nginx-dev环境
restart: always
image: nginx
container_name: nginx_dev
ports:
- 8871:8001 # 对外暴露的端口定义,8871可修改
volumes:
- ../nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ../html:/usr/share/nginx/html
- ../nginx/logs:/var/log/nginx

docker_nginx_sit: # nginx-sit环境
restart: always
image: nginx
container_name: nginx_sit
ports:
- 6092:8002 # 对外暴露的端口定义,6092可修改
volumes:
- ../nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ../html:/usr/share/nginx/html
- ../nginx/logs:/var/log/nginx

上面的代码跑了三个容器,jenkins,nginx_dev,nginx_sit

nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# nginx.conf 例:
user nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;


events {
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;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

gzip on;

#dev环境
server {
#监听的端口
listen 8001;
server_name localhost;
#设置日志
# access_log logs/dev.access.log main;

#定位到index.html
location / {
#linux下HTML文件夹,就是你的前端项目文件夹
root /usr/share/nginx/html/dev/hexo;
# root /home/html/dev/dist;
#输入网址(server_name:port)后,默认的访问页面
index index.html;
try_files $uri $uri/ /index.html;
}
}

#sit环境
server {
#监听的端口
listen 8002;
server_name localhost;
#设置日志
# access_log logs/sit.access.log main;

#定位到index.html
location / {
#linux下HTML文件夹,就是你的前端项目文件夹
root /usr/share/nginx/html/sit/hexo;
# root /home/html/dev/dist;
#输入网址(server_name:port)后,默认的访问页面
index index.html;
try_files $uri $uri/ /index.html;
}
}


# include /etc/nginx/conf.d/*.conf;


}

运行docker容器

1
2
cd /root/data/docker_data/jenkins/compose
docker-compose up -d

查看容器运行状态

1
docker-compose ps -a

三个容器运行状态

验证nginx

/docker/html/dev/hexo目录下新建index.html,文件内容如下

1
2
3
4
5
6
7
8
9
10
11
<!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>welcome to Nginx</h1>
</body>
</html>

浏览器访问服务器ip:8871,例如192.168.8.5:8871

返回页面

jenkins配置

浏览器输入你的服务器ip:8888

解锁jenkins

图片展示的docker-compose.yml和上面给出的有出入。当前运行给出挂载jenkins_home前有两个点,代表当前目录的上一级目录。所以实际运行的jenkins_home目录在docker-compose.yml的上一级目录。总之到jenkins_home目录下去找密码。

后面的安装和配置建议看从零开始搭建JENKINS+GITHUB持续集成环境,这篇文章看Jenkins的使用验证构建。主要步骤看建议的文章,下面列出有出入的地方

  • 新建任务时,任务名填blog。

自定义任务名字的话,在后续创建脚本的步骤中把监控文件代码中的blog,改成你的任务名称。

1
2
# 监控的文件
JENKINS_FILE="/root/data/docker_data/jenkins/jenkins_home/workspace/blog/hexo.tar"

任务名

  • 启用github插件,github plugin虽然默认安装了,但是并没有启用。需要取消启用github-branch这个插件,再开启github plugin。这两个插件只能启用一个,所以需要取消一个。

github插件

  • 在配置构建步骤时,再添加一个执行shell的步骤

添加执行shell

1
2
rm -rf hexo.tar    
tar -zcvf hexo.tar ./*

脚本的意思是,jenkins从github拉取更新后的代码之后,先把jenkins容器/var/jenkins_home/workspace/blog/hexo.tar 文件先给删除,然后再打包jenkins容器/var/jenkins_home/workspace/blog目录下的所有文件到hexo.tar文件。把文件打包成hexo.tar方便后续传输到nginx。

注意:构建步骤这里添加的执行shell本质是在jenkins容器的/var/jenkins_home/workspace/blog目录下执行的操作。所以在这里写脚本传输jenkins容器文件到nginx容器是没可能的。下面会给出本地脚本来进行容器间文件的传输。

  • 补几张图

建议文章的图会和安装的有出入,但细心点是可以按他的步骤设置好的。

配置github凭据

验证凭据

构建测试

项目配置

启用脚本

脚本功能:每隔10秒监测jenkins构建的输出目录workspace下hexo.tar是否更新,有更新就会执行先删除目标目录hexo文件夹下的所有文件,然后解压hexo.tar到目标目录,无更新不执行。

1
2
cd /root/data/shell_script
touch monitor_jenkins_to_nginx.sh

复制代码到monitor_jenkins_to_nginx.sh文件,然后执行以下命令

1
./monitor_jenkins_to_nginx.sh

monitor_jenkins_to_nginx.sh脚本代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/bin/bash

# 监控的文件
JENKINS_FILE="/root/data/docker_data/jenkins/jenkins_home/workspace/blog/hexo.tar"

# 解压目标目录
NGINX_DEST_DIR="/root/data/docker_data/jenkins/html/dev/hexo"

# 监控间隔时间(秒)
INTERVAL=10

# 日志文件路径
LOG_FILE="/root/data/shell_script/monitor_jenkins_to_nginx/monitor_jenkins_to_nginx.log"

# 停止标志文件
STOP_FILE="/root/data/shell_script/monitor_jenkins_to_nginx/stop_monitor_script"

# 最大日志文件大小(字节)20 MB
MAX_LOG_SIZE=$((20 * 1024 * 1024))

# 创建日志目录(如果不存在)
mkdir -p "$(dirname "$LOG_FILE")"

# 获取文件的最后修改时间
get_file_mod_time() {
if [ -f "$JENKINS_FILE" ]; then
stat -c %Y "$JENKINS_FILE"
else
echo 0
fi
}

# 检查并控制日志文件大小
check_log_size() {
if [ -f "$LOG_FILE" ]; then
LOG_SIZE=$(stat -c%s "$LOG_FILE")
if [ "$LOG_SIZE" -gt "$MAX_LOG_SIZE" ]; then
echo "日志文件超过 $MAX_LOG_SIZE 字节,正在删除..." >> "$LOG_FILE"
> "$LOG_FILE"
echo "日志文件已被重置。" >> "$LOG_FILE"
fi
fi
}

# 上一次的文件修改时间
LAST_MOD_TIME=$(get_file_mod_time)

# 后台执行脚本
if [ "$1" != "start" ]; then
echo "正在启动脚本,并在后台运行..."
nohup $0 start > "$LOG_FILE" 2>&1 &
echo "脚本已在后台启动,日志输出到 $LOG_FILE"
exit 0
fi

# 监控文件变化
while true; do
# 检查是否存在停止标志文件
if [ -f "$STOP_FILE" ]; then
echo "检测到停止标志文件,脚本退出。" >> "$LOG_FILE"
rm -f "$STOP_FILE"
exit 0
fi

CURRENT_MOD_TIME=$(get_file_mod_time)

if [ "$CURRENT_MOD_TIME" -gt "$LAST_MOD_TIME" ]; then
echo "检测到 $JENKINS_FILE 文件变化,正在处理..." >> "$LOG_FILE"

# 确保目标目录存在
mkdir -p "$NGINX_DEST_DIR"

# 删除目标目录中除 nav, qrc, fyh, bbd 目录外的所有文件
find "$NGINX_DEST_DIR" -mindepth 1 -maxdepth 1 ! -name 'nav' ! -name 'qrc' ! -name 'fyh' ! -name 'bbd' -exec rm -rf {} +

if [ $? -eq 0 ]; then
echo "已成功删除 $NGINX_DEST_DIR 目录中的无关文件。" >> "$LOG_FILE"

# 解压文件到目标目录
tar -xf "$JENKINS_FILE" -C "$NGINX_DEST_DIR"

if [ $? -eq 0 ]; then
echo "文件已成功解压到 $NGINX_DEST_DIR" >> "$LOG_FILE"
else
echo "解压文件失败,请检查路径是否正确。" >> "$LOG_FILE"
fi
else
echo "删除 $NGINX_DEST_DIR 目录中的文件失败,请检查路径。" >> "$LOG_FILE"
fi

# 更新最后的修改时间
LAST_MOD_TIME="$CURRENT_MOD_TIME"
fi

# 检查日志文件大小并控制
check_log_size

# 等待指定时间再进行下一次检查
sleep "$INTERVAL"
done

日志记录

1
2
3
检测到 /root/data/docker_data/jenkins/jenkins_home/workspace/blog/hexo.tar 文件变化,正在处理...
已成功删除 /root/data/docker_data/jenkins/html/dev/hexo 目录中的所有文件。
文件已成功解压到 /root/data/docker_data/jenkins/html/dev/hexo

停止运行脚本

1
2
cd /root/data/shell_script/monitor_jenkins_to_nginx
touch stop_monitor_script

查看脚本是否退出运行

1
ps aux | grep monitor_jenkins_to_nginx.sh | grep -v grep

如果没有输出,则表示该脚本已经退出运行状态

脚本设置开机自启

方法 1: 使用 crontab 设置开机自启

将脚本添加到 crontab 中,以便在系统启动时自动运行。

  1. 安装 cron

使用 apt 包管理器来安装 cron,通常在 Debian/Ubuntu 系统上可以执行以下命令:

1
2
sudo apt update
sudo apt install cron
  1. 启动并启用 cron 服务

安装完成后,启动 cron 服务并设置其开机自启:

1
2
sudo systemctl start cron
sudo systemctl enable cron
  1. 编辑 crontab 文件:
1
crontab -e
  1. crontab 中添加以下行,设置开机启动脚本:
1
@reboot /bin/bash /root/data/shell_script/monitor_jenkins_to_nginx.sh start

这行命令会在系统启动时自动执行脚本。

  1. 保存并退出编辑器。

方法 2: 使用 systemd 设置开机自启 (适用于现代 Linux 系统)

  1. 创建一个新的 systemd 服务文件,例如 monitor_jenkins_to_nginx.service

    1
    sudo nano /etc/systemd/system/monitor_jenkins_to_nginx.service
  2. 在服务文件中添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [Unit]
    Description=Monitor Jenkins to Nginx Script
    After=network.target

    [Service]
    Type=simple
    ExecStart=/bin/bash /root/data/shell_script/monitor_jenkins_to_nginx.sh start
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target

    这将使脚本在系统启动后运行,并确保网络启动完成后才运行该脚本。

  3. 保存文件并退出编辑器。

  4. 重新加载 systemd 配置:

    1
    sudo systemctl daemon-reload
  5. 启动服务并设置为开机启动:

    1
    2
    sudo systemctl start monitor_jenkins_to_nginx.service
    sudo systemctl enable monitor_jenkins_to_nginx.service

参考资料

从零开始搭建JENKINS+GITHUB持续集成环境

Docker Compose安装部署Jenkins

Jenkins修改显示语言为中文显示(亲测有效)_jenkins 中文-CSDN博客

Jenkins配置任务时无 send files execute commands over SSH

Docker + Jenkins + Nginx实现前端自动化部署