新坑:Hugo 全自動(dòng)部署

前些日子的 Hexo 自動(dòng)化構(gòu)建折騰起來真心有趣,但是速度好慢窒所,幾十篇文章從構(gòu)建到壓縮處理需要等待至少好幾秒的時(shí)間鲸拥,構(gòu)建時(shí)內(nèi)存占用也很高,雖然只是一時(shí)但就是讓人興致大減掉分。

所以肯定得換構(gòu)建引擎俭缓,然后就是 Hugo 了,Go 語言編寫酥郭,速度沒得說华坦,問題是擴(kuò)展功能不多,所以今天可是折騰了一天不从,笑惜姐。

實(shí)現(xiàn)效果:

  • 本地保存即時(shí)全自動(dòng)發(fā)布。

自動(dòng)化流程:

  • 本地編輯器保存,webdav (或者其他你喜歡的方式)服務(wù)自動(dòng)上傳服務(wù)器歹袁。
  • 服務(wù)器監(jiān)測(cè)到有文件上傳坷衍,啟動(dòng)圖片壓縮程序,自動(dòng)壓縮圖片条舔。
  • 圖片壓縮之后枫耳,啟動(dòng) Hugo 構(gòu)建頁面。
  • Hugo 構(gòu)建結(jié)束孟抗,啟動(dòng) Gulp 壓縮網(wǎng)頁資源文件迁杨。
  • 構(gòu)建任務(wù)結(jié)束,推送到所有服務(wù)器夸浅。
  • 最后由各個(gè)節(jié)點(diǎn)的 Nginx 服務(wù)器向外展示網(wǎng)站仑最。

為什么沒有部署到 Github?也沒有上傳圖片到 CDN帆喇?

  1. 因?yàn)?Github 不支持綁定域名的站點(diǎn)使用 HTTPS 訪問;
  2. 我服務(wù)器多亿胸,自動(dòng)同步坯钦,普通 CDN 太慢。

為了簡(jiǎn)化初次部署的繁瑣侈玄,以上操作只需要一行命令即可啟動(dòng)婉刀。在此之前還是先解釋一下整個(gè)流程的原理。

一共兩個(gè)鏡像:

REPOSITORY                 SIZE
zuolan/hugo                19.3 MB
zuolan/hugo:minify         79.73 MB

1. 自動(dòng)上傳服務(wù)器

這一步通過 Nextcloud 實(shí)現(xiàn)序仙,我日常就是用這種私有云盤突颊,所以這一步我跳過,如果你需要實(shí)現(xiàn)自動(dòng)上傳潘悼,可以考慮其他方法律秃。比如 scp、rsync 之類的治唤,Windows 下自動(dòng)同步的工具更是數(shù)不盡啦棒动。

2. 主鏡像:zuolan/hugo

整合功能包括:

2.1. 服務(wù)器監(jiān)測(cè)到有文件上傳

這一步的工具就是 inotifywait 了,已經(jīng)整合到容器中宾添,當(dāng)數(shù)據(jù)卷有變動(dòng)就會(huì)觸發(fā)一系列動(dòng)作船惨。

2.2. 圖片壓縮程序

就是一個(gè)腳本,自動(dòng)壓縮圖片缕陕,使用的是 TinyPNG 的服務(wù)粱锐,雖然 Linux 有不少圖片處理程序,但是壓縮算法不好扛邑,這里使用的在線壓縮服務(wù)非常不錯(cuò)怜浅,這個(gè)功能也已經(jīng)整合到容器中。

因?yàn)槭窃?sh 中執(zhí)行的腳本鹿榜,平時(shí)在 bash 和 zsh 養(yǎng)成的習(xí)慣寫法在 sh 中不一定有效海雪,所以暫時(shí)先把這部分的腳本寫死放進(jìn)了容器中锦爵,等明天完善了再把這部分代碼丟上來。

2.3. Hugo 構(gòu)建頁面

