從訂製 Ghost 鏡像聊聊優化 Dockerfile

  • 2020 年 3 月 13 日
  • 筆記

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)

本文作者: 蘇洋

創建時間: 2020年03月09日 統計字數: 6225字 閱讀時間: 13分鐘閱讀 本文鏈接: https://soulteary.com/2020/03/09/optimize-dockerfile-from-custom-ghost-image.html


從訂製 Ghost 鏡像聊聊優化 Dockerfile

在《修理 Ghost 中文輸入法的 BUG》一文中,通過給源碼打修補程式,並進行編譯的方式,我們解決了 Ghost 的「陳年固疾」:不能正常輸入中文。

兩個月過去了,Ghost 開啟了雞血模式,不講道理的更新了若干版本,從當時的 3.3.0 飆升至 3.9.0,考慮到項目中有依賴 Ghost,需要持續的更新維護,那麼就在這裡分享一下,如何更好的折騰它。

寫在前面

在GitHub 的倉庫中,我們可以看到,解決這個 Bug 需要兩步走:

  • 對管理後台的前端實現程式碼進行修補程式,並重新構建
  • 對管理後台的伺服器端渲染模版進行更新

而在使用和維護上,必須考慮以下幾點:

  • 修補程式內容是否會影響現有邏輯
  • 是否可以不干擾用戶使用官方鏡像
  • 是否可以儘可能少/不編碼,實現鏡像的維護更新
  • 用於構建修正過前端功能的工具鏡像性能能否更高

由於 Ghost 服務端腳本/模版不需要構建使用,我們以修改處理比較「麻煩」的 Ghost 前端資源為例,講講如何優化 Dockerfile。

優化構建鏡像

在程式碼倉庫中,我們可以看到 Dockerfile 的內容是這樣編寫的:

FROM node:12-alpine  LABEL maintainer="[email protected]"    ENV LANG en_US.UTF-8  ENV LANGUAGE en_US.UTF-8  ENV LC_ALL=en_US.UTF-8    RUN echo '' > /etc/apk/repositories &&       echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.10/main"         >> /etc/apk/repositories &&       echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.10/community"    >> /etc/apk/repositories &&       echo "Asia/Shanghai" > /etc/timezone    RUN apk update && apk add git &&       yarn global add knex-migrator grunt-cli ember-cli bower    COPY patches/mobiledoc-kit/event-manager.js /patches/mobiledoc-kit/event-manager.js    RUN git clone https://github.com/TryGhost/mobiledoc-kit.git /mobiledoc-kit &&       cd /mobiledoc-kit &&       git checkout 3b0f375d32f7183a4eee9cce5373ebabeb249165 &&       cp /patches/mobiledoc-kit/event-manager.js /mobiledoc-kit/src/js/editor/event-manager.js &&       yarn &&       cp -r /mobiledoc-kit/dist /patches/mobiledoc-kit/dist &&       rm -rf /mobiledoc-kit    RUN git clone --recurse-submodules https://github.com/TryGhost/Ghost.git /Ghost &&       cd /Ghost &&       git checkout 3.3.0 &&       yarn setup    RUN rm -rf /Ghost/core/client/node_modules/@tryghost/mobiledoc-kit/dist &&       cp -r /patches/mobiledoc-kit/dist /Ghost/core/client/node_modules/@tryghost/mobiledoc-kit/    WORKDIR /Ghost    RUN grunt prod    EXPOSE 2368    CMD ["npm", "start"]

這裡存在幾個問題:

  1. 「程式碼版本」被硬編碼到了 Dockerfile 中,不利於 mobiledoc-kitGhost 程式碼升級管理。
  2. 對 Ghost 進行完整數據獲取,是沒有必要的。
  3. 我們不確定是否能夠繼續對目標文件打修補程式。

明確需要解決的問題之後,解決問題就容易多了。

解決硬編碼的問題

我們首先需要將「版本」定義為變數,然後抽象出來,考慮到不希望未來每次程式碼升級都需要修改 Dockerfile,我們可以使用 它的 ARG 指令,對於原始內容進行優化,例如:

# FOR GHOST 3.9.0  ARG MOBILEDOC_KIT_VERSION=v0.11.1-ghost.4  RUN git clone https://github.com/TryGhost/mobiledoc-kit.git /mobiledoc-kit &&       cd /mobiledoc-kit &&       git checkout $MOBILEDOC_KIT_VERSION &&       cp /patches/mobiledoc-kit/event-manager.js /mobiledoc-kit/src/js/editor/event-manager.js &&       yarn &&       cp -r /mobiledoc-kit/dist /patches/mobiledoc-kit/dist &&       rm -rf /mobiledoc-kit

未來如果 Ghost 發布 4.0.0,這個依賴的組件也有了版本變化,那麼在構建的時候只需要添加構建參數,即可完成新版本鏡像的構建,而不用在修改 Dockerfile,像是這樣:

docker build --build-arg MOBILEDOC_KIT_VERSION=v0.11.1-ghost.5

只獲取必要的程式碼

原始的 Dockerfile 中,我們獲取 Ghost 源碼將其整個倉庫都下載下來,在網路條件不好的時候,非常影響構建。

所以可以通過限定 depth 克隆深度,以及 branch 下載分支,限定要獲取的程式碼量,只下有用的內容。

ARG GHOST_RELEASE_VERSION=3.9.0  RUN git clone --recurse-submodules https://github.com/TryGhost/Ghost.git --depth=1 --branch=$GHOST_RELEASE_VERSION /Ghost &&       cd /Ghost &&       yarn setup

判斷是否能夠對當前文件打修補程式

