遲到總比不到好。該故事講關(guān)于我們因不支持使用常規(guī)的Dockerfile來構(gòu)建鏡像導(dǎo)致我們差點(diǎn)犯了一個重大錯誤。Werf[1]是一個GitOps工具,可以很好地集成到任何CI/CD系統(tǒng)中,并提供完整的應(yīng)用程序生命周期管理,允許你:
構(gòu)建和推送鏡像
部署應(yīng)用程序到Kubernetes中
根據(jù)策略清理未使用鏡像
我們工具的理念是:將低級手段組合到一個統(tǒng)一的系統(tǒng)中讓DevOps工程師控制應(yīng)用程序。盡可能使用現(xiàn)有的即用型工具(如Helm和Docker)。但是如果沒有合適的任務(wù)解決方案呢?答案很簡單,我們自己編寫并維護(hù)工具來完成工作。背景:自定義鏡像構(gòu)建器
Werf鏡像構(gòu)建器也發(fā)生了同樣的故事。Dockerfile是描述構(gòu)建鏡像過程的事實標(biāo)準(zhǔn),但我們的需求受到很大限制。這個問題在我們項目的早期階段變得至關(guān)重要。在開發(fā)用于容器化應(yīng)用的工具時,我們很快意識到Dockerfile不適合以下特定任務(wù):
遵循構(gòu)建典型小型Web應(yīng)用程序的標(biāo)準(zhǔn)工作流程:a)安裝系統(tǒng)范圍的應(yīng)用程序依賴項,b)安裝特定于應(yīng)用程序的庫,c)構(gòu)建資產(chǎn)(assets),d)最重要的部分,快速高效地更新鏡像中的代碼。
構(gòu)建器在發(fā)生更改時應(yīng)通過提交修補(bǔ)應(yīng)用于修改的文件來創(chuàng)建新的鏡像層。
如果某些文件已被修改,則必須重建依賴階段。
這是我們一開始的需求列表,在今天我們的構(gòu)建器有著許多額外的功能。總而言之,我們沒花多長時間就開始使用首選編程語言開發(fā)自定義DSL(見下文)。它必須滿足既定目標(biāo),根據(jù)文件描述分階段的構(gòu)建過程并確定不同階段間的依賴。它由相應(yīng)的那些可將DSL轉(zhuǎn)變成最終目標(biāo)的構(gòu)建器,即即用型Docker鏡像補(bǔ)充。一開始我們使用Ruby實現(xiàn)了DSL,在切換到Golang之后我們用YAML文件形式重寫了它。
Werf的Ruby的配置,這是舊的版本(此時項目被稱為dapp)
Werf的YAML形式配置,這是現(xiàn)在的版本構(gòu)建器的概念隨時間推移一直在變化。在一開始,我們只是簡單地使用我們的配置動態(tài)地生成一些臨時的Dockerfile,然后我們在臨時容器中運(yùn)行構(gòu)建指令并進(jìn)行提交。注意:目前我們使用YAML配置的Stapel構(gòu)建器(如上所示)已經(jīng)發(fā)展成一個相當(dāng)強(qiáng)大的工具。雖然它值得一篇文章來詳細(xì)描述其本身,但你現(xiàn)在可以先在該文檔[2]中找到更多詳細(xì)信息。等一下!
不久之后,我們發(fā)現(xiàn)了一個嚴(yán)重的錯誤,那就是我們沒有添加使用標(biāo)準(zhǔn)Dockerfiles構(gòu)建鏡像的能力,我們將它們集成到已建立的基礎(chǔ)架構(gòu)中以進(jìn)行完整的應(yīng)用程序管理(即用于構(gòu)建,部署和刪除鏡像)。“我們怎么可能在沒有支持Dockerfile的情況下打造為Kubernetes部署鏡像的工具,這是否是一種描述大多數(shù)項目鏡像的流行方式?”這個問題依舊困擾著我們。我們沒有回答該問題,而是提出了解決方案。如果你已經(jīng)有了一個Dockerfile(或一組Dockerfile)且想使用werf呢?注意:順便問一下,你為何要使用werf?至少,它有各種很好的功能來增強(qiáng)和粘合你的CI/CD流程,例如:
完整的應(yīng)用程序管理周期,包括刪除鏡像
在單個配置中構(gòu)建多個鏡像的能力
改進(jìn)的部署Helm兼容圖表的流程
完整的功能列表請點(diǎn)擊項目頁面[3]。因此,直至最近,如果你對使用werf感興趣,我們還希望你將Dockerfiles移植到我們的配置格式。但是現(xiàn)在我們很高興地告訴你,“讓werf來構(gòu)建你的Dockerfiles吧!”用法
此功能的首次完整實現(xiàn)在werf的v1.0.3-beta.1版本引入。一般流程非常簡單,即用戶在werf配置中指定已存在的Dockerfile的路徑,然后使用werf build命令啟動werf。然后就沒有然后了,werf將會構(gòu)建鏡像。以下是一個例子。我們在應(yīng)用的根目錄中定義 Dockerfile:
FROM ubuntu:18.04
RUN echo Building ...
然后我們定義 werf.yaml它將引用上面的 Dockerfile:
configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: ./Dockerfile
然后我們就可以執(zhí)行werf build了:
順便說下,你也可以這樣定義werf.yaml以使用多個Dockerfile同時構(gòu)建鏡像:
configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: ./dockerfiles/Dockerfile-backend
---
image: frontend
dockerfile: ./dockerfiles/Dockerfile-frontend
Werf配置中同樣支持傳遞額外的構(gòu)建參數(shù),例如--build-arg和--add-host等。以下是完整Dockerfile鏡像配置的鏈接[4]。它是如何運(yùn)作的?
在構(gòu)建鏡像期間,本地層的通用Docker緩存處于活動狀態(tài)。重要的是,werf還將Dockerfile配置集成到其基礎(chǔ)架構(gòu)中。這意味著什么?
所有使用Dockerfile構(gòu)建的鏡像都包含一個特定的名為dockerfile的階段。(可以在werf文檔中[5]了解“階段”相關(guān)內(nèi)容)
在dockerfile階段,werf會根據(jù)Dockerfile配置中的內(nèi)容計算出簽名。Dockerfile配置的改變將會引起dockerfile階段的簽名改變。在這種情況下,werf使用新的Dockerfile配置啟動此階段的重建。如果簽名保持不變,則werf使用緩存的鏡像。
你可是使用werf publish或werf build-and-publish發(fā)布構(gòu)建出來的鏡像并將其部署到Kubernetes中。已推送到Docker倉庫的鏡像會通過常規(guī)werf機(jī)制進(jìn)行清理。這意味著舊鏡像(超過N天)和與不存在的Git分支相關(guān)聯(lián)的鏡像將被自動刪除,且可以應(yīng)用其他策略。
你可以在相應(yīng)的文檔中了解有關(guān)這些werf特性的更多信息:
發(fā)布過程[6];
與Kubernetes的部署過程集成[7];
清理過程[8]。
提示和警告
1. 指令A(yù)DD不支持外部URL當(dāng)前ADD參數(shù)不能支持外部的URL。Werf不會啟動重建過程以響應(yīng)指定URL處的資源更改。我們計劃很快添加此功能。
2. 不能將.git目錄包含到鏡像中事實上,將.git目錄添加到你的容器鏡像中不是個好主意,原因如下:
.git目錄在最終鏡像中的存在違反了12要素應(yīng)用理念。最終鏡像必須與單個提交鏈接;不應(yīng)允許其在任意提交上執(zhí)行g(shù)it checkout。
.git目錄增大了鏡像的體積(Git倉庫可能會因為曾經(jīng)添加刪除過大文件而增大)。相反地,每個特定提交對工作樹大小將不依賴于Git操作的歷史。此外,.git目錄從最終鏡像中添加以及后續(xù)的刪除,文件夾將不再起作用,因為無論如何都將生成新的層次(這正是Docker的工作原理)。
即使正在處理相同的提交(源自不同的工作樹),Docker也可能啟動不必要的重建。例如,GitLab在/home/gitlab-runner/builds/HASH/[0-N]/yourproject啟用并行構(gòu)建時創(chuàng)建單獨(dú)的克隆文件夾。不必要的重建是由.git同一存儲庫的各種克隆版本中的文件夾的差異引起的(即使我們構(gòu)建完全相同的提交)。
最后一點(diǎn)直接影響了werf的使用。Werf需要構(gòu)建緩存來運(yùn)行某些命令(例如werf deploy)。執(zhí)行這些命令時,werf會為werf.yaml文件中指定的鏡像計算各階段簽名,因此它們必須存在于構(gòu)建緩存中,否則命令將會失敗。.git內(nèi)容在簽名階段的依賴意味著緩存容易受到無關(guān)文件的影響,這是werf無法容忍的錯誤(更多細(xì)節(jié)[9])。無論如何,通過ADD和COPY指令添加特定和需要的文件仍然是一個很好的做法。它提高了創(chuàng)建的效率和所創(chuàng)建的Dockerfile的可靠性,并提高了緩存(通過上述內(nèi)容構(gòu)建Dockerfile)對Git中無關(guān)的更改的彈性。總結(jié)
我們?yōu)樘囟ㄐ枨笾谱髯远x構(gòu)建器之路是艱難的,誠實的和直接的:我們傾向于使用自定義語法開發(fā)自己的解決方案,而不是將解決方法置于默認(rèn)Dockerfile之上。這種方法有其優(yōu)勢:Stapel構(gòu)建器就做得很好!但是,在創(chuàng)建自定義鏡像構(gòu)建器時,我們完全忽略了應(yīng)用現(xiàn)有Dockerfiles的情況。這個漏洞現(xiàn)在已經(jīng)解決了。在未來,我們計劃加強(qiáng)對Dockerfiles的支持以及我們的定制Stapel構(gòu)建器,用于分布式構(gòu)建和在Kubernetes集群內(nèi)構(gòu)建鏡像(即通過使用類似于kaniko的Kubernetes中的運(yùn)行程序)。所以,如果你碰巧有一些好的Dockerfiles,不要猶豫,快來嘗試werf[1]吧!相關(guān)鏈接:
https://github.com/flant/werf
https://werf.io/documentation/reference/build_process.html#stapel-image-and-artifact
https://github.com/flant/werf#complete-features-list
https://werf.io/documentation/configuration/dockerfile_image.html
https://werf.io/documentation/reference/stages_and_images.html#stages
https://werf.io/documentation/reference/publish_process.html
https://werf.io/documentation/reference/deploy_process/deploy_into_kubernetes.html#integration-with-built-images
https://werf.io/documentation/reference/cleaning_process.html
https://werf.io/documentation/reference/stages_and_images.html
原文鏈接:https://medium.com/flant-com/werf-dockerfile-support-e6504211b8e6Kubernetes入實戰(zhàn)培訓(xùn)
Kubernetes入門與實戰(zhàn)培訓(xùn)將于2019年11月29日在深圳開課,3天時間帶你系統(tǒng)掌握Kubernetes,學(xué)習(xí)效果不好可以繼續(xù)學(xué)習(xí)。本次培訓(xùn)包括:云原生介紹、微服務(wù);Docker基礎(chǔ)、Docker工作原理、鏡像、網(wǎng)絡(luò)、存儲、數(shù)據(jù)卷、安全;Kubernetes架構(gòu)、核心組件、常用對象、網(wǎng)絡(luò)、存儲、認(rèn)證、服務(wù)發(fā)現(xiàn)、調(diào)度和服務(wù)質(zhì)量保證、日志、監(jiān)控、告警、Helm、實踐案例等等,點(diǎn)擊下方圖片或者閱讀原文鏈接查看詳情。
總結(jié)
以上是生活随笔為你收集整理的dockerfile cd目录_使用Werf和现有的Dockerfiles改善你的CI/CD体验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。