這個(gè)作為整個(gè)流程最關(guān)鍵的一步奥裸,近百篇文章耗時(shí)也只有幾十毫秒险掀。

構(gòu)建一般不會(huì)出錯(cuò),但是如何觸發(fā)下一步壓縮網(wǎng)頁文件就是讓我折騰了一天的關(guān)鍵點(diǎn)湾宙。

劃重點(diǎn)時(shí)間

如何觸發(fā)下一步壓縮構(gòu)建好的網(wǎng)頁文件呢樟氢?

首先想到的就是使用前端打包工具執(zhí)行,但是一個(gè) Node.js 環(huán)境就會(huì)使我的主鏡像體積翻了一番侠鳄,這點(diǎn)不能忍埠啃,我要努力把主鏡像壓縮到僅有 6 MB 的存儲(chǔ)體積。

所以把 Hugo 和 Gulp 放一塊是不可能的伟恶,畢竟不是每個(gè)人需要壓縮功能碴开。

所以就想到了在容器中運(yùn)行容器,但是需要在容器中裝 Docker 環(huán)境博秫,鏡像體積必然破百 MB潦牛,而且每次容器重啟還得重新拉壓縮鏡像,太二挡育,所以不予考慮巴碗。

那,就使用 docker-compose 吧即寒,通過掛載 docker.sock 與宿主機(jī)通信橡淆,避免了上面的問題,試了一下母赵,只有 22 MB逸爵,還能接受。

但是額外加一個(gè) docker-compose 還是讓我不舒服市咽,我要做到盡可能小的體積痊银,所以,我選擇 curl施绎。

直接對(duì)著 unix socket 來操作溯革。

2.3.1. 在容器中啟動(dòng)容器

API 文檔地址:https://docs.docker.com/engine/api/v1.26/

API 返回的是 json 格式,本來用 jq 可以搞定的谷醉,迅速取到相應(yīng)的值致稀,但是不想裝額外的軟件包,所以強(qiáng)行使用 cut 把結(jié)果剪切出來了俱尼,好粗暴抖单,笑。

ID=$(curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "zuolan/hugo:minify", "Volumes": {"/hugo/public":"/work/html"}}' -X POST http:/v1.26/containers/create | cut -d: -f2 | cut -d, -f1 | cut -d\" -f2)
curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/start
curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/wait
curl --unix-socket /var/run/docker.sock "http:/v1.26/containers/$ID/logs?stdout=1"
curl --unix-socket /var/run/docker.sock -X DELETE http:/v1.26/containers/$ID

2.3.2. 主鏡像源代碼

run.sh

#!/bin/sh
SEPARATOR="================================================================"
echo "正在執(zhí)行初次構(gòu)建:"
echo $SEPARATOR
echo "正在構(gòu)建頁面:"
hugo
echo "正在壓縮網(wǎng)頁資源:"
ID=$(curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "zuolan/hugo:minify", "Volumes": {"/hugo/public":"/work/html"}}' -X POST http:/v1.26/containers/create | cut -d: -f2 | cut -d, -f1 | cut -d\" -f2)
curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/start
curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/wait
curl --unix-socket /var/run/docker.sock "http:/v1.26/containers/$ID/logs?stdout=1"
curl --unix-socket /var/run/docker.sock -X DELETE http:/v1.26/containers/$ID
echo "頁面已經(jīng)發(fā)布,容器進(jìn)入監(jiān)視狀態(tài)矛绘。"
VOLUMES="/hugo"
INOTIFY_EVENTS="create,delete,modify,move"
INOTIFY_OPTONS="--monitor --exclude=public"
inotifywait -rqe ${INOTIFY_EVENTS} ${INOTIFY_OPTONS} ${VOLUMES} | \
    while read -r notifies;
    do
        echo $SEPARATOR
        echo "文件有變動(dòng):"
        echo "$notifies"
        echo "正在重新構(gòu)建頁面:"
        hugo
        ID=$(curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "zuolan/hugo:minify", "Volumes": {"/hugo/public":"/work/html"}}' -X POST http:/v1.26/containers/create | cut -d: -f2 | cut -d, -f1 | cut -d\" -f2)
        curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/start
        curl --unix-socket /var/run/docker.sock -X POST http:/v1.26/containers/$ID/wait
        curl --unix-socket /var/run/docker.sock "http:/v1.26/containers/$ID/logs?stdout=1"
        curl --unix-socket /var/run/docker.sock -X DELETE http:/v1.26/containers/$ID
        echo "新的頁面構(gòu)建完成耍休。"
        echo $SEPARATOR
    done

