自从 coding 推出 PaaS 演示平台以及开放自定义域名以后,不少人开始尝试在 coding 上部署本身的博客,其中就有 jekyll,coding 上就有官方推荐的 jekyll-demo。可是由于这个 Demo 的 README 文档中只是简单介绍配置步骤而已,没有详细介绍原理以及灵活配置的地方,我在参照着迁移 jekyll 博客的过程当中也遇到一些问题。如今写下文章,但愿可以把原理理清楚。html
<!-- MORE -->git
声明:这篇文章主要是对原来的 Demo 的几个主要思路作一个补充说明,而并不是 coding 演示平台使用操做的详细教程,因此在有些细节上不必定覆盖到,建议最终的部署代码须要以官方推荐的 repo 里的代码为主。github
由于 Coding 提供的演示平台是通用的 PaaS 平台,并不是相似 Github 或者 Gitcafe 的 Pages 服务,因此 jekyll 部署到演示平台须要解决三个问题:web
1. 运行问题,blog 须要以常规 Web 程序的方式运行;
2. 启动脚本,部署完成后自动启动服务器;
3. 自动更新,blog 内容更新 push 后可以自动生成新的页面。json
第一个问题咱们能够经过 rack-jekyll 解决;第二个问题经过 Coding 约定的 Procfile
文件解决;第三个问题咱们经过 Coding 的 Webhook 结合脚本解决。segmentfault
Jekyll 本来是一个用于生成静态博客站点的框架,可是为了可以在 coding 演示平台上直接运行 Jekyll 博客,咱们须要一个可以在 Unicorn 服务器上运行 Jekyll 的方法。经过原来 coding 提供的 Demo,找到了一个叫 rack-jekyll 的工具。浏览器
rack-jekyll 主要的功能如其介绍:ruby
Transform your Jekyll app into Rack application!服务器
就是将 Jekyll 做为 Rack 程序运行。app
首先,为了可以使用 rack-jekyll 以及 unicorn,咱们在 Gemfile
文件(若是没有则直接新建便可)中加入:
gem "rack-jekyll" gem "unicorn"
这两行,而后执行 bundle install
这样,咱们的项目中就成功引入 rack-jekyll
以及 unicorn
了。
其次,由于 unicorn 默认会从项目根目录下的 config.ru
文件启动,再结合 rack-jekyll 的使用说明 ,咱们在 jekyll 项目根目录下要建立一个包含如下内容的文件,而且名字就是 config.ru
:
# config.ru require "rack/jekyll" run Rack::Jekyll.new
到此,能够在命令行中 cd 到当前项目根目录,执行 jekyll build
生成站点,而后再执行 unicorn
从默认配置启动服务器,成功启动后,在浏览器中访问“ http://127.0.0.1:8080 ”就能够看到博客了。
上面第一步只是解决了 Jekyll 可以以 Rack 方式运行的问题而已,可是为了部署到 coding 后,项目可以正常启动,咱们还须要加入启动命令。
按照 coding 在关于 Ruby 部分的演示平台文档 中的介绍得知,coding 会查找项目根目录下的 Procfile
文件,并将里边的内容做为启动命令,当此文件不存在时,则将默认使用一下启动命令:
web: bundle exec rackup config.ru -p $PORT
按照默认启动命令的格式,咱们也能够写出如下 Procfile
文件,用于部署后从 unicorn 启动项目:
web: bundle exec unicorn -p $PORT -c ./unicorn.rb
完成前面两步以后,将代码 push 到 coding 上,再从演示平台一键部署的话,就应该能够成功启动 unicorn 服务器,而且可以访问你的 jekyll 博客了。可是,若是有了新文章呢?怎么自动在站点改动后从新生成站点?
coding 为用户提供了 webhook 功能,方便用户在 push 代码改动后自动 POST 请求你指定的 Web URL,你能够利用这个 URL 在程序后台完成程序的自动部署等操做。更多的介绍跟使用方法请参考 "WebHook 的内容是什么?" 以及 "WebHook 是什么?我该如何使用?"。
为了增长新的入口以接收 coding 的 Webhook 通知,咱们能够在 config.ru
中添加新的路由,而且添加响应的处理脚本,这部分的内容我先直接拷贝官方推荐的 jekyll demo 的代码 后再作必要的解读:
# config.ru require "bundler/setup" Bundler.require(:default) WEBHOOK_TOKEN = ENV['WEBHOOK_TOKEN'] app = Proc.new do |env| request = Rack::Request.new(env) response = Rack::Response.new path_info = request.path_info if request.content_type =~ /application\/json/ params = JSON.parse(request.body.read) else params = request.params end if request.post? && params['token'] == WEBHOOK_TOKEN repo_url = params['repository']['url'] rescue nil if repo_url archive_url = "#{repo_url}/archive/master" puts "--> updating to #{params['ref']}.." puts `jekyll build` `rm -rf $HOME/_posts; curl -s -L -o $TMPDIR/archive.zip #{archive_url}; unzip -qo -d $HOME $TMPDIR/archive.zip; cd $HOME; jekyll build` puts "--> done." else STDERR.puts "--> error: no url field found in params: #{params}" end ['200', { 'Conetent-Type' => 'application/json;charset=utf-8' }, ['ok']] else ['403', { 'Conetent-Type' => 'application/json;charset=utf-8' }, [{ error: 'webhook token mismatch!' }.to_json]] end end jekyll = Rack::Jekyll.new(auto: true) run Rack::URLMap.new('/' => jekyll, '/_' => app)
首先,程序在启动时,指定了两个路由入口分别指向不一样的后台程序,其中 '/'
路径指向了咱们的 jekyll
程序,这个跟原来的配置目的一致;而 '/_'
路径指向了 app
这个程序。
因此,当有外部向服务器发送了一个指向 "/_" 路径(好比“ http://test.codingapp.com/_ ”)的请求时,服务器在内部启动了 app
的脚本。(注意,若是你但愿使用别的路径名来配置 webhook 的入口,只要将下划线改为你须要的路径便可,好比: "http://test.codingapp.com/deploy")。
app
脚本首先经过请求的 Content-Type
头信息判断请求格式,并据此从请求中提取请求参数赋给 params
变量;接着脚本验证请求的合法性,要求请求必须是 POST 方式,而且参数中的 token
参数的值必须与咱们在 coding 后台中配置的 token 一致。
最后,在确认请求的合法性后,脚本先清空了当前部署的项目,而后下载解压指定分支的最新代码,而且进入项目根目录($HOME
环境变量)从新执行了 jekyll build
命令以从新生成静态站点,见代码:
`rm -rf $HOME/_posts; curl -s -L -o $TMPDIR/archive.zip #{archive_url}; unzip -qo -d $HOME $TMPDIR/archive.zip; cd $HOME; jekyll build`
其中值得一提的是,archive_url
是在前面代码中拼接而来的连接:
archive_url = "#{repo_url}/archive/master"
请注意其中硬编码的部分 "archive/master"
,其中的 master
指定了是 master
分支上的代码压缩包的路径,因此假如你须要从 master 分支外的分支部署代码,请务必记得将 master
改成对应的分支名,好比个人部署分支是 coding-pages
,那我这里的代码就应该改成:
archive_url = "#{repo_url}/archive/coding-pages"
完成 webhook 处理脚本后,须要从新 push 代码而且从新在演示平台部署一次,以使 config.ru
文件里的代码生效。至于如何配置 webhook ,直接参照 coding 的官方文档便可。
以上的三点主要是对在 coding 上部署 jekyll 博客的关键思路的说明,经过这三点,相信你再去看原来的 README 的时候,应该就能很快理解为何须要配置 WEBHOOK_TOKEN
环境变量以及为何要配置 webhook 的 URL 为相似 "http://host/_" 这么奇怪的连接了吧?除此以外,你也能够根据你的须要将脚本中的代码分支从 master
改成你所须要的目标分支了。
其实用 unicorn 运行 jekyll 项目的原理仍是很是简单的,知道了这些以后,将你的已有 jekyll 项目直接迁移到 coding 甚至是其余 PaaS 平台上就不是件麻烦的事了。
Octopress 博客是在 jekyll 的基础上封装而来的更高级也更方便的静态站点框架,因此按照上面的原理,将已有的 octopress 项目部署到 coding 平台上,应该也不是件难事。
Octopress 自己支持另一种部署方式,就是本地生成静态站点以后,直接执行 rake deploy
将生成后的静态站点 push 到指定的远程 repo 或者指定的分支上,从这个角度考虑,其实也能够为 jekyll 实现相似的脚本,结合 coding 演示平台的 静态站点部署 ,就能够直接部署 jekyll 博客了,这种方式就省去了 unicorn 服务器等的配置了,也不须要再使用 webhook 从新生成站点了,并且纯静态站点的方案的最大优势就是,特别节约内存。这种方案只是构想,可是值得一试。若是哪位朋友尝试成功了,请记得在评论里回复一下。
segmentfault blog 里边的博文都拷贝自个人我的博客 ,若是须要及时查看个人最新文章,能够移步个人博客查看。