利用Docker进行静态博客自动化部署
我需要的是更高的性能,更加灵活,更容易维护。
就像汽车一样,网站同样需要在性能 可维护性上让人们不断的权衡。生成内容发布给需要的人,是一个网站的主旨之一。一方面,随着科技的发展,越来越多的静态内容发布技术普及的很快,像Jekyll,它们给人们带来了新的体验,但是这不意味着使用这些静态发布系统就没有问题。很高的学习成本和复杂的操作流程,也是一件很恼人的事情。
另一方面,像wordpress这样的灵活的 基于数据库的网站内容管理系统也在不断的改进,提供更多更方便的内容管理方式,当然它们可能性能不佳,且有时候使用起来性能调优比较麻烦。
最后我还是在不断的寻找我的网站的最佳选择。目前有很多理由推荐使用 Jekyll静态模板方法。我喜欢人们可以使用github来进行交流和代码提交。我也看中静态文件在nginx下的优势。我是使用Octopress的,由于我是一个Ruby的小白,所以经常会出现一些问题,我要不断的从github上来回更新,再用rake生成我的网站页面发布出去,这些都是小问题当时让我很懊恼,我多么想有一种方式能够保证我的网站和github上的代码是同步更新的。
多说一句,github在在线markdown编辑器真的很不错,我再也不用担心需要一次写完一整篇文章,因为我可以随时随地的保存,然后随时继续
游戏开始
我们要做些什么?我常常在想通过一些自动化系统,能够直接将Docker hub和我的网站发布挂钩。每当我重新编译或部署网站内容的时候,系统就会以异步的方式完成整个发布流程,我什么都不用做,只要专注于写作。这种技术将适用于所有静态流程式发布的网站生成器方案。
下面就是我要做的:
- 建立一个
Dockerfile
生成一个包含静态网站生成器的image - 建立一个可以自动构建流程,链接Docker Hub和Github,能够执行重新编译。
- 使用Docker Hub的web Hooks发出 Post请求给监听器,执行发布流程。
第一步: 建立一个 Dockerfile
为你的静态网站生成器
下面是我的Octopress的Dockerfile:
from debian:wheezy
run apt-get update && \
apt-get install -y curl build-essential
run apt-get install -y ruby1.9.3
run apt-get install -y lsb-release && \
curl -sL https://deb.nodesource.com/setup | bash
run apt-get install -y nodejs npm
run apt-get install -y nginx
run gem install bundler
add Gemfile /blog/Gemfile
workdir /blog
run bundle install -j8
add . /blog
run rake install['pageburner'] && rake generate
run rm /etc/nginx/sites-available/default
add nginx/nathanleclaire.com /etc/nginx/sites-available/nathanleclaire.com
run ln -s /etc/nginx/sites-available/nathanleclaire.com /etc/nginx/sites-enabled/nathanleclaire.com
run echo "daemon off;" >>/etc/nginx/nginx.conf
expose 80
cmd ["service", "nginx", "start"]
显然Jekyll是依赖Nodejs的。(注意:这里Dockerfile中的命令小写是因为 作者个人爱好,并不推荐)
Dockerfile很酷因为Bundle install 在Gemfile不发生改变前是一直缓存的。 所以在执行 docker build
建立镜像包括 rake generate
生成静态的时候,都是速度很快的。
Octopress最好的支持是 Ruby 1.9.3, 我很运行的找到了一个Debian的软件包能够提供。这些静态文件的访问服务被运行在容器中的nginx控制着,nginx监听80端口,这样的配置对我来说够用了。实际上,我的nginx服务只是设置了关于gzip和header的一些设置,我喜欢针对不同的网站做定制化的配置。
server {
server_name nathanleclaire.com;
location / {
proxy_pass http://localhost:8000;
}
location /hubhook {
proxy_pass https://localhost:3000;
}
}
The /hubhook
is some proxy-matic goodness, which farms out the task to re-deploy the site to a simple but effective “Docker Hub Listener” worker that my colleague Brian Goff originally wrote (and which I twisted to my own nefarious purposes, muahaha). Okay, on to the next steps.
第二步:在Docker Hub上设置自动构建源
这一步十分关键,是否能够实现自动化部署的关键所在。当你的在github上的代码分支发生变化的时候(提交,合并或其他的操作),会触发一个自动重建image的过程。这就是新发布的内容被异步构建而我却什么都不需要再做,打开网站就可以看到最新的内容。当然这同样适用了Bitbucket。
这种实现主要利用了hook机制。
第三步: 发送到监听器触发重新部署
下面是一个基于go语言编写的webhook服务,还支持ssl加密
地址:
可以通过下面的脚本生成相应的key和csr
#!/bin/bash
openssl genrsa -des3 -out server.key 1024 && \
openssl req -new -key server.key -out server.csr && \
cp server.key server.key.org && \
openssl rsa -in server.key.org -out server.key && \
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
将生成好的key配置到config.ini:
[apiKeys]
key = bigLongRandomApiKeyString
[tls]
key = ../server.key
cert = ../server.crt
最后编写一个接受到通知,执行重新部署的脚本:
#!/bin/bash
sudo docker pull nathanleclaire/octoblog:latest
docker kill blog
docker rm blog
docker run --name blog -d -p 8000:80 nathanleclaire/octoblog
go代码看起来就是这样
func reloadHandler(msg HubMessage) {
log.Println("received message to reload ...")
out, err := exec.Command("../reload.sh").Output()
if err != nil {
log.Println("ERROR EXECUTING COMMAND IN RELOAD HANDLER!!")
log.Println(err)
return
}
log.Println("output of reload.sh is", string(out))
}
下面就可以自己去试试了
其实真实步骤是这样:
- 提交到github
- Docker hub重建image
- Docker Hub (在这一步的时候获取最新的代码)
- 重新发布image容器,并启动 一切就开始运行了
总结
老外的这个做法,思路很好,利用hook