Dockerfile

FROM alpine
WORKDIR /hugo
ENV GIT_USER=izuolan GIT_EMAIL=i@zuolan.me
COPY run.sh /run.sh
RUN apk add --no-cache inotify-tools hugo curl && \
    chmod a+x /run.sh
VOLUME ["/hugo"]
CMD ["/run.sh"]

3. 壓縮網(wǎng)頁文件

因?yàn)?Hugo 是使用 Go 語言寫的,在網(wǎng)頁處理上缺少相應(yīng)的功能货矮,所以為了壓縮網(wǎng)頁羊精,這里使用 Gulp 來自動(dòng)化壓縮網(wǎng)頁。

比較遺憾的是我不知道 Gulp 有哪些可以實(shí)現(xiàn) replace (替換 link)效果的插件(類似的插件)囚玫,所以沒能實(shí)現(xiàn)把外聯(lián)式資源喧锦、圖片嵌入網(wǎng)頁的功能。哪位大佬知道請(qǐng)告知~注意是不能修改 HTML 的情況下實(shí)現(xiàn)抓督。如果修改了主題文件就不能適用于他人了燃少。

3.1. Gulp 壓縮網(wǎng)頁資源文件

某一次的自動(dòng)壓縮過程:

$ docker-compose logs -f
Attaching to hugo, minify, blog
hugo      | 正在執(zhí)行初次構(gòu)建:
hugo      | ================================================================
hugo      | 正在構(gòu)建并部署頁面:
hugo      | Started building sites ...
hugo      | Built site for language en:
hugo      | 0 draft content
hugo      | 0 future content
hugo      | 0 expired content
hugo      | 6 regular pages created
hugo      | 16 other pages created
hugo      | 0 non-page files copied
hugo      | 14 paginator pages created
hugo      | 7 tags created
hugo      | 5 categories created
hugo      | total in 584 ms
hugo      | 頁面已經(jīng)發(fā)布,容器進(jìn)入監(jiān)視狀態(tài)铃在。
minify    | 正在執(zhí)行資源文件壓縮:
minify    | ================================================================
minify    | 
minify    | > @ build /work
minify    | > gulp build
minify    | 
minify    | [12:50:26] Requiring external module babel-register
minify    | [12:50:28] Using gulpfile /work/gulpfile.babel.js
minify    | [12:50:28] Starting 'build'...
minify    | [12:50:28] Starting 'minify-html'...
minify    | [12:50:29] Finished 'minify-html' after 1.43 s
minify    | [12:50:29] Starting 'minify-js'...
minify    | [12:50:32] Finished 'minify-js' after 2.33 s
minify    | [12:50:32] Finished 'build' after 3.77 s
minify    | 頁面已經(jīng)壓縮阵具,容器進(jìn)入監(jiān)視狀態(tài)。

3.1.1. 壓縮鏡像源代碼

Dockerfile

FROM mhart/alpine-node
WORKDIR /work
COPY . /work
RUN mkdir /work/html && \
    npm install
VOLUME ["/work/html"]
CMD ["npm", "run", "build"]

gulpfile.babel.js

