阅读 1596

吃灰的云主机不要忘,部署个人博客,隔壁开发都馋哭了

还记得,今年、前年或大前年,618、双11 租来吃灰的 xx云服务器 吗?
还记得,当初是怀揣着怎么的心情,从服务器供应商小心翼翼的接过它吗?
还记得,斥资几百租回来后,自己口口声声立下的海誓山盟吗?
而今多年过去,它在你身边过得还安好吗?

看到这里,相信部分读者 想起自己租的云服务器,扫码登录ing...

笔者大前年学Python爬虫,一口气搞了三个,主从服务器,弄分布式爬取,
玩了一下下,可惜工作中没有具体的业务场景,劲头过了就搁置了。
后面妹子要找工作,挑了一个,随手给她撸了个静态网站放放作品和简历,
然后就一直吃灰直到过期,现在就剩一个薅了5年的弱鸡服务器。

最近一些事情,让我再次有了一种置办自己个人博客的想法:

  • 1、平时写的文章大部分是面向读者,骚话、废话和表情有点多,而且比较零散, 自己 回顾和速查 的时候 效率低下,有时要翻上好几篇才能找到姿势点;
  • 2、平台的不可控性,比如Github,本来就慢,因为某些原因,间接性抽风;
    还有某些博客站点,时不时来个“因涉及xxx”,含辛茹苦写好的文章被下架无法访问;
  • 3、很多无脑搬运的直接照搬文章,改个标题就是自己的了,在推荐群学了个骚操作:

以上就是笔者置办个人博客的动机,尔后是技术选型:

  • 简洁:界面简洁,排版合理,不需要花里花哨;
  • 简单:上手简单,开箱即用,输出文章即可,无需过于关注实现细节;
  • :加载快,性能高效,移动端适配(地铁上也可以康康);

Gitbook、Hexo、WordPress等之前折腾过一下,各有优缺点,最后决定用尤大的 Vuepress
相关介绍自行移步至官网查阅:vuepress.docschina.org/,就不复制粘贴了。
网上大部分文章都是教如何把Vuepress部署到Github上,上面也说了不稳定,
部署到云服务器上也不难,就是build一下生成带样式的 静态网站,通过ftp传上去,
配置下Nginx,域名解析下即可。于是乎每次更新博客的流程:

本地修改 → 命令行build → ftp工具上传生成文件进行覆盖

可以是可以,就是有点繁琐,其实可以把build这一步放在服务器上,就不用ftp传了:

答:自动化构建 了解下?说到这个名词,第一反应是不是:Gitlab CI + jenkins, 但是小博客用他两太重了,官方推荐Gitlab服务器内存4G以上,Jenkins对配置要求也较高, 内存只有一个鸡的云服务器表示心有余而力不足。

酱紫,就得想想其他替代方案了,我把目光转向了国产Github → 码云Gitee,支持 WebHooks

em,要写一个API接口给它调,接口功能:拉取最新博客源代码 → 执行vuepress build构建命令 等。 一切准备就绪后的结果:我文章写完,git push一波,个人博客就自动更新了。妙啊! 另外,考虑到云服务器的硬盘只有50G,图片类资源文件就不丢上去了,直接用CDN~

本节就来手把手实践一波~


0x1、Vuepress 本地部署

① Node.js 安装配置

官网下载:nodejs.org/en/download…,傻瓜式下一步安装,完成后可配置
npm 安装的 全局模块 和 缓存cache的路径,不然全局安装的模块都会塞到:
C:\Users\用户名\AppData\Roaming\npm 中,占用C盘空间,可通过下述命令
修改为node.js的安装文件夹:

cd nodejs
    
# 创建文件夹 
mkdir node_global
mkdir node_cache

# 设置
npm config set prefix node_global
npm config set cache node_cache
    
# 配置下环境变量(路径根据自己的实际情况进行替换):
# 系统变量 => 新建 => NODE_PATH => 输入
D:\Coding\nodejs\node_global\node_modules

