前言
背景
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_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,给个星星?
构建和启动
构建
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
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
成功之后,你的博客就可以通过域名访问了,并且带有小绿锁哦。
总结一下
这套方案有三解耦:云服务和Docker解耦,证书(在云服务上)和Docker解耦,HTML静态资源和Docker解耦(Githooks)。同时Nginx也无需手工配置。这套方案不仅可用于博客,只要是静态文件的部署,都能适用。
最后求个赞吧:Github,Docker Hub