在 coding.net 上部署 Jekyll 博客 (此方式已過時,coding 官方已直接支持 jekyll)

自從 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

1. 將 Jekyll 博客變爲一個在線運行的 Rack 程序

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 」就能夠看到博客了。

2. 添加用於 Coding 演示平臺的啓動腳本

上面第一步只是解決了 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 博客了。可是,若是有了新文章呢?怎麼自動在站點改動後從新生成站點?

3. 使用 Webhook 在 push 後自動從新生成站點內容

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 平臺上就不是件麻煩的事了。

其餘聯想

  1. Octopress 博客是在 jekyll 的基礎上封裝而來的更高級也更方便的靜態站點框架,因此按照上面的原理,將已有的 octopress 項目部署到 coding 平臺上,應該也不是件難事。

  2. Octopress 自己支持另一種部署方式,就是本地生成靜態站點以後,直接執行 rake deploy 將生成後的靜態站點 push 到指定的遠程 repo 或者指定的分支上,從這個角度考慮,其實也能夠爲 jekyll 實現相似的腳本,結合 coding 演示平臺的 靜態站點部署 ,就能夠直接部署 jekyll 博客了,這種方式就省去了 unicorn 服務器等的配置了,也不須要再使用 webhook 從新生成站點了,並且純靜態站點的方案的最大優勢就是,特別節約內存。這種方案只是構想,可是值得一試。若是哪位朋友嘗試成功了,請記得在評論裏回覆一下。

個人博客

segmentfault blog 裏邊的博文都拷貝自個人我的博客 ,若是須要及時查看個人最新文章,能夠移步個人博客查看。

相關文章
相關標籤/搜索