# 用户变量Path中删除:
C:\Program Files\nodejs\node_global

# 新增
D:\Coding\nodejs\node_global
复制代码

附:Node.js 及 npm 更新相关命令:

# 查看安装的node.js版本 
node -v 

# 清除cache
sudo npm cache clean -f

# 安装用于管理node.js版本的n工具
sudo npm install -g n

# 安装最新node.js
sudo n stable

# 查看版本号
npm -v  

# 更新最新版
npm install npm@latest -g.  
复制代码

Tips:深入了解npm可移步至:www.npmjs.cn/getting-sta…

② 快速搭建

走一波命令安装vuepress,以及创建相关文件

# 全局安装,执行一次即可
npm install -g vuepress

# 创建博客项目
mkdir Blog

# 项目初始化
npm init -y

# 添加主README.md文件
touch README.md

# 添加docs文件夹
mkdir docs

# docs文件夹中创建.vuepress文件夹
cd docs
mkdir .vuepress

# 新建总配置config.js文件
cd .vuepress
touch config.js

# dosc文件夹中创建README.md文件
cd ..
touch README.md
复制代码

此时目录结构比较简单:

D:\Blog
├── docs
|  ├── .vuepress
|  |  └── config.js
|  └── README.md
├── package-lock.json
├── package.json
└── README.md
复制代码

接着打开package.json添加运行脚本:

"scripts": {
    "dev": "vuepress dev docs",
    "build": "vuepress build docs"
}
复制代码

保存后,输入下述命令中的一个即可运行:

npm run dev
yarn run dev
复制代码

运行成功,可以看到控制台输出:

此时打开localhost:8080,即可看到效果。

③ 推荐的目录结构

VuePress 遵循 “约定优于配置” 的原则,推荐的目录结构如下(小改了一些~):

.
├── docs
│   ├── .vuepress (可选) → 存放全局配置、组件、静态资源等
│   │   ├── components (可选) → 该目录中的 Vue 组件将会被自动注册为全局组件
│   │   ├── theme (可选) → 存放本地主题
│   │   │   └── Layout.vue
│   │   ├── public (可选) → 静态资源目录
│   │   ├── styles (可选) → 存放样式相关的文件
│   │   │   ├── index.styl → 将会被自动应用的全局样式文件,会生成在最终的
│   │   │   │                CSS 文件结尾,具有比默认样式更高的优先级。
│   │   │   └── palette.styl → 重写默认颜色常量,或者设置新的 stylus 颜色常量
│   │   ├── templates (可选,谨慎配置,最好基于默认模板文件来修改) → 存储HTML模板文件
│   │   │   ├── dev.html → 用于开发环境的HTML模板文件
│   │   │   └── ssr.html → 重写默认颜色常量,或者设置新的 stylus 颜色常量    
│   │   ├── config.js → 全局配置文件
│   │   ├── enhanceApp.js → 客户端应用的增强
│   ├── guide (可选) → 一般会在此目录下创建网站指南
│   │   └── README.md
│   ├── study (举例)
│   │   └── study01.md
│   │   └── study02.md
│   ├── README.md → 博客首页
└── package.json → 项目启动配置
复制代码

④ 默认主题配置

此处只是做下简单配置,更详细的配置可移步至官方文档: www.vuepress.cn/theme/defau…

1)页面标题与图标

修改 → docs/.vuepress/config.js

module.exports = {
    title: 'CoderPig的小世界',  // 网站标题
    description: '吾日三省吾身',    // 网站描述  
    head: [
        // 网页标签图标,'/'指向docs/.vuepress/public 文件目录
        ['link', { rel: 'icon', href: '/img/favicon.ico' }]
    ],
    base: '/',// 设置站点根路径
    dest: './ROOT',  // 设置输出目录
    plugins: [],
}
复制代码

2) 设置封面页

修改 → docs/README.md

---
home: true
heroImage: /img/logo.png
heroText: CoderPig的小世界
tagline: 吾日三省吾身
actionText: Get Started →
actionLink: /zh/guide/
features:
- title: 待填充
  details: 待填充
