使用云原生buildpacks将你的代码转换成Docker Image | 技术干货
戳藍(lán)字“CSDN云計(jì)算”關(guān)注我們哦!
技術(shù)頭條:干貨、簡(jiǎn)潔、多維全面。更多云計(jì)算精華知識(shí)盡在眼前,get要點(diǎn)、solve難題,統(tǒng)統(tǒng)不在話下!
?
七年前buildpack技術(shù)開(kāi)源之時(shí),我們就看到了這項(xiàng)技術(shù)將大大簡(jiǎn)化應(yīng)用的發(fā)布過(guò)程。當(dāng)開(kāi)發(fā)人員要跑一個(gè) :git push heroku master的時(shí)候,buildpack就可以保證所有依賴以及編譯工作都會(huì)作為發(fā)布的一部分被全權(quán)打理好。
一如之前所宣布,我們正在將buildpacks成功的哲學(xué)理論運(yùn)用到創(chuàng)立云原生buildpacks(CNB)之中,一種再也不需要dockerfile并將源代碼轉(zhuǎn)換為Docker?Image的標(biāo)準(zhǔn)。簡(jiǎn)單地看一下CNB?是如何工作的,它是如何旨在解決許多現(xiàn)存于dockerfile上的問(wèn)題, 以及如何以將它和最近發(fā)布的 buildpacks.io 項(xiàng)目 beta版本一起使用。作為這次發(fā)布的一部分,我們已經(jīng)給 Ruby, Node.js, Java, Python, PHP, 以及Go建立好后可以使用CNB?工具的Heroku buildpacks builder image。
?
我們先從創(chuàng)造一個(gè)稻草人(假設(shè)模型)開(kāi)始。通過(guò)一些比較冗長(zhǎng)無(wú)聊但卻很根本且必須的步驟來(lái)創(chuàng)建一個(gè)Ruby?on Rails 應(yīng)用的Dockerfile。
?
抽象泄露:遞增地來(lái)寫一個(gè)Dockerfile
?
大多開(kāi)發(fā)者以寫一個(gè)dockerfile?來(lái)使用Docker,這個(gè)file會(huì)定義整個(gè)生成Docker?image的build流程。比如說(shuō), 你手里有一個(gè)的Rails?項(xiàng)目,并且你希望將它以一個(gè)Docker?Container來(lái)發(fā)布。你會(huì)需要從一個(gè)基本的Ruby?Image?開(kāi)始, 將其他額外需要的包加入進(jìn)來(lái),以此來(lái)讓你的應(yīng)用跑起來(lái)。如果你從未用過(guò)Docker,你可能要先學(xué)幾樣?xùn)|西才能到這一步。
FROM ruby
RUN apt-get update -qq \
??&& apt-get install -y nodejs libpq-dev build-essential
COPY . /app
WORKDIR /app
RUN bundle install
RUN bundle exec rake assets:precompile
EXPOSE 5000
CMD bin/rails s
??
除了Ruby以外,一個(gè)Rails應(yīng)用的Docker?image?也將會(huì)需要幾個(gè)額外的 Apt包。要想跑用來(lái)預(yù)編譯assets的必須要的工具, node js ?的runtime一定要被包含在其中;為了要和PostgreSQL 交流, libpq-dev也是需要的;以及為了讓gcc能夠給Ruby?gems?們build原生的插件(一個(gè)Ruby包管理器,類似Python的 pip),我們還會(huì)需要到build-essential。
?
一個(gè)Dockerfile?已經(jīng)足夠用來(lái)在生產(chǎn)環(huán)境跑一個(gè)簡(jiǎn)單的Rails應(yīng)用,但是整個(gè)image會(huì)充滿很多非相關(guān)的緩存文件夾。你或許會(huì)想去掉那些文件,以縮減整個(gè)image大小,但這只會(huì)對(duì)本地有序性build有用。
RUN apt-get update -qq \
??&& apt-get install -y nodejs libpq-dev build-essential \
??&& apt-get clean autoclean && apt-get autoremove -y \
??&& rm -rf /var/lib/apt /var/lib/dpkg /var/lib/cache /var/lib/log
# ..
RUN bundle exec rake assets:precompile
??&& rm -rf /app/tmp/cache/assets/
?
這便突出了使用Dockerfile在速度上的短板。 它并不能適當(dāng)利用那些緩存目錄,只因?yàn)橐淮蝦ebuild就會(huì)要把整個(gè)image從頭build。然而,我們可以利用些聰明的小技巧來(lái)緩存依賴(dependency)的信息來(lái)加速builds。相比較每次復(fù)制整個(gè)應(yīng)用,你可以如下選擇性地加入文件。
ADD Gemfile /app/
ADD Gemfile.lock ?/app/
RUN bundle install
?
復(fù)制加入Gemfile?和Gemfile.lock 可以用來(lái)取代dockerfile的緩存機(jī)制,以此來(lái)防止因?yàn)閮H你更改了一行代碼而導(dǎo)致所有的緩存失效。
?
這些例子僅強(qiáng)調(diào)出了“幾個(gè)” 當(dāng)使用Dockerfile構(gòu)建應(yīng)用時(shí)的挑戰(zhàn)和難點(diǎn)。而且你會(huì)在每次使用Dockerfile構(gòu)建應(yīng)用時(shí)都會(huì)重復(fù)遇見(jiàn)這些困難。多數(shù)情況下,最后你都會(huì)復(fù)制粘貼某個(gè)應(yīng)用Dockerfile?的一部分到另外一個(gè)應(yīng)用的Dockerfile,而這種行為會(huì)潛在地造成維護(hù)人員噩夢(mèng)。
?
維護(hù),是Dockerfile最大的短板。除了復(fù)制粘貼代碼,它給你帶來(lái)了一些如果你不使用Dockerfile是絕對(duì)不會(huì)關(guān)心的低等級(jí)問(wèn)題。舉例來(lái)說(shuō),和很多其他編程語(yǔ)言一樣,Ruby有很多基本image?可以給你用來(lái)繼承使用,而且每個(gè)image都有自己的大小和安全性考量。如果有一天,Rails的生態(tài)系統(tǒng)系要一個(gè)新的依賴(dependency),而這個(gè)新的依賴并不存在于你現(xiàn)有的Dockerfile,那你就要負(fù)責(zé)根據(jù)需要更新相關(guān)的設(shè)置。如果你把你的項(xiàng)目分拆成多個(gè)“微服務(wù)”(microservices),同時(shí)也意味著你需要在多個(gè)位置更新你的文件。
最終來(lái)說(shuō),Dockerfile是個(gè)具有漏洞性的抽象概念。它強(qiáng)制開(kāi)發(fā)者們要小心運(yùn)作上,以及平臺(tái)的需要注意點(diǎn),而在這之前這些需要注意點(diǎn)都已經(jīng)被平臺(tái)抽象打理了。要想寫出一個(gè)好的Dockerfile,你就必須理解底層機(jī)制,以及產(chǎn)生image的每一步是如何工作的并以此來(lái)打理未來(lái)的更新。
所有的這些問(wèn)題都源于Dockerfile缺少對(duì)應(yīng)用的相對(duì)了解。如果沒(méi)有你的應(yīng)用相關(guān)或所使用架構(gòu)的上下文相關(guān)信息,開(kāi)發(fā)者如何開(kāi)發(fā)和他們使用的工具就會(huì)產(chǎn)生巨大的不匹配現(xiàn)象。
像這樣將運(yùn)行和應(yīng)用的關(guān)注點(diǎn)混合在一起就相當(dāng)于給了一個(gè)希望盡量容易去寫代碼以及運(yùn)輸代碼的開(kāi)發(fā)者一個(gè)非常差的工具。基于此類不足之處,我們接下來(lái)看一下另外一種可以減少此類復(fù)雜度的替代辦法。
向Buildpacks學(xué)習(xí)
如果你曾經(jīng)使用Heroku來(lái)發(fā)布你的應(yīng)用你就會(huì)知道,這就像在本地跑一個(gè) git?push?heroku?master?一樣容易。而在幕后,一個(gè) buildpack?就會(huì)收集依賴(retrieve?dependencies),運(yùn)行數(shù)據(jù)信息,打理緩存,并且給你的應(yīng)用語(yǔ)言編譯代碼。舉例來(lái)說(shuō),有一個(gè)Rails?應(yīng)用。Ruby的buildpack就會(huì)安裝Ruby和 bundler(一個(gè)Ruby的依賴管理應(yīng)用)。你的gem(一系列包和文件的總稱)依賴會(huì)被提取出來(lái),你的資源代碼會(huì)被編譯,而且緩存也會(huì)被清理干凈:
git push heroku master
remote: Compressing source files... done.
remote: Building source:
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.6.0
remote: -----> Installing dependencies using bundler 1.15.2
remote: ???????Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
...
remote: ???????Bundle complete! 18 Gemfile dependencies, 61 gems now installed.
remote: ???????Gems in the groups development and test were not installed.
remote: ???????Bundled gems are installed into `./vendor/bundle`
remote: ???????Removing bundler (1.15.2)
remote: ???????Bundle completed (42.62s)
remote: ???????Cleaning up the bundler cache.
...
remote: ???????Asset precompilation completed (3.72s)
remote: ???????Cleaning assets
remote: ???????Running: rake assets:clean
remote: -----> Detecting rails configuration
remote: -----> Compressing...
remote: ???????Done: 41.3M
remote: -----> Launching...
remote: ???????Released v6
remote: ???????https://myapp.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
??
一個(gè)Buildpack以識(shí)別你應(yīng)用代碼語(yǔ)言的行為慣例幫你自動(dòng)處理了這些步驟。Builpacks的設(shè)計(jì)原則就是就是安裝并設(shè)置所有需要的設(shè)置以幫你達(dá)到運(yùn)行你的應(yīng)用的目的。站在云原生Buildpacks的角度來(lái)說(shuō),我們希望利用Docker和現(xiàn)代container標(biāo)準(zhǔn),有一個(gè)相似的系統(tǒng)來(lái)讓我們的開(kāi)發(fā)者更加注重于他們的應(yīng)用,而不是拼湊一個(gè)build管道。
?
運(yùn)行云原生Buildpacks
因?yàn)橄M軌驅(qū)?/span> Buildpacks?的簡(jiǎn)潔性和可用性與container的優(yōu)勢(shì)結(jié)合起來(lái),我們開(kāi)發(fā)了云原生Buildpacks(CNB),它可以產(chǎn)出一個(gè) “開(kāi)放容器計(jì)劃”兼容(OCI-Compliant)image, 并且這個(gè)image可以使用現(xiàn)存 的Docker?工具,以及更廣闊的現(xiàn)存容器生態(tài)系統(tǒng)。
Buildpacks.io項(xiàng)目是一個(gè)讓我們?cè)妇俺煽赡艿拈_(kāi)源工具之家。其中,第一個(gè)工具便是 pack?build,其行為和git?push heroku master非常相似。你可以在任意資源庫(kù)下產(chǎn)生一個(gè)Docker?image。以下便是一個(gè)在Rails應(yīng)用上跑的Heroku云原生buildpack的例子。
?
和buildpack產(chǎn)生可執(zhí)行的壓縮文件(slug)很相似, 一個(gè)CNB會(huì)根據(jù)你現(xiàn)有項(xiàng)目的文件識(shí)別什么東西需要被安裝。你不需要進(jìn)行任何配置來(lái)識(shí)別確認(rèn)你的應(yīng)用的需求。因?yàn)閎uildpack?是應(yīng)用感知的(app-aware),它能夠精準(zhǔn)地捕捉到你所使用的編程語(yǔ)言以及你應(yīng)用的所需依賴,在build階段也同樣會(huì)有著合理的系統(tǒng)默認(rèn)值來(lái)處理內(nèi)存的使用和處理并發(fā)。
?
CNB?進(jìn)程在產(chǎn)生最后image的進(jìn)行的步驟和現(xiàn)存Heroku?Buildpacks運(yùn)作的不同階段非常相似:
·?CLI 偵測(cè)到你的項(xiàng)目使用的主要語(yǔ)言。比如說(shuō),如果你的源代碼目錄下有一個(gè)Gemfile,那么CNB就會(huì)將它識(shí)別為一個(gè)Ruby項(xiàng)目;如果有個(gè)pom.xml那么它就會(huì)被識(shí)別為一個(gè)Java項(xiàng)目,以此類推。
·?之后,執(zhí)行環(huán)境會(huì)分析之前的build來(lái)確認(rèn)其中是否有任何步驟可以在接下來(lái)build中使用。
·?CNB開(kāi)始跑build,下載所需的依賴以及將應(yīng)用準(zhǔn)備好可以在production當(dāng)中運(yùn)行。
·?最后,它會(huì)將以上build的結(jié)果以Docker?image的形式導(dǎo)出。
?
產(chǎn)出一個(gè)image的底層幕后進(jìn)程全權(quán)被buildpack所打理。如果這個(gè)進(jìn)程需要被更新-比如有個(gè)漏洞被檢測(cè)到-你可以很輕松地獲取一個(gè)新的工具鏈并且用 pack?rebase重新build一個(gè)image來(lái)更新你的image而不用從頭開(kāi)始build一個(gè)image, 整個(gè)過(guò)程花費(fèi)不到一秒鐘。和用Dockerfile在你每一個(gè)應(yīng)用上rebuild相比(一個(gè)可能耗費(fèi)幾個(gè)小時(shí)的過(guò)程),這會(huì)節(jié)省大量的時(shí)間。
?
現(xiàn)在就來(lái)試一下云原生Buildpacks吧!
?
再也沒(méi)有比現(xiàn)在更好的時(shí)機(jī)來(lái)嘗試一下云原生Buildpacks(CNB)了。這個(gè)項(xiàng)目剛剛出了它第一個(gè)beta?版本, 它已經(jīng)準(zhǔn)備好被你使用,也希望到你的反饋!
如何開(kāi)始呢?先下載 pack CLI?并且在你的應(yīng)用源代碼目錄下使用我們?nèi)我籦uildpack(Ruby,??Node.js, Java, Python, PHP, Go)。
?
$ pack build --builder heroku/buildpacks <docker image name>
來(lái)Slack上加入我們!如果你還想生成你自己的OCI?Images,我們還有定義了使用細(xì)則的buildpack API文檔?。
Heroku 一直以來(lái)都認(rèn)為切合開(kāi)發(fā)者的關(guān)注和需求是非常重要的:即他們應(yīng)用的源代碼。我們相信云原生Buildpacks?會(huì)因?yàn)橐越⒘嘶谌萜鞯膽?yīng)用而幫助減少在運(yùn)行維護(hù)上的復(fù)雜度,從而解放了開(kāi)發(fā)者雙手來(lái)專注于給他們的用戶創(chuàng)作更多優(yōu)秀的的功能和特性。?
?
福利
掃描添加小編微信,備注“姓名+公司職位”,加入【云計(jì)算學(xué)習(xí)交流群】,和志同道合的朋友們共同打卡學(xué)習(xí)!
推薦閱讀:
如何快速深入理解監(jiān)控知識(shí)? | 技術(shù)干貨
為什么說(shuō)深耕AI領(lǐng)域繞不開(kāi)知識(shí)圖譜?
ARM 發(fā)布新一代 CPU 和 GPU,實(shí)現(xiàn) 20% 性能提升!
比特幣沖到9000美元, 你就能找個(gè)好工作?
1000 萬(wàn)個(gè)“AI 名師”:用機(jī)器算法“解剖”應(yīng)試教育
阿里面試,我掛在了第四輪……
10個(gè)爬蟲(chóng)工程師必備的工具了解一下
真香,朕在看了!
總結(jié)
以上是生活随笔為你收集整理的使用云原生buildpacks将你的代码转换成Docker Image | 技术干货的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: boost的chrono模块操作时钟对象
- 下一篇: boost的chrono模块最小时间点的