Dockerfile 編寫推薦

一、導讀

本文主要介紹在編寫 docker 鏡像的時候一些需要注意的事項和推薦的做法。

雖然 Dockerfile 簡化了鏡像構建的過程,并且把這個過程可以進行版本控制,但是不正當的

Dockerfile 使用也會導致很多問題。

  1. docker 鏡像太大。如果你經常使用鏡像或者構建鏡像,一定會遇到那種很大的鏡像,甚至有些能達到 2G 以上
  2. docker 鏡像的構建時間過長。每個 build 都會耗費很長時間,對于需要經常構建鏡像(比如單元測試)的地方這可能是個大問題
  3. 重復勞動。多次鏡像構建之間大部分內容都是完全一樣而且重復的,但是每次都要做一遍,浪費時間和資源

希望讀者能夠對 docker 鏡像有一定的了解,閱讀這篇文章至少需要一下前提知識

  1. 了解 docker 的基礎概念,運行過容器
  2. 熟悉 docker 鏡像的基礎知識,知道鏡像的分層結構
  3. 最好是負責過某個 docker 鏡像的構建(使用 docker build 命令創建過自己的鏡像)
  4. Dockerfile 和鏡像構建

Dockerfile 是由一個個指令組成的,每個指令都對應著最終鏡像的一層。每行的第一個單詞就是命令,后面所有的字符串是這個命令的參數,關于 Dockerfile 支持的命令以及它們的用法,可以參考官方文檔,這里不再贅述。

當運行 docker build 命令的時候,整個的構建過程是這樣的:

a. 讀取 Dockerfile 文件發送到 docker daemon

b. 讀取當前目錄的所有文件(context),發送到 docker daemon

c. 對 Dockerfile 進行解析,處理成命令加上對應參數的結構

d. 按照順序循環遍歷所有的命令,對每個命令調用對應的處理函數進行處理

e. 每個命令(除了 FROM)都會在一個容器執行,執行的結果會生成一個新的鏡像,為最后生成的鏡像打上標簽

二、編寫 Dockerfile 的一些最佳實踐

1.使用統一的 base 鏡像

有些文章講優化鏡像會提倡使用盡量小的基礎鏡像,目前集團操作系統一級提供統一的基礎鏡像,一些BU也根據自己的技術規范定義了BU級的基礎鏡像,一般的應用只需要FROM自己BU提供的基礎鏡像即可,因為基礎鏡像只需要下載一次可以共享,并不會造成太多的存儲空間浪費。它的好處是這些鏡像的生態比較完整,方便我們安裝軟件,除了問題方便調試。

2.動靜分離

經常變化的內容和基本不會變化的內容要分開,把不怎么變化的內容放在下層,創建出來不同基礎鏡像供上層使用。比如可以創建各種語言的基礎鏡像,這些鏡像包含了最基本的語言庫,每個組可以在上面繼續構建應用級別的鏡像。

3.最小原則:只安裝必需的東西

很多人構建鏡像的時候,都有一種沖動——把可能用到的東西都打包到鏡像中。要遏制這種想法,鏡像中應該只包含必需的東西,任何可以有也可以沒有的東西都不要放到里面。因為鏡像的擴展很容易,而且運行容器的時候也很方便地對其進行修改。這樣可以保證鏡像盡可能小,構建的時候盡可能快,也保證未來的更快傳輸、更省網絡資源。

4.一個原則:每個鏡像只有一個功能

不要在容器里運行多個不同功能的進程,每個鏡像中只安裝一個應用的軟件包和文件,需要交互的程序通過 容器之間的網絡進行交流。這樣可以保證模塊化,不同的應用可以分開維護和升級,也能減小單個鏡像的大小。

5.使用更少的層

雖然看起來把不同的命令盡量分開來,寫在多個命令中容易閱讀和理解。但是這樣會導致出現太多的鏡像層,而不好管理和分析鏡像,而且鏡像的層是有限的。盡量把相關的內容放到同一個層,使用換行符進行分割,這樣可以進一步減小鏡像大小,并且方便查看鏡像歷史。

6.減少每層的內容

盡管只安裝必須的內容,在這個過程中也可能會產生額外的內容或者臨時文件,我們要盡量讓每層安裝的東西保持最小。

比如使用 --no-install-recommends 參數告訴 apt-get 不要安裝推薦的軟件包

7.不要在 Dockerfile 中單獨修改文件的權限