- title: 待填充
  details: 待填充
- title: 待填充
  details: 待填充
footer: MIT Licensed | Copyright © 2018-present Evan You
---
复制代码

看下运行效果,很Nice!

//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/52dfe21bec7e4fc2bc2d0fa8c472af0e~tplv-k3u1fbpfcp-zoom-1.image

3) 添加导航栏nav

修改 → docs/.vuepress/config.js

themeConfig: {
    // 添加导航栏
    nav: [
        { text: '主页', link: '/' },
        { text: 'Android', 
            items: [
                {text: '源码', link: '/android/sourcecode/'},
                {text: '架构', link: '/android/architecture/'},
                {text: '逆向', link: '/android/hook/'}
            ]
        },
        { text: 'Github', link: 'https://github.com/coder-pig' },
        { text: '关于我', link: '/other/aboutme.md' },
    ],
}
复制代码

看下运行结果:

//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/359da043b9004eceafc6014c1140c675~tplv-k3u1fbpfcp-zoom-1.image

基础配置的示例就说这些,接着说下抽取配置,实现模块化。

⑤ 配置抽取

配置的东西全写在config.js中,后续随着博客文章数量及分类增多,维护起来不怎么方便。
可将对应的属性抽取出来,放到一个单独的js文件中,config.js中去引用,示例如下:

// head.js
module.exports =[
    ['link', { rel: 'icon', href: '/img/favicon.ico' }]
]

// nav.js
module.exports = [
    {
        text: '首页', link: '/'
    },
    {
        text: 'Python',
        items: [
            {text :'基础', link: '/python/base'},
            {text :'爬虫', link: '/'},
            {text :'Web', link: '/'},
            {text :'机器学习', link: '/'},
        ]
    },
]

// config.js中引用
const navConf = require('./config/nav')
const headConf = require('./config/head')

module.exports = {
    title: 'CoderPig的小世界',  // 网站标题
    description: '吾日三省吾身',    // 网站描述  
    dest: './ROOT',  // 设置输出目录
    plugins: [],
    head: headConf,
    themeConfig: {
        nav: navConf,
        sidebarDepth: 2,
        lastUpdated: 'Last Updated',
    }
}
复制代码

另外说下sidebar,有时可能会为某几个页面设置单独的侧边栏,比如:

可以单独设置一个sidebar,如:

// ptyhon-base/sidebar.js
module.exports = [
    {
        title: '开发环境搭建',
        sidebarDepth: 2,
        collapsable: true,
        children: ['1.1/', '1.2/', '1.3/']
    },
    {
        title: '概念常识',
        sidebarDepth: 2,
        collapsable: true,
        children: ['2.1/', '2.2/', '2.3/']
    },
    {
        title: '数据类型',
        sidebarDepth: 2,
        collapsable: true,
        children: ['3.1/', '3.2/', '3.3/', '3.4/']
    },
    {
        title: '条件判断与循环',
        sidebarDepth: 2,
        collapsable: true,
        children: ['1.1/', '1.2/']
    },
]
复制代码

然后config/slidebar.js引用一波:

module.exports = {
    '/python-base/': require('../../python-base/sidebar'),
}
复制代码

完美~

⑥ 生成静态文件

执行一波 vuepress build 即可,构建成功后,可以看到文件的存放目录:

此时如果你来到目录下打开index.html,会发现没有样式,控制台也一堆爆红

点开其中一个css:

明显的路径不对,可以修改config.js中的 base 属性,然后重新build一下, 不过笔者发现即使修改正确后,本地打开正常,然后会立马跳转404,目前无解, 有知道的朋友欢迎在评论区留言告知下,万分感激~

⑦ 添加.gitignore文件

然后是配置.gitignore文件,将一些不需要提交的文件忽略掉:

node_modules
dist
.idea
复制代码

本地部署相关的就折腾那么多,接着是部署到云服务器上。


0x2、Vuepress 部署到云服务器

