之前的 Hexo 和 WordPress 一直放在阿里云虚拟主机上,到期了,为了博客专门买个虚拟主机也不划算,部署在 Github 速度又不行,于是就打算用一种非常轻量的方式在服务器上部署,也能熟悉一下这些服务是如何使用的。

基本思路

  • 使用 docker 的 node 镜像创建容器初始化 Hexo
  • 本地编辑之后 push 到服务器触发 Githook
  • 使用 docker 的 alpine/node 镜像创建容器渲染静态页面
  • 使用 Nginx 完成网站部署

优点

  • 对于不写 javascript 的同学可以不用在服务器安装 node.js 环境
  • 一键部署
  • 仅占用少量服务器资源
  • 不用另外找地方放网站(我的主因)

缺点

配置麻烦,但折腾一通下来新技能又 get 了~

初始化 Hexo

docker 安装:https://www.runoob.com/docker/ubuntu-docker-install.html

docker 的容器随建随删十分方便,因此连初始化我都在容器里完成了。

首先 pull 一个 node.js 环境的镜像下来:

docker pull node

(这里不用 alpine 是因为它太简洁了,而初始化 Hexo 还需要一些其它依赖)

服务器创建一个 hexo 目录用于初始化:

mkdir ~/hexo

创建容器:

docker run --name hexo-init -v ~/hexo:/hexo -it -d node

--name 指定容器名称,方便管理

-v 将服务器路径挂载到容器内 服务器路径:容器内路径

-it 可以简单理解为保持容器运行状态,否则创建后就会退出

-d 后台创建容器

进入容器:

docker exec -it hexo-init /bin/bash

安装 Hexo:

npm install hexo-cli -g

初始化 hexo:

hexo init /hexo

exit 退出容器,然后停止、删除容器:

docker kill hexo-init && docker rm hexo-init

再看看 ~/hexo,已经 完成了初始化。

Nginx 的安装配置(Ubuntu)

# Ubuntu 安装依赖库
sudo apt-get install libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev zlib pcre openssl gcc

# 通过 wget 下载源码,http://nginx.org/en/download.html
wget http://nginx.org/download/nginx-1.16.1.tar.gz
tar -zxvf nginx-1.16.1.tar.gz
cd nginx-1.16.1

# 指定安装路径为 /usr/local/nginx
# 如果需要配置 SSL 证书的话添加 http_ssl_module 模块就够了
./configure --prefix=/usr/local/nginx \
    --with-http_ssl_module

# 编译
make

# 安装
sudo make install

# 建软连接
sudo ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/

参考:Ubuntu 编译安装 nginx

配置 nginx.conf 文件

vim /usr/local/nginx/conf/nginx.conf

该配置支持 https,并将 http 和带 www 的请求转到 https://brucegao.cn;域名我是在阿里云注册的,同时也在阿里云申请了免费的 SSL 证书。

    server {
        listen *:80;
        listen *:443 ssl;
        listen [::]:80;
        listen [::]:443 ssl;
        server_name www.brucegao.cn;

        # 将 https 证书的 .pem 和 .key 文件上传到服务器并填写路径
        ssl_certificate /path-to-pem/xxx.pem;
        ssl_certificate_key /path-to-key/xxx.key;
        return 301 https://brucegao.cn$request_uri;
    }

    server {
        listen *:80;
        listen [::]:80;
        server_name brucegao.cn;
        return 301 https://brucegao.cn$request_uri;
    }

    server {
        listen *:443 ssl;
        listen [::]:443 ssl;
        server_name brucegao.cn;

        # 将 https 证书的 .pem 和 .key 文件上传到服务器并填写路径
        ssl_certificate /path-to-pem/xxx.pem;
        ssl_certificate_key /path-to-key/xxx.key;
        location / {
                 # 将 public 文件夹(存放 Hexo 静态页面文件)作为网站根目录
                 root html/public;
                 index index.html;
        }
    }

创建 docker 容器用于每次更新后生成 Hexo 静态页面

镜像使用 mhart/alpine-node,只有 100M,是 node 镜像的十分之一:

docker pull mhart/alpine-node

编写 Dockerfile

vim Dockerfile

FROM mhart/alpine-node:latest
WORKDIR /hexo
RUN /bin/sh -c 'npm install hexo-cli -g'
CMD hexo -g

创建镜像

docker build -t hexo-g .

-t 指定镜像名称

. Dockerfile 在当前目录

创建容器,并让它每次执行 hexo -g 之后立即退出:

docker run --name --hexo-g -v ~/hexo:/hexo -d hexo-g

使用 Githook 触发自动部署

创建一个裸仓库:

git init --bare hexo-bare.git

重命名 post-update.sample 文件:

cp hexo-bare.git/hooks/post-update.sample hexo-bare.git/hooks/post-update

配置 post-update 脚本:

#!/bin/sh

unset GIT_DIR
DIR=/home/XXX/hexo
cd $DIR

git init
git remote add origin ~/hexo-bare.git
sudo rm -r public
git clean -df
git pull origin master

# 如果主题是作为子模块的话需要加上下面这句
git submodule update --init --recursive

docker start hexo-g
sleep 5

sudo rm -r /usr/local/nginx/html/public
sudo cp -r $DIR/public /usr/local/nginx/html/
sudo sudo nginx -s reload

添加执行权限:

chmod +x post-update

本地创建新仓库并添加 remote 源:

git init
git remote add origin ssh://user@1.2.3.4:22/home/USER/hexo-bare.git
git remote show origin  # 查看是否添加成功

将服务器上 ~/hexo 里的文件复制到本地仓库并推送(文件较多,建议打包传输后本地解压缩):

git push --set-upstream origin master

大功告成!

踩坑和总结

Docker 在 Win10 上的实践

最好的实践就是安装 Docker Desktop,然后在 WSL 安装客户端连接 Windows Docker,因为 WSL 是运行不了 Docker daemon 的。这样也好,Win10 上可以很方便地设置 Docker 不开机自启,Docker engine 内存占用还是挺高的,需要时再打开。

在 WSL 上装 Docker 的时候还发现了一个 Ubuntu Apt 的坑,如果 Apt 安装时报的错误是 Python 格式的,就要注意 python 命令的软连接是否是指向的 python3,因为 Ubuntu 和 Debian 默认的 python 都是 python2,有些系统脚本是用 python2 编写的:Unable to apt-get install packages E: Sub-process /usr/bin/dpkg returned an error code (1)

Chrome 报隐私设置错误

通过域名访问网站的时候有时正常,有时会出现隐私错误,错误代码是 ERR_CERT_COMMON_NAME_INVALID

很粗心,纠结了两三天,后来查看域名解析的时候才发现是因为之前解析到云虚拟主机 IP 的记录没有删掉。。理解错误代码也很重要,至少有个思考的方向了。

Comments