--- title: Survey|Source-To-Image date: 2023-02-16 is_modified: false disqus: cynthiahackmd image: https://i.imgur.com/ZVTUloI.png categories: - "資訊科技 › 開發與輔助工具" tags: - "Docker" - "工具安裝與部署" - "工具介紹與操作" --- {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 過年大掃除,又掃出一篇之前 Survey 過且寫到一半的草稿 XDDD 這應該是去年(2021)年 12 月份筆記,我這次只是把筆記整理到能見人的程度,如果後續有更新,麻煩告知我一下,我有空再來看看 ~~(雖然很有可能會一直沒空下去)~~ 這篇的 Servey 目標是玩玩 S2I,順便看看 ==Openshift 利用 S2I 提供了哪些 image builder 相關功能==。 <!--more--> <p class="illustration"> <img src="https://i.imgur.com/ZVTUloI.png" alt="openshift/source-to-image"> openshift/source-to-image(圖片來源: <a href="https://github.com/openshift/source-to-image">GitHub</a>) </p> ## Overview 雖然我習慣使用 Dockerfile 從頭構建一個 image。但若你的應用不複雜,則可以考慮下 Image Builder 這些更快捷的方法。Image Builder 通常可藉由指定基礎 image 及提供要安裝工具、函式庫與自定義程式...等,為使用者提供客製化 image。 ### Source-To-Image,S2I Source-To-Image(S2I),就是套由 **OpenShift** 所提供的 Image Builder Framework,它可以將你的程式碼編譯後,注入 Builder Image 中以產生新的 image。 這樣的開發方式,是為了方便軟體開發人員對程式碼進行改動,他們毋需了解 Dockerfile 的撰寫與構建,只需要專注在軟體的開發即可, ~~(當然還要學會用 S2I)~~。其工作流程如下: <p class="illustration"> <img src="https://imgur.com/dE1zcpi.png" alt="S2I Developer Workflow"> S2I Developer Workflow(圖片來源: <a href="https://cloud.redhat.com/blog/source-image-s2i-deep-dive-ben-parees-openshift-commons-briefing-43">Red Hat Blog</a>) </p> SI2 是套相當便捷的工具,也是 OpenShift 生態系中相當重要的一個工具。我在網路上看到一個[論點](https://www.jianshu.com/p/c06b8ec92ed3),他認為 ==OpenShift 之所以能區別於 K8S 成為一個 PaaS 平台,其中一個主要環節就是 SI2==。透過這套工具,在使用時僅需提供程式碼,就能生成 image,並利用 OpenShift 現有的體系架構(Deployment config,DC 和 Build config,BC)直接部署,完成所有的應用的生命週期管理。 ### Pros S2I 除可以讓開發者關注程式碼本身外,亦有以下好處: - **關注點分離 SoC** 這點有點贅述了,它的意思就是程式碼和 Docker image 是清楚的分離開的,簡而言之就是讓==開發者關注程式碼本身==,不過我覺得這小標看起來很厲害的樣子,所以我還是再貼了一次 XDDD - **速度 Speed** 這可以想像,依照前面所說的,不需要從 Dockerfile 從頭 build 起,改利用現有 image 的話確實會比較快。 是說我有個疑問,我習慣把程式碼的部份放在 Dockerfile 的最後面,好像也就重 build 最後一層?這樣的話,重 build 最後一層跟編譯注入程式碼會是哪個快? :thinking_face: 嗯...好像少算了寫 Dockerfile 的時間,算了這先別管它好了。 - **可修補性 Patchability** 如果 Builder Image 基於安全問題需要修補,可以協助不斷 rebuild 應用的 image。 - **操作安全性 Operational Safety** 這優點在 PaaS 平台上比較能展現。透過 S2I 進而對構建 image 的過程進行限制,可以避免意外或故意濫用構建系統。 <br><br> 此外,讓使用者直接用 Dockerfile 構建 image,可能主機系統暴露於 root 特權提升的風險中,透過 S2I 限制可以 root 使用者的操作。 - **使用者效率 User efficiency** 其實這跟上一條有點像,不過這是從使用者的角度出發。它可以阻止使用者員在應用構建期間執行任意的 yum 安裝類型操作,避免過度安裝太多的套件導致 image 太過肥大,拖慢開發迭代的效率。 - **生態性 Ecosystem** 鼓勵共享 image 的生態系統,找到並利用最佳實踐的方式來為應用構建映像檔。 上面我直接當搬運工,直接從這篇 [〈OpenShift Container Platform 4.4 构建(build)〉](https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.4/pdf/builds/OpenShift_Container_Platform-4.4-Builds-zh-CN.pdf) 搬過來的 XDDD ## Required Image Contents <p class="illustration"> <img src="https://i.imgur.com/TeduiMV.png" height="450px" alt="S2I Developer Workflow"> S2I Developer Workflow(圖片來源: <a href="https://cloudpak.info/openshift/что-такое-source-2-image/4811">Cloudpak Service</a>) </p> 在 S2I 中,image 的建構主要是由**三個元素**互動所構成,分別是:==builder image、s2i scripts、source code==。 ### Builder Image 就是拿來當基底的 image,我在 [Software Collections](https://github.com/sclorg?q=s2i&type=all&language=&sort=) 有找到一些支援 S2I framework 的 image,它是有含 Pyhton 的 container 啦,不過像是我們比較常用的 Jupyter、 Tensorfolw、 Pytorch 之類好像都沒有,所以還要來研究下怎麼自定義 S2I framework image。 <br class="br"> [研究](https://github.com/openshift/source-to-image/blob/master/examples/nginx-centos7/README.md)了下,感覺自定義 S2I framework image 不難,只是必須包含特定文件,也就是我們的第二個元素 **s2i scripts**: | File | Required? | Description | |------------------------|-----------|--------------------------------------------------------------| | Dockerfile | **Yes** | Defines the base builder image | | s2i/bin/assemble | **Yes** | Script that builds the application | | s2i/bin/usage | No | Script that prints the usage of the builder | | s2i/bin/run | **Yes** | Script that runs the application | | s2i/bin/save-artifacts | No | Script for incremental builds that saves the built artifacts | | test/run | No | Test script for the builder image | | test/test-app | No | Test application source code | 這些[結構](https://github.com/openshift/source-to-image/blob/master/docs/cli.md#sti-create)不用特別去記憶,可以直接用相對應的指令產生目錄結構: ```bash= $ s2i create <imageName> <destination> [flags] ``` 其中 `<imageName>` 就是 image 的名字,`<destination>` 則是要產生目錄的資料夾名稱。詳細的狀況稍後等我們實際玩指令時再來試試。 ### S2I Scripts 焦點在回到前面提到的 s2i scripts。在前述的表格中,除了 Dockerfile 外還有幾項必備的文件就都是屬於 s2i scripts: - **[Required] assemble** 它會涉及原始碼的編譯、構建。我們會建立一個 assemble scripts 來 build 我們的程式,如:build modules、 bundle install gems、設置應用程式 configuration...之類的。 <br><br> 預設情況下,build 時程式碼會放在 `/tmp/s2i/src` 下,你可依照需求搬移至指定位置。你也可以透過 `io.openshift.s2i.destination label`,或傳入 `--destination` 參數修改。 - **[Required] run** 生成的最終 image 將以這個 script 作為容器的啟動命令。 - **[Optional] usage** 印出協助資訊,以告知使用者 image 的用法,我理解就是我們平常看到 `--help` 所看到的資訊。 - **[Optional] save-artifacts** 為了實現增量構建,在構建過程中會執行此腳本保存中間構建產物,以節省時間。(待會再詳細介紹) ### Source Code Source code 顧名思義就是我們要放入 image 中的原始碼。原始碼的來源已有二: 1. **遠端 Git Repository** 你可以從遠端的 Git Repository 抓取原始碼來構建映像檔,甚至可以從指定 repo 中的特定資料夾來建構映像檔。 2. **本地端** 另一個可以取得原始碼的方法就是從本地端啦 XDDD ### Build Flow 大概知道三個元素在構建過程中所扮演的角色後,我們可以來綜觀整個構建過程。 S2I 會將 sources 和 scripts 壓成 tar,並將其放入 builder image 中。在執行 assemble scripts 之前,S2I 會將壓縮檔解壓放並置指定位置,然後執行 S2I。完整的構建流程如下: <p class="illustration"> <img src="https://i.imgur.com/RIbvZ6i.png" alt="Build Workflow"> Build Workflow(圖片來源: <a href="https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md">GitHub|source-to-image</a>) </p> 其中會按照下面的順序與位置搜索 scripts : 1. at the `--scripts-url` URL 2. in the application source `.s2i/bin` directory(`/usr/libexec/s2i`) 3. at the default image URL(`io.openshift.s2i.scripts-url` label) 並以下列形式提供位置資訊: 1. image 內的絕對路徑:`image://path_to_scripts_dir` 2. 主機上的相對或絕對路徑:`file://path_to_scripts_dir` 3. URL:`http(s)://path_to_scripts_dir` <br class="big"> 換個較簡單的方法來表示,基本上將 copying、 assemble 與 run 這三個步驟,對應回 Dockerfile 中,可以比較清楚這三個步驟對應的的執行時間。 <p class="illustration"> <img src="https://i.imgur.com/pZrbq3x.png" alt="Build Workflow"> </p> ### Save Artifacts 不過像這樣的建構方式,一旦稍有有變動相依性就被打破,導致 assemble script 中相關安裝必須重來。 所以為了使用增量,我們需傳遞 `--incremental=true` 參數,並提供一個已構建好的 image 作為 cash,以獲取中間產物: ```bash= $ ./s2i build <source code> <Builder Image> <New Image> --incremental=true ``` <br class="big"> 引入增量後,流程會變成這樣: <p class="illustration"> <img src="https://i.imgur.com/ieSfMSA.png" alt="Build Workflow"> </p> ## Installation and Operation 好了,還是來看看怎麼使用這套軟體吧。 ### Installation 首先,當然必須先將它安裝起來 XDDD 1. **安裝 s2i** 首先先建立一個資料夾,並目前目錄切換置資料夾: ```bash= $ mkdir s2i $ cd s2i ``` 前往 [releases 頁面](https://github.com/openshift/source-to-image/releases),挑選合適的發行版本並解壓縮: ```bash= $ wget https://github.com/openshift/source-to-image/releases/download/v1.3.1/source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz $ tar zxvf source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz ``` <br class="big"> 解壓完成後,會多出兩個資料夾 `sti` 與 `s2i`: ```bash= $ ls s2i source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz sti ``` 將其中的 s2i 添加到 PATH 環境變數中,或移動到 PATH 的目錄中: ```bash= $ cp s2i /usr/local/bin $ ./s2i version s2i v1.3.1 ``` ### Operation 我們從自定義 S2I builder image 開始,並以 builder image 為底構建新的 image。 #### 自定義 S2I builder image 1. **建立一個 builder image** 前面提過不用特別去[記 builder image 的結構](https://github.com/openshift/source-to-image/blob/master/docs/cli.md#sti-create),可以直接用相指令產生目錄結構: ```bash= $ s2i create <imageName> <destination> [flags] ``` <br class="big"> 實際試試指令的執行效果,將 `<imageName>` 命名為 test-imag、要產生的目錄資料夾 `<destination>` 則命名為 test-image-content: ```bash= $ ./s2i create test-image test-image-content ``` 建立目錄後,可以切進目錄以觀察目錄結構。基本上與先前介紹過得相呼應(廢話 XDDD): ```bash= $ cd test-image-content/ $ tree . ├── Dockerfile ├── Makefile ├── README.md ├── s2i │ └── bin │ ├── assemble │ ├── run │ ├── save-artifacts │ └── usage └── test ├── run └── test-app └── index.html 4 directories, 9 files ``` 2. **修改 Dockerfile** 這邊開始撰寫所需要 Dockerfile。在這份文件中會有許多提示,依照這些提示填入需要的安裝。 3. **修改 assemble / run** - 建立一個 assemble,主要是配置文件和靜態內容複製到目標容器中。 不過這邊我沒做 XDDD - 再稍微修改下 run ```bash= exec ./app.sh ``` 4. **建立 base image** ```bash= $ docker build -t test-image-base test-image-content/. ``` #### 構建 app image 1. **撰寫個人程式** ```bash= $ mkdir myproject $ echo "echo 'Hello Word' " > myproject/app.sh ``` 6. **構建 app image** ```bash= $ s2i build myproject/ test-image-base hello-world-app ``` 如果順利,就會做出新的 image。但若你的 builder image 不符合 s2i 架構,在構建 app image 時就會出現錯誤訊息: ```bash= warning: Image sha256:37e4715d22fd3c00d8b51379e9e0eb556e842d4796d4c582fd4ff814e3d55edd does not contain a value for the io.openshift.s2i.scripts-url label Build failed ERROR: An error occurred: failed to install [assemble run] ERROR: Suggested solution: set the scripts URL parameter with the location of the S2I scripts, or check if the image has the "io.openshift.s2i.scripts-url" label set ERROR: If the problem persists consult the docs at https://github.com/openshift/source-to-image/tree/master/docs. Eventually reach us on freenode #openshift or file an issue at https://github.com/openshift/source-to-image/issues providing us with a log from your build using log output level 3. ``` <br class="big"> 是說,我這邊偷懶用了比較簡單的例子。另外這邊有一個範例演示如何構建包含 Nginx 服務的 image builder: - [〈自定义 S2I 模板〉](https://kubesphere.io/zh/docs/v3.3/project-user-guide/image-builder/s2i-templates/) - [〈Openshift S2I構建流程〉](https://www.twblogs.net/a/5c4c35cebd9eee6e7e06f186) #### 從 Git Repository 抓取原始碼 之前說過除了從本地端抓取原始碼外,也可以從遠端抓取原始碼。 1. 從遠端 Git Repository 抓取原始碼來構建 image ```bash= $ s2i build <git-repo> <S2I Builder Image Repository> <imageName> ``` 2. 或是從指定 repo 中的特定資料夾抓取原始碼 ```bash= $ s2i build <git-repo> --context-dir=<Path/To/Context> <S2I Builder Image Repository> <imageName> ``` ## OpenShift S2I 阿,這篇一開始的目的是要看 OpenShift 利用 S2I 提供了哪些 image builder 相關功能。不過,我完全忘了截 OpenShift 的圖,只能附上幾篇有 UI 的 XDDD - [〈Get s2i image on Openshift〉](https://programmersought.com/article/70153639307/) - [〈OpenShift应用镜像构建(1) S2I tomcat 镜像定制〉](https://www.cnblogs.com/ericnie/p/9677719.html) ## Epilogue and Supplement 好吧,我承認我這篇寫的爛透了 XDDD 畢竟這篇是好久前的事情,希望下一篇不會這麼糟糕 Orz <p class="illustration"> <img src="https://i.imgur.com/cPqnoom.png" alt="爛透了"> 爛透了(圖片來源: <a href="https://memes.tw/">Meme 梗圖倉庫</a>) </p> <br class="big"> 手邊還有幾張在文中用不到的圖,但我覺得圖還不錯,所以我就把圖放在這邊提供大家參考了: <p class="illustration"> <img src="https://i.imgur.com/4sVwCth.png" alt="s2i flow"> s2i flow(圖片來源: <a href="https://andyyoung01.github.io/2016/08/24/Source-to-image构建代码">Andy's Techblog</a>) </p> <p class="illustration"> <img src="https://i.imgur.com/b9Y8tjr.png" alt="s2i flow"> s2i flow(圖片來源: <a href="https://osninja.io/source-to-image-getting-started-with-s2i-4554dc9daa68">The OpenShift Ninja|Medium </a>) </p> ## 參考資料 1. [Introduction to S2I](https://v2-1.docs.kubesphere.io/docs/developer/s2i-introduction/)。檢自 KubeSphere Documents (2022-12-31)。 2. [S2I Requirements| OpenShift Container Platform 3.11](https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html)。檢自 Red Hat OpenShift (2022-12-31)。 3. Maciej Szulik (2015-07-21)。[How to Create an S2I Builder Image](https://cloud.redhat.com/blog/create-s2i-builder-image)。檢自 Red Hat Hybrid Cloud (2022-12-31)。 4. Diane Mueller (2016-07-08)。[Source-to-Image (S2I) Deep Dive with Ben Parees - OpenShift Commons Briefing #43](https://cloud.redhat.com/blog/source-image-s2i-deep-dive-ben-parees-openshift-commons-briefing-43)。檢自 Red Hat Hybrid Cloud (2022-12-31)。 5. (2021-03-11)。[OpenShift Container Platform 4.4 构建(build)](https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.4/pdf/builds/OpenShift_Container_Platform-4.4-Builds-zh-CN.pdf)。檢自 Red Hat (2022-12-31)。 6. coreydaley et al. (2022-07-09)。[s2i builder image requirements](https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md)。檢自 source-to-image|GitHub (2023-01-12)。 7. Nautilu, coreydaley (2021-10-18)。[Creating a basic S2I builder imag](https://github.com/openshift/source-to-image/blob/master/examples/nginx-centos7/README.md)。檢自 source-to-image|GitHub (202-01-12)。 8. Vidyasagar Machupalli (2021-10-18)。[Build a Container Image from Source Code Using S2I and Push It to a Private Registry](https://www.ibm.com/cloud/blog/build-a-container-image-from-source-code-using-s2i)。檢自 IBM (202-01-12)。 9. The OpenShift Ninja (2018-07-03)。[Source-To-Image: Getting Started With s2i](https://osninja.io/source-to-image-getting-started-with-s2i-4554dc9daa68)。檢自 Medium (2022-12-31)。 10. elef (2018-11-08)。[第5章 5.2 OpenShift Origin下快速部署JAVA应用](https://www.jianshu.com/p/c06b8ec92ed3)。檢自 简书 (2022-12-31)。 11. brandontsai (2020-09-26)。[免 Dockerfile 就可建構 Image 神器 - Source-To-Image (S2I)](https://ithelp.ithome.com.tw/articles/10244344)。檢自 iT 邦幫忙 (2022-12-31)。 12. 张雷 (2018-01-16)。[Source to Image 工具介绍 - ](https://zhuanlan.zhihu.com/p/33046277)。檢自 知乎 (2022-12-31)。 13. 杨冬 (2016-08-24)。[使用Source-to-image(S2I)构建镜像](https://andyyoung01.github.io/2016/08/24/Source-to-image构建代码/)。檢自 Andy's Techblog (2022-12-31)。 14. 我是读书人 (2020-06-15)。[使用S2I从源码构建镜像](https://segmentfault.com/a/1190000022936004)。檢自 SegmentFault 思否 (2022-12-31)。 15. shenhonglei (2020-07-16)。[快速学习Source-to-Image (S2I) (一)](https://blog.csdn.net/shenhonglei1234/article/details/107396708)。檢自 shenhonglei 的博客|CSDN博客 (2022-12-31)。 16. 胡了了 (2017-09-27)。[openshift/origin学习记录(9)——S2I镜像定制(基于Git)](https://blog.csdn.net/huqigang/article/details/78110233?ops_request_misc=&request_id=&biz_id=102&utm_term=openshift/origin学习记录(9)——S2I镜像&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-78110233.142^v70^js_top,201^v4^add_ask&spm=1018.2226.3001.4187)。檢自 胡了了的博客|CSDN博客 (2022-12-31)。 17. 胡了了 (2017-10-25)。[openshift/origin工作记录(1)——S2I镜像定制(基于SVN)](https://blog.csdn.net/huqigang/article/details/78338376?ops_request_misc=&request_id=&biz_id=102&utm_term=openshift/origin工作记录(1)——S2I镜像&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-78338376.142^v70^js_top,201^v4^add_ask&spm=1018.2226.3001.4187)。檢自 胡了了的博客|CSDN博客 (2022-12-31)。 18. echochio (2017-05-07)。[Source-to-image(S2I)測試一下](https://echochio.pixnet.net/blog/post/44754745-source-to-image(s2i)測試一下)。檢自 echochio|痞客邦 (2022-12-31)。 19. qq_dao (2019-01-26)。[Openshift S2I構建流程](https://www.twblogs.net/a/5c4c35cebd9eee6e7e06f186)。檢自 台部落 (2022-12-31)。 20. [Get s2i image on Openshift](https://programmersought.com/article/70153639307/)。檢自 Programmer Sought (2022-12-31)。 ## 更新紀錄 :::spoiler 最後更新日期:2023-02-16 - 2023-02-16 發布 - 2023-01-08 完稿 - 2022-12-29 起稿 ::: {%hackmd @CynthiaChuang/Github-Page-Footer %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up