相关工具:

  • 云服务器系统:CentOS 8
  • SSH终端:Windows terminal
  • FTP工具:WinSCP

① SSH 连接云服务器

# 回车输入密码 → 回车
ssh root@xxx.xxx.xxx.xxx
复制代码

② Nginx 安装

# 安装Nginx
sudo yum install nginx

# ↓ ↓ ↓ ↓ ↓ ↓ 其他常用命令 ↓ ↓ ↓ ↓ ↓ ↓ 

# 查看nginx运行状态
ps aux | grep nginx

# 重载nginx配置文件n
nginx -s reload 

# 立即停止nginx
nginx -s stop

# 优雅停止nginx
nginx -s quit

# 杀死所有nginx进程
killall nginx

# 启动nginx
systemctl start nginx.service

# 停止nginx服务
systemctl stop nginx.service

# 重启nginx服务
systemctl restart nginx.service

# ↓ ↓ ↓ ↓ ↓ ↓ 常用文件位置 ↓ ↓ ↓ ↓ ↓ ↓ 

# 查看nginx安装列表,可看到所有安装位置
rpm -ql nginx

/etc/nginx/nginx.conf       # nginx总配置文件
/etc/nginx/conf.d           # 所有的nginx自定义配置文件
/var/log/nginx/error.log    # 错误日志文件
/usr/share/nginx/html       # 服务器默认启动目录
复制代码

另外,CentOS 8内置FirewallD防火墙方案,需要配置运行nginx的 80(HTTP) 和 443(HTTPS) 端口通过:

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload
复制代码

浏览器输入主机公网ip,出现如下页面,代表Nginx安装成功。

③ Nginx 配置

接着把我们本地build生成的文件通过ftp工具上传到云服务器上,因为使用相对路径, build之前要修改下config.js文件,添加 base 属性:

build一波,然后上传一波,传哪里自己看自己喜好,笔者上传到下述路径中:

然后配置下nginx,来到 /etc/nginx/ 目录下,配置文件一般是 nginx.conf,不过考虑到 后续可能还要导几个项目,此处分一层,把配置写到单独一个文件中,放到 /conf.d 文件夹下。

文件内容如下:

server {
    listen 80;
    server_name xxx.xxx.xxx.xxx; // 主机IP
    location /{
        root /home/project/blog;
        index index.html index.htm index.nginx-debian.html;
        try_files $uri $uri/ =404;
    }
}
复制代码

然后 /conf.d 文件的http层级,添加:

