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
#基于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配置
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_nopushon; keepalive_timeout 65; #gzipon; #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,给个星星?
构建和启动
构建
docker build -t hexo-docker .

启动 这里要在云上Run了,如果在本机跑的化能跑起来但是没法继续搞证书了。至于怎么把构建好的镜像转移到云上呢?各位搞开源的Docker Hub也行,直接Copy也行。
注意这里使用了volume方案,为后续申请证书的挂载做准备
docker run -v $(pwd)/letsencrypt:/etc/letsencrypt -d -p 80:80 -p 443:443 -p 8004:22 hexo-docker

我已经将构建出的Docker镜像上传到了 Docker Hub,给个星星?
配置证书
进入Docker Container
docker exec -it "[your_container_name]" /bin/bash

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

这里就按照提示一步一步走就是了,最后见到congratulation!就能证明证书已经安装好了,因为我们在docker run 时采用了volume方案,生成出的证书会挂载到云服务的$(pwd)/letsencrypt目录下,并关联到Docker内部的/etc/letsencrypt目录 。这样能保证镜像中不带CA证书,解耦的同时也确保Docker在迁移的时候的安全性。
可以看到/etc/nginx/nginx.conf 已经加入了443端口和证书路径。
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}

证书更新
/usr/bin/certbot renew

【Hexo博客部署的终极解决办法(云+域名+Https+Nginx镜像+Docker部署)】Letsencrypt 3个月就需要更新一次,很多人用自动更新任务来完成更新。我这边就不想用了,因为我觉得每个月收到提示邮件后上云更新一把是一件很愉快的事。如果你需要自动更新可以使用下面命令
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 中。
mkdir ~/.ssh

echo "[your_ssh_public_key]" > ~/.ssh/authorized_keys

chmod 600 ~/.ssh/authorized_keys

chmod 700 ~/.ssh

mkdir /run/sshd

/usr/sbin/sshd

Hexo推送
恭喜你胜利在即,到这一步已经可以退出Docker镜像,并且退出云服务器了(有没有发现完全没改云服务器本身的配置,感叹Docker实在强大!)。接下来都是直接在本机操作。
更改Hexo _config.yml 配置
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)
Host hexo-test HostName [your_remote_server_ip] Port 8004

推送Hexo
hexo deploy

Success! 当hexo deploy 成功之后,你的博客就可以通过域名访问了,并且带有小绿锁哦。
Hexo博客部署的终极解决办法(云+域名+Https+Nginx镜像+Docker部署)
文章图片

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

    推荐阅读