import gulp from 'gulp'
import htmlmin from 'gulp-htmlmin'
import uglify from 'gulp-uglify'
import runSequence from 'run-sequence'

gulp.task('minify-html', () => {
  return gulp.src('html/**/*.html')
    .pipe(htmlmin({
      collapseWhitespace: true,
      minifyCSS: true,
      minifyJS: true,
      removeComments: true,
      useShortDoctype: true,
    }))
    .pipe(gulp.dest('./html'))
})

gulp.task('minify-js', () => {
    return gulp.src('./html/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./html'));
});

gulp.task('build', (callback) => {
  runSequence('minify-html','minify-js', callback)
})

package.json

{
  "private": true,
  "scripts": {
    "build": "gulp build"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.5.0",
    "babel-register": "^6.5.2",
    "gulp": "^3.9.1",
    "gulp-cli": "^1.2.1",
    "gulp-htmlmin": "^1.3.0",
    "gulp-uglify": "^2.0.0",
    "run-sequence": "^1.1.5"
  },
  "babel": {
    "presets": [
      "es2015"
    ]
  }
}

3.2. 推送到所有服務(wù)器

這個(gè)就各顯神通了定铜,文件都有怔昨,自己看著辦。

不知不覺寫到 23 點(diǎn) 49 分宿稀,怎么使用就留到明天吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赖捌,一起剝皮案震驚了整個(gè)濱河市祝沸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌越庇,老刑警劉巖罩锐,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異卤唉,居然都是意外死亡涩惑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門桑驱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竭恬,“玉大人,你說我怎么就攤上這事熬的∪叮” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵押框,是天一觀的道長(zhǎng)岔绸。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么盒揉? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任晋被,我火速辦了婚禮,結(jié)果婚禮上刚盈,老公的妹妹穿的比我還像新娘羡洛。我一直安慰自己,他們只是感情好扁掸,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布翘县。 她就那樣靜靜地躺著,像睡著了一般谴分。 火紅的嫁衣襯著肌膚如雪锈麸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天牺蹄,我揣著相機(jī)與錄音忘伞,去河邊找鬼。 笑死沙兰,一個(gè)胖子當(dāng)著我的面吹牛氓奈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鼎天,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼舀奶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了斋射?” 一聲冷哼從身側(cè)響起育勺,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罗岖,沒想到半個(gè)月后涧至,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桑包,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年南蓬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哑了。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赘方,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垒手,到底是詐尸還是另有隱情蒜焊,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布科贬,位于F島的核電站泳梆,受9級(jí)特大地震影響鳖悠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜优妙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一乘综、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧套硼,春花似錦卡辰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雾鬼,卻和暖如春萌朱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背策菜。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工晶疼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人又憨。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓翠霍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親蠢莺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寒匙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Docker — 云時(shí)代的程序分發(fā)方式 要說最近一年云計(jì)算業(yè)界有什么大事件?Google Compute Engi...
    ahohoho閱讀 15,547評(píng)論 15 147
  • 在現(xiàn)在的前端開發(fā)中躏将,前后端分離蒋情、模塊化開發(fā)、版本控制耸携、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,449評(píng)論 1 32
  • 0. 前言 docker是什么辕翰?docker是用GO語言開發(fā)的應(yīng)用容器引擎夺衍,基于容器化,沙箱機(jī)制的應(yīng)用部署技術(shù)喜命」瞪常可...
    sessionboy閱讀 3,862評(píng)論 2 49
  • 轉(zhuǎn)載自 http://blog.opskumu.com/docker.html 一、Docker 簡(jiǎn)介 Docke...
    極客圈閱讀 10,510評(píng)論 0 120
  • 二進(jìn)制和八進(jìn)制二進(jìn)制以 0b(0B)開頭八進(jìn)制以0o(0O)開頭 轉(zhuǎn)換成十進(jìn)制 檢查數(shù)值是否為有限或者為空 解析整...
    _by_w_z閱讀 655評(píng)論 0 1