include /etc/nginx/conf.d/*.conf;
复制代码

最后 nginx -s reload 重载下配置文件,此时在浏览器打开主机的公网IP:

啧啧啧,可以外网访问自己的博客了,接着弄自动化部署~

0x3、Vuepress 自动部署

码云Gitee 新建个仓库,把本地代码Push上去,基本常识不讲,不懂善用搜索引擎~ 开头说过,这个自动化部署的流程:

  • 1、提供一个接口,功能:自动拉取最新代码 → build生成文件 → 覆盖博客目录
  • 2、当我们Push代码,Gitee WebHook调用这个接口即可

① 编写脚本文件

我们把自动化操作写到一个脚本文件中,调用接口时执行这个sh脚本即可:

# 拉取远程分支
git pull origin master

# 生成静态文件
npm run build

# 把生成的静态文件 复制到 静态网站的目录下,存在则覆盖
\cp -rf docs/.vuepress/dist/. /home/project/blog
复制代码

SSH终端 bash xxx.sh 运行一波,看下是否有覆盖成功即可~

② 编写接口

脚本写完,写个接口来执行这个脚本,后台语言Java,Python、Go、PHP等都可以,会啥用啥。
笔者用的是Python Flask,相关API及详细用法可参见之前写的:
《偷个懒,公号抠腚早报80%自动化——3.Flask速成大法》, 此处仅做演示,故只是简单的写个接口~

CentOS 8 自带Python 3.6.8,就不用另外安装Python了,命令行:

cd /home/project
mkdir Api
cd Api
python3 -m venv venv
source venv/bin/activate
pip install flask 
pip install flask-script
vim app.py
复制代码

输入下述内容:

from flask_script import Manager
from flask import Flask
import os

app = Flask(__name__)

@app.route("/api/refresh_blog")
def refresh_blog():
    os.system("cd ../blog/;bash auto.sh")
    return "博客刷新成功!"


if __name__ == '__main__':
    app.run()
复制代码

按ESC,输入 :wq,保存即可,然后输入下述命令启动项目:

 python app.py runserver -p 12345
复制代码

再接着新开一个ssh终端链接云服务器,用curl命令看下接口能否正常调用:

curl http://127.0.0.1:12345/refresh_blog
复制代码

如果正常调用,终端可以看到vuepress打包的过程,最后输出:

③ 安装uwsgi

yum install uwsgi

# 如果安装报错:Command "/usr/bin/python3.6 -u -c "import setuptools, tokenize;
# 先安装一波python-devel,这里是python3.6版本,要用python36-devel

# 搜索python36-devel版本
yum search python36-devel
# 根据输出结果,如:python36-devel.x86_64 : Libraries and header files ..。

# 安装对应版本的python36-devel
yum install python36-devel.x86_64

# 此时再安装uwsgi就可以了~
复制代码

④ 编写uwsgi配置文件

在项目目录下创建一个配置文件

vim config.ini
复制代码

配置内容如下:

[uwsgi]
# 指明要启动的模块,前者为项目启动文件名去掉.py,后者为变量app,Flask的实例
module = app:app

# 处理器数
processes = 1

# 指向网站目录  
chdir = /home/project/Api

# uwsgi 启动时所使用的地址与端口
socket = 127.0.0.1:8005

# 日志输出目录
logto = /home/project/Api/history.log  

# 状态检测地址
stats = 127.0.0.1:12345 
复制代码

然后命令行启用即可:

uwsgi config.ini
复制代码

⑤ Nginx 配置

上面Vuepress部署时配过Nginx,没太大必要用两个域名,直接在原先基础上配置一个location即可,配置后的blog.conf

server {
    listen 80;
    server_name xx.xx.xx.xx;

    location /{
    root /home/project/blog;
    index index.html index.htm index.nginx-debian.html;
        try_files $uri $uri/ =404;
    }
    
    location /api/ {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8005;
    }
}
复制代码

保存后 nginx -s reload,重载下nginx,接着浏览器访问:主机IP/api/refresh_blog,没有出现404,静待片刻后,出现如下界面即可:

⑥ 域名解析

这个就很简单了,自己买个域名备案,然后打开域名管理页面,找到刚买的域名,点击 解析

点击 添加记录,出现如图所示对话框,记录值那里填写你的云服务器公网ip即可。

过10分钟左右就可以用你的域名访问我们的个人博客了~

⑦ Gitee配置WebHooks

点击项目 Settings → 找到点击 WebHooks → 点击 Add

我丢,竟然还要POST请求的,另外码云这里街口响应时间超过10s就会超时, 执行构建命令比较耗时,使用线程池来异步执行,修改后的代码如下:

import os
from concurrent.futures.thread import ThreadPoolExecutor
from flask import Flask

app = Flask(__name__)
executor = ThreadPoolExecutor(max_workers=2)


def auto_build():
    os.system("cd ../blog/;bash auto.sh")


@app.route("/api/refresh_blog", methods=['POST'])
def refresh_blog():
    executor.submit(auto_build)
    return "博客刷新成功!"


if __name__ == '__main__':
    app.run()
复制代码

然后Gitee上点击Test,可以看到接口响应结果:

最后打开blog项目,改点东西,然后Push一下,打开域名康到蕾姆酱:

大功告成~~~


结语

以上就是如何把Vuepress生成的静态网站部署到云服务器上的全过程实录, 实现手法比较 粗糙,后续肯定是会折腾下主题和其他乱七八糟的, 当然最重要的还是整理记录自己的姿势树,厚积薄发,温故知新,就酱,谢谢~