因為 docker 鏡像是分層的,任何修改都會新增一個層,修改文件或者目錄權限也是如此。如果有一個命令單獨修改大文件或者目錄的權限,會把這些文件復制一份,這樣很容易導致鏡像很大。

解決方案也很簡單,要么在添加到 Dockerfile 之前就把文件的權限和用戶設置好,要么在容器啟動腳本(entrypoint)做這些修改,或者拷貝文件和修改權限放在一起做(這樣最終也只是增加一層)。

8.利用 cache 來加快構建速度

如果 Docker 發現某個層已經存在了,它會直接使用已經存在的層,而不會重新運行一次。如果你連續運行 docker build 多次,會發現第二次運行很快就結束了。

不過從 1.10 版本開始,Content Addressable Storage 的引入導致緩存功能的實效,目前引入了 --cache-from 參數可以手動指定一個鏡像來使用它的緩存。

反之,如果想要緩存失效(禁用此層及后面層的緩存),可以在對應層前加LABEL語句:

LABEL key=value ,每次修改value的值,使得緩存失效。

9.版本控制和自動構建

最好把 Dockerfile 和對應的應用代碼一起放到版本控制中,然后能夠自動構建鏡像。這樣的好處是可以追蹤各個版本鏡像的內容,方便了解不同鏡像有什么區別,對于調試和回滾都有好處。

另外,如果運行鏡像的參數或者環境變量很多,也要有對應的文檔給予說明,并且文檔要隨著 Dockerfile 變化而更新,這樣任何人都能參考著文檔很容易地使用鏡像,而不是下載了鏡像不知道怎么用。

10.使用一個.dockerignore文件

在大部分情況下,最好的做法是將每一個Dockerfile文件放到一個空的文件夾里。接著,把構建Dockerfile所需的文件添加到這個文件下。為了提高構建的效率,你可以在這個文夾下添加一個.dockerignore 文件來排除那些沒用的文件和文件夾。這個文件支持類似 .gitignore 文件那樣的排除模式。關于如何創建它,可以移步到dockerignore 文件。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70206.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70206.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70206.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql 學習16 視圖,存儲過程,存儲函數,觸發器

視圖, 存儲過程, 存儲函數 觸發器

SpringBoot+Vue+數據可視化的動漫妝造服務平臺(程序+論文+講解+安裝+調試+售后等)

感興趣的可以先收藏起來,還有大家在畢設選題,項目以及論文編寫等相關問題都可以給我留言咨詢,我會一一回復,希望幫助更多的人。 系統介紹 在當今數字化高速發展的時代,動漫產業迎來了前所未有的繁榮,動漫…

rtsp rtmp 跟 http 區別

