0%

Hexo博客部署的终极解决办法(云+域名+Https+Nginx镜像+Docker部署)

前言

背景

17年在大学用Hexo部署了第一个博客后,一直对Hexo个人博客进行改造升级。最开始是挂载在Github.io,后用Nginx迁移至自有域名chanchun.net,在后来启用了GitHooks让Hexo构建产物直接SSH推送至云,再后来通过letsencrypt 升级了Https。自从Oracle Cloud开放了免费实例后,一直想把博客服务迁移到免费的云上(无奈工作太忙,也怪搬瓦工服务器太难用)。那么与其从0开始迁移,还不如把一直以来的沉淀(Https、GitHooks、Nginx)也一起Docker化掉。方便以后继续迁移,也给自己想折腾博客的人一个我认为最终极的解决方案。

你需要准备什么

云基础配置

  • 买一个Niubility的域名(推荐国外域名注册商)
  • 买一个Niubility云服务实例(推荐国外云服务商)
  • 把你的域名DNS解析至你的云公网IP(生效时间预计从0-48小时不等)

Hexo游刃有余

  • 熟悉Hexo的基本操作,熟悉hexo init hexo new hexo clean hexo generate hexo server hexo deploy 等命令,并能启动Hexo服务构建出静态html,如果已经搭建过了简单的博客系统就更棒棒

Docker

  • 了解一下Docker基本操作docker build docker run 等等一系列操作

正题

思路

第一步,新建一个hexo-docker工程来构建Docker镜像(基于Nginx镜像),里面有且仅包含Dockerfile和初始Nginx配置。Dockerfile中描述了Githooks挂载地址,安装好了Certbot命令,并加入初始Nginx配置。

第二步,在云服务中直接Docker Run起构造好的镜像,进入镜像生成好letsencrypt证书,配置好远程SSH提供给Hexo Deploy。

第三步,配置好本地的Hexo代码,Hexo Deploy就能看到带绿锁的自有域名的博客了。

Show Code

Dockerfile

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
#基于Nginx镜像
FROM nginx:latest

#换国内的源,这里用网易源
RUN sed -i 's#http://deb.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list
RUN sed -i 's#http://security.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list

#更新Docker中的apt-get
RUN rm -Rf /var/lib/apt/lists/* && apt-get update

#安装Git,挂载Githooks钩子,并将产物放置在var/www/hexo中
RUN apt-get install -y git
RUN git init --bare ~/blogs.git
RUN mkdir -p /var/www/hexo
RUN echo "git --work-tree=/var/www/hexo --git-dir=/root/blogs.git checkout -f" >~/blogs.git/hooks/post-receive
RUN chmod a+x ~/blogs.git/hooks/post-receive

#SSH初始化
RUN apt-get install -y openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -y
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -y
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -y

#安装Certbot
RUN apt-get install -y certbot
RUN apt-get install -y python3-certbot-nginx

#初始化Nginx配置挂载,这里选择直接覆盖所有配置
ADD nginx/hexo.conf /etc/nginx/nginx.conf

#暴露22 SSH
#暴露80 HTTP
#暴露443 HTTPS
EXPOSE 22
EXPOSE 80
EXPOSE 443

Nginx配置

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
user nginx;
worker_processes auto;

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;

#include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name chanchun.net; #记得改成自己的域名

location / {
root /var/www/hexo; #要和刚刚的Githooks目录对应上
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}

我已经将代码上传到了Github,给个星星?

构建和启动

构建

1
docker build -t hexo-docker .

启动

这里要在云上Run了,如果在本机跑的化能跑起来但是没法继续搞证书了。至于怎么把构建好的镜像转移到云上呢?各位搞开源的Docker Hub也行,直接Copy也行。

注意这里使用了volume方案,为后续申请证书的挂载做准备

1
docker run -v $(pwd)/letsencrypt:/etc/letsencrypt -d -p 80:80 -p 443:443 -p 8004:22 hexo-docker

我已经将构建出的Docker镜像上传到了Docker Hub,给个星星?

配置证书

进入Docker Container

1
docker exec -it "[your_container_name]" /bin/bash

申请证书

我们在用Dockfile来构建的时候已经安装了Certbot,我们可以利用Certbot帮忙安装Https证书,同时Certbot会自动识别上文中配置的Nginx文件,加入证书验证和443端口开放。

1
certbot --nginx -d "[your_domain.com]"

这里就按照提示一步一步走就是了,最后见到congratulation!就能证明证书已经安装好了,因为我们在docker run 时采用了volume方案,生成出的证书会挂载到云服务的$(pwd)/letsencrypt目录下,并关联到Docker内部的/etc/letsencrypt目录 。这样能保证镜像中不带CA证书,解耦的同时也确保Docker在迁移的时候的安全性。

可以看到/etc/nginx/nginx.conf 已经加入了443端口和证书路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
server_name chanchun.net;

location / {
root /var/www/hexo;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/chanchun.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/chanchun.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

证书更新

1
/usr/bin/certbot renew

Letsencrypt 3个月就需要更新一次,很多人用自动更新任务来完成更新。我这边就不想用了,因为我觉得每个月收到提示邮件后上云更新一把是一件很愉快的事。如果你需要自动更新可以使用下面命令

1
echo "0 0 1 * * /usr/bin/certbot renew --quiet" >> /etc/crontabs/root

配置Hexo Deploy的SSH

还是在Docker镜像内操作,不需要离开Docker镜像内部。如果离开了看上述“进入Docker Container”命令。

依次执行下面的命令吧,注意your_ssh_public_key改成自己电脑上的公钥,在~/.ssh/xxx.pub 中。

1
mkdir ~/.ssh
1
echo "[your_ssh_public_key]" > ~/.ssh/authorized_keys
1
chmod 600 ~/.ssh/authorized_keys
1
chmod 700 ~/.ssh
1
mkdir /run/sshd
1
/usr/sbin/sshd

Hexo推送

恭喜你胜利在即,到这一步已经可以退出Docker镜像,并且退出云服务器了(有没有发现完全没改云服务器本身的配置,感叹Docker实在强大!)。接下来都是直接在本机操作。

更改Hexo _config.yml 配置

1
2
3
4
5
deploy:
type: git
repo: root@hexo-test:/root/blogs.git #Docker中8004端口作为SSH端口,但repo没法写端口号,写一个hexo-test作为config
branch: master

新增~/.ssh/config文件

~/.ssh/config中配置你的云服务公网ip,ssh端口即可(按照文章来就是8004)

1
2
3
Host hexo-test
HostName [your_remote_server_ip]
Port 8004

推送Hexo

1
hexo deploy

Success! 当hexo deploy 成功之后,你的博客就可以通过域名访问了,并且带有小绿锁哦。

chanchun.net

总结一下

这套方案有三解耦:云服务和Docker解耦,证书(在云服务上)和Docker解耦,HTML静态资源和Docker解耦(Githooks)。同时Nginx也无需手工配置。这套方案不仅可用于博客,只要是静态文件的部署,都能适用。

最后求个赞吧:GithubDocker Hub