“平常心” 网站部署日志

选购服务器

建议选择轻量应用服务器,它性价比高,适合部署小网站

采购完服务器之后,使用 SSH 连接登陆服务器,请根据你选择的操作系统进行登录,这里我选择的是 ubuntu

ssh ubuntu@100.100.100.100

另外,可以将 PC(个人电脑)的公钥上传到服务器,下次连接就不用再输入密钥啦

ssh-copy-id ubuntu@100.100.100.100

然后为 ubuntu 服务器创建生成密钥(后续从 Github 拉取私有仓库会用到)

ssh-keygen -t rsa -C "ubuntu@me.com"

执行成功之后,公钥会存放在 ~/.ssh/id_rsa.pub

安装 Git

yum install git -y

安装 Node

这里我使用的是 nvm,它是 Node 的版本管理器

# 云服务器在中国大陆境内,
# 所以使用 Gitee 上面的镜像安装速度比较快
curl -o- https://gitee.com/RubyMetric/nvm-cn/raw/main/install.sh | bash

# 安装 Node 16
nvm install 16

# 切换 Node 为16版本
nvm use 16

# 安装 CNPM
npm install cnpm -g --registry=https://registry.npmmirror.com

安装 Hexo

cnpm install hexo-cli -g

至此,云服务器准备就绪

部署网站服务

这里使用 nginx 的方式进行部署,你也可以使用 Docker 的方式

安装并启动 nginx

sudo apt install nginx -y

# 启动 nginx
sudo systemctl start nginx
# 检查运行状态
sudo systemctl status nginx

浏览器访问 100.100.100.100:80,如果显示 nginx 的默认欢迎页,那么 nginx 就准备就绪啦


编译网站静态页面


打开 nginx 的配置文件 /etc/nginx/sites-available/default

server {
	listen 80 default_server;
	listen [::]:80 default_server;

	# SSL configuration
	#
	# listen 443 ssl default_server;
	# listen [::]:443 ssl default_server;
	#
	# Note: You should disable gzip for SSL traffic.
	# See: https://bugs.debian.org/773332
	#
	# Read up on ssl_ciphers to ensure a secure configuration.
	# See: https://bugs.debian.org/765782
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	# include snippets/snakeoil.conf;

	root /var/www/html;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name _;

	location / {
		try_files $uri $uri/ =404;
	}
}

选购域名

域名部分有 3 个步骤:

  1. 购买域名
  2. 域名 ICP 备案(因为在境内,这步最麻烦~😭)
  3. 解析到主机

第 1 和第 2 步直接跟云服务供应商的链路走就可以了,这里主要说说第 3 步解析到主机

在域名解析(DNS)中,A 记录 和 CNAME 记录 是最常见的两种记录类型,它们的主要区别如下:

  • A 记录:绑定到 IP 地址
  • CNAME 记录:绑定到另一个域名

如果你的服务器 IP 不变,使用 A 记录 更快;如果你的 IP 可能变动,或者使用 CDN/云服务,CNAME 更灵活

配置 SSL

Nginx 服务器 SSL 证书安装部署

腾讯云 SSL 证书

docker container cp shxo:/etc/nginx ~/pingcx

获取 nginx.conf 文件

scp /path/to/local/file.txt user@remote_host:/path/to/remote/directory/

启动容器

docker run -d -p 80:80 -p 443:443 --name shxo \
	-v /usr/local/docker/nginx/conf:/etc/nginx \
	-v /usr/local/docker/nginx/logs:/var/log/nginx \
	-v /usr/local/docker/nginx/html:/usr/share/nginx/html \
	nginx

Nginx default.conf 证书路径的写法,参考这篇文章

对象存储 COS

购买标准存储容量包 和 外网下行流量包

创建公有读私有写的存储桶

防盗链设置

开启防盗链白名单,设置 Refer 头为网站域名

图片处理

COS 对象存储——基础图片处理

购买流量资源包和请求资源包

流量资源包用于支付从 COS 下载数据时的外网流量费用,例如你通过 GET 请求从 COS 下载一个 5MB 的图片文件,将会消耗流量资源包中的 5MB 流量

请求资源包用于支付对 COS 发起的操作请求次数,例如你对 COS 发起了一个 GET 请求,下载某个文件,不论文件大小,每个请求都需要消耗一个请求次数

请求资源包适合高频次小文件操作或 API 调用的场景,流量资源包适合大文件下载或数据传输的场景。

CDN

内容分发网络开启您的加速服务

购买流量包和 HTTPS 请求包

流量包用于支付通过 CDN 网络传输的流量,例如下载 1GB 的大文件会从流量包中扣除 1GB 的流量。