SDP 一SDP介紹 1. SDP的核心功能 會話描述:定義會話的名稱、創建者、時間范圍、連接地址等全局信息。媒體協商:明確媒體流的類型(如音頻、視頻)、傳輸協議(如RTP/UDP)、編碼格式(如H.264、Op…

Containerd 簡介、安裝與使用指南

1. Containerd 簡介 Containerd 是一個開源的容器運行時,專注于管理容器的生命周期。它最初是 Docker 的一部分,后來被分離出來成為一個獨立的項目,并成為 Kubernetes 和其他容器平臺的底層運行時。Containerd 提供了容器的創建、啟動、停止…

開源語音克隆項目 OpenVoice V2 本地部署

#本機環境 WIN11 I5 GPU 4060ti 16G 內存 32G #開始 git clone https://github.com/myshell-ai/OpenVoice.git conda create -n opvenv python3.9 -y conda activate opvenv pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/…

【Prometheus】prometheus結合domain_exporter實現域名監控

?? 歡迎大家來到景天科技苑?? ???? 養成好習慣,先贊后看哦~???? ?? 作者簡介:景天科技苑 ??《頭銜》:大廠架構師,華為云開發者社區專家博主,阿里云開發者社區專家博主,CSDN全棧領域優質創作者,掘金優秀博主,51CTO博客專家等。 ??《博客》:Python全…

rustdesk編譯修改名字

最近,我用Rust重寫了一個2W行C代碼的linux內核模塊。在此記錄一點經驗。我此前沒寫過內核模塊,認識比較疏淺,有錯誤歡迎指正。 為什么要重寫? 這個模塊2W行代碼量看起來不多,卻在線上時常故障,永遠改不完。…

在linux系統中安裝Anaconda,并使用conda

系統 : ubuntu20.04 顯卡:NVIDIA GTX1650 目錄 安裝Anaconda第一步:下載合適版本的Anconda1. 查看自己Linux的操作系統及架構命令:uname -a2. 下載合適版本的Anconda 第二步:安裝Aanconda1. 為.sh文件設置權限2. 執行.sh文件2.1 .…

(前端基礎)HTML(一)

前提 W3C:World Wide Web Consortium(萬維網聯盟) Web技術領域最權威和具有影響力的國際中立性技術標準機構 其中標準包括:機構化標準語言(HTML、XML) 表現標準語言(CSS) 行為標準&#xf…

【ISO 14229-1:2023 UDS診斷(會話控制0x10服務)測試用例CAPL代碼全解析③】

ISO 14229-1:2023 UDS診斷【會話控制0x10服務】_TestCase03 作者:車端域控測試工程師 更新日期:2025年02月15日 關鍵詞:UDS診斷、0x10服務、診斷會話控制、ECU測試、ISO 14229-1:2023 TC10-003測試用例 用例ID測試場景驗證要點參考條款預期…

TDengine 客戶端連接工具 taos-Cli

簡介工具獲取運行命令行參數 基礎參數高級參數 數據導出/導入 數據導出數據導入 執行 SQL 腳本使用小技巧 TAB 鍵自動補全設置字符列顯示寬度其它 錯誤代碼表 簡介 TDengine 命令行工具(以下簡稱 TDengine CLI)是用戶操作 TDengine 實例并與之交互最簡…

Git高級用法

GIT高級用法及實戰案例解析 前言 作為現代開發者的必備工具,Git的基礎操作(add/commit/push)早已深入人心。但當面對復雜場景時,掌握Git的高級用法將極大提升開發效率。本文將深入解析Git的高級功能,并配合真實場景案…

9個用于測試自動化的最佳AI測試工具(2024)

選擇一款優質的基于生成式AI人工智能的測試工具能夠確保測試過程的準確性和效率,從而加速整個軟件測試周期。相反,設計不佳的測試工具可能無法發現錯誤,并可能存在安全問題。它們可能產生誤報或漏報,誤導開發與測試團隊&#xff0…

vue-model如何自定義指令,及批量注冊自定義指令

一、在Vue.js中,v-model是一個用于在表單輸入和應用狀態之間創建雙向綁定的指令。要編寫自定義的v-model指令,你需要使用Vue的自定義指令API。以下是編寫自定義v-model指令的步驟: 定義一個自定義指令對象。在指令對象的bind鉤子函數中&…

簡單認識一下-Redis

一、什么是Redis Redis(Remote Dictionary Server)是一個開源的、基于內存的數據結構存儲系統,它既可以用作數據庫、緩存,也可以作為消息中間件使用。以下為你詳細介紹 Redis: 基本特點 高性能:Redis 將數…

LabVIEW的吞雨測控系統

本案例介紹了一種基于LabVIEW開發的吞雨測控系統,該系統通過建模仿真分析不同控制器模式下的階躍信號響應,從而選擇了最適合的控制器。為了有效解決在控制流量過程中出現的振蕩收斂和流量信號大擾動問題,系統采用了改進的積分分離PID算法&…

C++中的順序容器(一)

文章目錄 順序容器概述所有容器類型都支持的操作迭代器容器定義與初始化將一個容器初始化為另一個容器的拷貝標準庫array具有固定大小 賦值和swap關系運算符 順序容器的特有操作向順序容器添加元素訪問元素刪除元素特殊的forward_list操作改變容器的大小容器操作可能是迭代器失…

Javaweb中,使用Servlet編寫簡單的接口

案例:網頁提交用戶名和密碼信息,后端校驗密碼長度需在6-12位之間 后端部分 WebServlet("/valid") public class SimpleServlet extends HttpServlet{public void service(HttpServletRequest req, HttpServletResponse resp) throws IOExcepti…

C語言實現的常見排序算法

排序是計算機科學中非常重要的基礎算法之一。無論是在數據分析、數據庫查詢還是圖形界面中,我們都可能會遇到排序問題。本文將介紹幾種常見的排序算法,并提供其C語言實現代碼。排序算法的效率和應用場景有很大關系,不同的算法有不同的時間復雜…

對于簡單的HTML、CSS、JavaScript前端,我們可以通過幾種方式連接后端

1. 使用Fetch API發送HTTP請求(最簡單的方式): //home.html // 示例:提交表單數據到后端 const submitForm async (formData) > {try {const response await fetch(http://your-backend-url/api/submit, {method: POST,head…