可以判斷的方法很多,但是最簡單的自動化方案莫過於判斷程式碼文件是否被修改過。

先使用 shasum 或者任何你用的順手的計算工具,對目標要進行修補程式的文件進行校驗值計算,如果你使用的鏡像的基礎系統是 Ubuntu 可以使用下面的方式進行校驗:

# 計算校驗值  shasum -a 256 path_to_project/event-manager.js    0faeb4eb1cd177f3d7972fda6c52a0089a4814171cedd5c43a7302f027b26723  path_to_project/event-manager.js    # 進行校驗  echo "0faeb4eb1cd177f3d7972fda6c52a0089a4814171cedd5c43a7302f027b26723  path_to_project/event-manager.js" | shasum -a 256 -c

這裡使用 Alpine 發行版作為系統的容器,在不安裝額外軟體的情況下,可以換為 md5sum 來進行計算,原來的 Dockerfile 可以更新成下面這樣:

# FOR GHOST 3.9.0  ARG MOBILEDOC_KIT_VERSION=v0.11.1-ghost.4  ARG EVENT_MANAGER_HASH=9a0456060f1c816a0a66bdcf3363e928  RUN git clone https://github.com/TryGhost/mobiledoc-kit.git /mobiledoc-kit &&       cd /mobiledoc-kit &&       git checkout $MOBILEDOC_KIT_VERSION &&       (echo "$EVENT_MANAGER_HASH  /mobiledoc-kit/src/js/editor/event-manager.js" | md5sum -c -s -) &&       cp /patches/mobiledoc-kit/event-manager.js /mobiledoc-kit/src/js/editor/event-manager.js &&       yarn &&       cp -r /mobiledoc-kit/dist /patches/mobiledoc-kit/dist &&       rm -rf /mobiledoc-kit

如果校驗值和我們傳遞的不一致,構建會自動中斷,如果發生這個狀況,那麼理論來說我們需要調整修補程式邏輯,並計算出新的文件的校驗值。

完整的鏡像文件

為了方便有相同需求的同學,這裡給出完整的鏡像文件,相關程式碼也已經上傳 GitHub。

FROM node:12-alpine  LABEL maintainer="[email protected]"    ENV LANG en_US.UTF-8  ENV LANGUAGE en_US.UTF-8  ENV LC_ALL=en_US.UTF-8    RUN echo '' > /etc/apk/repositories &&       echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.10/main"         >> /etc/apk/repositories &&       echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.10/community"    >> /etc/apk/repositories &&       echo "Asia/Shanghai" > /etc/timezone    RUN apk update && apk add git &&       yarn global add knex-migrator grunt-cli ember-cli bower    COPY patches/mobiledoc-kit/event-manager.js /patches/mobiledoc-kit/event-manager.js    ARG GHOST_RELEASE_VERSION=3.9.0  RUN git clone --recurse-submodules https://github.com/TryGhost/Ghost.git --depth=1 --branch=$GHOST_RELEASE_VERSION /Ghost &&       cd /Ghost &&       yarn setup    # FOR GHOST 3.9.0  ARG MOBILEDOC_KIT_VERSION=v0.11.1-ghost.4  ARG EVENT_MANAGER_HASH=9a0456060f1c816a0a66bdcf3363e928  RUN git clone https://github.com/TryGhost/mobiledoc-kit.git /mobiledoc-kit &&       cd /mobiledoc-kit &&       git checkout $MOBILEDOC_KIT_VERSION &&       (echo "$EVENT_MANAGER_HASH  /mobiledoc-kit/src/js/editor/event-manager.js" | md5sum -c -s -) &&       cp /patches/mobiledoc-kit/event-manager.js /mobiledoc-kit/src/js/editor/event-manager.js &&       yarn &&       cp -r /mobiledoc-kit/dist /patches/mobiledoc-kit/dist &&       rm -rf /mobiledoc-kit    RUN rm -rf /Ghost/core/client/node_modules/@tryghost/mobiledoc-kit/dist &&       cp -r /patches/mobiledoc-kit/dist /Ghost/core/client/node_modules/@tryghost/mobiledoc-kit/    WORKDIR /Ghost    RUN grunt prod    EXPOSE 2368    CMD ["npm", "start"]

其他

處理軟體的版本更新,多多少少需要做一些簡單的分析,下面這些在線鏈接或許可以幫到你(以這次處理 3.9.0 為例):

  • 確認新舊版本差異:https://github.com/TryGhost/Ghost/compare/3.3.0…3.9.0
    • 老版本需要放在前面,不然按照時間線,是一定對比不出內容的。
  • 確認新版本引用子模組版本:https://github.com/TryGhost/Ghost/tree/3.9.0/core
    • Ghost 的管理後台、主題使用子模組方式引入,需要單獨檢查並確認引用。
    • 也可以 Clone 到本地,檢查 .submodule 文件,不過需要兩個步驟操作,略顯麻煩。
  • 確認新版本的子模組依賴內容:https://github.com/TryGhost/Ghost-Admin/blob/3.9.0/package.json
    • 檢查是否還存在 @tryghost/mobiledoc-kit 依賴,並確認其版本。
  • 確認編輯器組件模版:https://github.com/TryGhost/mobiledoc-kit/compare/v0.11.1-ghost.4…3b0f375d32f7183a4eee9cce5373ebabeb249165
    • 確認模組是有效的,並且查看是否有比較大的邏輯變更。

最後

下一篇 Ghost 相關的內容,或許會聊聊怎麼在容器中使用阿里雲(oss)/騰訊雲(cos)對象儲存,以及如何搭配 SSO 單點登錄使用 Ghost。