HTTPS 请求包用于支付通过 CDN 进行的 HTTPS 请求次数。例如,发起 1000 次 HTTPS 请求会从 HTTPS 请求包中扣除 1000 次请求次数。

HTTPS 服务按请求数收费的原因:
1、SSL/TLS 证书的加密和解密成本
2、证书管理和安全性

CDN 工作原理简单说明

使用 Makefile 治理你的服务

在云主机上创建脚本 blog_auto_deploy.sh,该脚本主要做的是重新部署上传的网站目录。在终端执行 chmod +x pingcx_auto_deploy.sh 赋予文件执行权限

#!/bin/bash

logFile="/root/scripts/pingcx.log"
readyFile="/root/pingcx/ready.txt"
monitoredFolder="/root/pingcx"
targetFolder="/usr/local/docker/nginx/html"
recordFile="/root/scripts/last_updated_at.txt"

echo "$(date +"%Y-%m-%d %H:%M:%S") - 🤖 开始始执行网站同步任务" >> "$logFile"

if [[ ! -f "$readyFile" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ready文件未就绪不存在" >> "$logFile"
    exit 1
fi
status=$(echo "$(cat "$readyFile")" | sed '/^\s*$/d')
if [[ "$status" != "ready" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - 读取ready文件状态失败, val:$status" >> "$logFile"
    exit 1
fi

if [[ ! -d "$monitoredFolder" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - 目录不存在" >> "$logFile"
    echo "目录不存在"
    exit 1
fi

touch "$recordFile"

lastUpdatedAt=$(cat "$recordFile")

currentUpdatedAt=$(stat -c %Y "$monitoredFolder")

if [ "$currentUpdatedAt" != "$lastUpdatedAt" ]; then
    rm -rf "$targetFolder"
    mv "$monitoredFolder" "$targetFolder"
    cp -r "$monitoredFolder" /tmp/

    # 重启服务
    docker rm -f shxo
    docker run -d -p 80:80 -p 443:443 --name shxo \
	-v /usr/local/docker/nginx/conf:/etc/nginx \
	-v /usr/local/docker/nginx/logs:/var/log/nginx \
	-v /usr/local/docker/nginx/html:/usr/share/nginx/html \
	nginx

    echo "$currentUpdatedAt" > "$recordFile"
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ✅更新成功" >> "$logFile"
else
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ❌不用更新 " >> "$logFFile"
fi

然后将这个脚本配置到 crontab 任务,执行频率为每分钟一次。执行 crontab -e 打开定时任务配置文件,然后加入下面的代码即可

* * * * * /root/scripts/blog_auto_deploy.sh

每次编辑完文章之后,在终端执行 make remote,将网站目录编译并上传到云主机

.PHONY: remote
remote:
	# 编译页面
	hexo clean
	hexo g
	# 上传到云主机
	scp -r /Users/luca/dev/shxo2/public root@81.69.245.17:~/pingcx
	# 标记同步为已就绪状态
	echo "ready" | ssh root@81.69.245.17 "cat > ~/pingcx/ready.txt"

脚本监测到上传目录,网站就会开始自动化构建

其它

nginx 版本脚本

#!/bin/bash

logFile="/home/ubuntu/scripts/pingcx.log"
readyFile="/home/ubuntu/pingcx/ready.txt"
monitoredFolder="/home/ubuntu/pingcx"
targetFolder="/var/www/html"
recordFile="/home/ubuntu/scripts/last_updated_at.txt"

echo "$(date +"%Y-%m-%d %H:%M:%S") - 🤖 开始始执行网站同步任务" >> "$logFile"

if [[ ! -f "$readyFile" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ready文件未就绪不存在" >> "$logFile"
    exit 1
fi
status=$(echo "$(cat "$readyFile")" | sed '/^\s*$/d')
if [[ "$status" != "ready" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - 读取ready文件状态失败, val:$status" >> "$logFile"
    exit 1
fi

if [[ ! -d "$monitoredFolder" ]]; then
    echo "$(date +"%Y-%m-%d %H:%M:%S") - 目录不存在" >> "$logFile"
    echo "目录不存在"
    exit 1
fi

touch "$recordFile"

lastUpdatedAt=$(cat "$recordFile")

currentUpdatedAt=$(stat -c %Y "$monitoredFolder")

if [ "$currentUpdatedAt" != "$lastUpdatedAt" ]; then
    rm -rf "$targetFolder"
    mv "$monitoredFolder" "$targetFolder"

    echo "$currentUpdatedAt" > "$recordFile"
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ✅更新成功" >> "$logFile"
else
    echo "$(date +"%Y-%m-%d %H:%M:%S") - ❌不用更新 " >> "$logFile"
fi