精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Dockerfile的最佳實踐

汽車電子技術 ? 來源:程序猿技術大咖 ? 作者: xcbey0nd ? 2023-01-20 10:59 ? 次閱讀

微信截圖_20230105161930.png

隨著應用的容器化、上云后,將伴隨著 Docker 鏡像的構建,構建 Docker 鏡像成為了最基本的一步,其中 Dockerfile 便是用來構建鏡像的一種文本文件,鏡像的優劣全靠 Dockerfile 編寫的是否合理、合規。本文將講述編寫 Dockerfile 的一些最佳實踐和技巧,讓我們的鏡像更小、更優。

1、Docker 鏡像是如何工作的

首先,我們一起回顧下 Docker 鏡像的相關概念及工作流程吧。

1.1 鏡像

鏡像(image)是一堆只讀層(read-only layer)的統一視角,也許這個定義有些難以理解,下面的這張圖能夠幫助您理解鏡像的定義。

微信截圖_20230105161930.png

從左邊我們看到了多個只讀層,它們重疊在一起。除了最下面一層,其它層都會有一個指針指向下一層。這些層是 Docker 內部的實現細節,并且能夠在主機的文件系統上訪問到。統一文件系統技術能夠將不同的層整合成一個文件系統,為這些層提供了一個統一的視角,這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統。我們可以在圖片的右邊看到這個視角的形式。

您可以在您的主機文件系統上找到有關這些層的文件。需要注意的是,在一個運行中的容器內部,這些層是不可見的。在我的主機上,我發現它們存在于 /var/lib/docker/overlay2 目錄下。

1.2 鏡像分層結構

為什么說是鏡像分層結構,因為 Docker 鏡像是以層來組織的,可以通過命令 docker image inspect 或者 docker inspect 來查看鏡像包含哪些層。

例如,鏡像 busybox :

xcbeyond@xcbeyonddeMacBook-Pro ~ % docker inspect busybox
[
    {
        "Id": "sha256:3c277069c6ae3f3572998e727b973ff7418c3962b9403de4b3a3f8624399b8fa",
        "RepoTags": [
            "busybox:latest"
        ],
        "RepoDigests": [
            "busybox@sha256:d2b53584f580310186df7a2055ce3ff83cc0df6caacf1e3489bff8cf5d0af5d8"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2022-04-14T00:39:25.923517152Z",
        "Container": "39aaf4eecc48824531078c316f5b16e97549417e07c8f90b26ae16053111ea57",
        "ContainerConfig": {
            "Hostname": "39aaf4eecc48",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"sh\"]"
            ],
            "Image": "sha256:3289bc85dc0eba79657979661460c7f6f97688ad8a4f93174e0cabdd6b09a365",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "20.10.12",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "sh"
            ],
            "Image": "sha256:3289bc85dc0eba79657979661460c7f6f97688ad8a4f93174e0cabdd6b09a365",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "arm64",
        "Variant": "v8",
        "Os": "linux",
        "Size": 1411540,
        "VirtualSize": 1411540,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/merged",
                "UpperDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/diff",
                "WorkDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:31a5597e16d3c5adaaf5826162216e256126d2fbf1beaa2b6c45c1822a2b9ca3"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

其中,RootFS 就是鏡像 busybox:latest 的鏡像層,只有一層,這層數據是存儲在宿主機哪里的呢?動手實踐的同學會在上面的輸出中看到一個叫做 GraphDriver 的字段內容如下:

"GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/merged",
                "UpperDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/diff",
                "WorkDir": "/var/lib/docker/overlay2/e89181e7cadd3a6ee49f66bae34fed369621a1a5cfbe0003ce4621d0eec020e6/work"
            },
            "Name": "overlay2"
        }

GraphDriver 負責鏡像本地的管理和存儲以及運行中的容器生成鏡像等工作,可以將 GraphDriver 理解成鏡像管理引擎,我們這里的例子對應的引擎名字是 overlay2(overlay 的優化版本)。除了 overlay 之外,Docker 的 GraphDriver 還支持 btrfs、aufs、devicemapper、vfs 等。

我們可以看到其中的 Data 包含了多個部分,這個對應 OverlayFS 的鏡像組織形式,雖然我們上面的例子中的 busybox 鏡像只有一層,但是正常情況下很多鏡像都是由多層組成的。

1.3 Dockerfile、鏡像、容器間的關系

Dockerfile 是軟件的原材料,Docker 鏡像是軟件的交付品,而 Docker 容器則可以認為是軟件的運行態。從應用軟件的角度來看,Dockerfile、Docker 鏡像與 Docker 容器分別代表軟件的三個不同階段,Dockerfile 面向開發,Docker 鏡像成為交付標準,Docker 容器則涉及部署與運維,三者缺一不可,合力充當 Docker 體系的基石。

簡單來講,Dockerfile 構建出 Docker鏡像,通過 Docker 鏡像運行Docker容器。

我們可以從 Docker 容器的角度,來反推三者的關系,如下圖:

微信截圖_20230105161930.png

2、Dockerfile

Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明,它是構建鏡像的關鍵。

一個 Docker 鏡像包含了很多只讀層,每一層都由一個 Dockerfile 指令構成,這些層堆疊在一起,每一層都是前一層變化的增量。例如:

FROM ubuntu:18.04COPY . /appRUN make /appCMD python /app/app.py

每條指令都會創建一層:

  • FROM:從 ubuntu:18.04 Docker 鏡像創建了一層,也作為基礎鏡像層。
  • COPY:從 Docker 客戶端的當前目錄添加文件。
  • RUN:執行 make 命令.
  • CMD:指定要在容器中運行的命令。

上述就是一個簡單的 Dockerfile 文件,再通過 docker build -t 命令便可直接構建出鏡像。

在這里就不過多介紹 Dockerfile 的各個指令的用法,更多更詳細的可參考:Dockerfile reference

3、Dockerfile 的最佳實踐

本節將列舉出一些最佳實踐技巧,來幫助我們更好的寫好 Dockerfile。

3.1 盡可能使用官方鏡像作為基礎鏡像

Docker 鏡像是基于基礎鏡像構建而來,因此選擇的基礎鏡像越恰當,我們要做的底層工作就越少。比如,如果構建一個 Java 應用鏡像,選擇一個 openjdk 鏡像作為基礎比選擇一個 alpine 鏡像更簡單。

盡可能使用當前的官方鏡像作為基礎鏡像,無論是從鏡像大小,還是安全性來講,都是比較可靠的。

下面的一些鏡像,可根據使用場景來選擇合適的基礎鏡像:

鏡像名稱 大小 說明和使用場景
busybox 754.7 KB 一個超級簡化版嵌入式 Linux 系統。臨時測試用。
alpine 2.68 MB 一個面向安全的、輕量級的Linux系統,基于musl libc 和 busybox。主要用于測試,也可用于生產環境。
centos 79.65 MB 主要用于生產環境,支持CentOS/Red Hat,常用于追求穩定性的企業應用。
ubuntu 29.01 MB 主要用于生產環境,常用于人工智能計算和企業應用。
debian 52.4 MB 主要用于生產環境。
openjdk 161.02 MB 主要用于 Java 應用。

3.2 減少 Dockerfile 指令的行數

Dockerfile 中每一行指令都代表了一層,多一層都可能帶來鏡像大小變大。

因此,在實際編寫 Dockerfile 時,可以將同類操作放在一起來避免多行指令,更有助于促進層緩存。比如將多條 RUN 操作進行合并,并用 ;\\ 或者 && 連接在一起。

(減少指令行數,并不意味著越少越好,需要從改動頻繁程度來決定是否合并為一條指令。)

例如下面的 Dockerfile,會執行多條命令,通過 ;\\ 連接將其用一條 RUN 指令來完成。

FROM node:6.14LABEL MAINTAINER xcbeyondRUN npm install gitbook-cli -g;\\
   gitbook -V; \\
   npm install svgexport -g --unsafe-permCMD ["/bin/sh"]

3.3 改動不頻繁的內容往前放

對于 Docker 鏡像而言,每一層都代表了 Dockerfile 中的一行指令,每一層都是前一層變化的增量。例如一個 Docker 鏡像有ABCD 四層,B 層修改了,那么 BCD 都會變化。

因此,在編寫 Dockerfile 時,盡量將改動不頻繁的內容往前放,即:將系統依賴往前寫,因為像 apt, yum 這些安裝的東西,是很少修改的。然后寫應用的庫依賴,比如 pip install,最后 copy 應用,編譯應用。

例如下面這個 Dockerfile,就會在每次代碼改變的時候都重新 Build 大部分層,即使只改了一個頁面的標題。

FROM python:3.7-buster # copy sourceRUN mkdir -p /opt/appCOPY myapp /opt/app/myapp/WORKDIR /opt/app# install dependencies nginxRUN apt-get update && apt-get install nginxRUN pip install -r requirements.txtRUN chown -R www-data:www-data /opt/app # start serverEXPOSE 8020STOPSIGNAL SIGTERMCMD ["/opt/app/start-server.sh"]

我們可以改成,先安裝 Nginx,再單獨 copy requirements.txt,然后安裝 pip 依賴,最后 copy 應用代碼。

FROM python:3.7-buster # install dependencies nginxRUN apt-get update && apt-get install nginxCOPY myapp/requirements.txt /opt/app/myapp/requirements.txtRUN pip install -r requirements.txt # copy sourceRUN mkdir -p /opt/appCOPY myapp /opt/app/myapp/WORKDIR /opt/app RUN chown -R www-data:www-data /opt/app # start serverEXPOSE 8020STOPSIGNAL SIGTERMCMD ["/opt/app/start-server.sh"]

3.4 編譯和運行需分離

我們在編譯應用時很多時候會用到很多編譯工具、編譯環境,例如:node、Golang 等,但是編譯后,運行時卻不再需要。這樣的編譯環境往往占用很大,使得鏡像額外變大。

因此,可以將應用事先在某個固定編譯環境編譯完成,得到編譯后的二進制文件,再將其 COPY 到鏡像中即可,這樣鏡像中只包含應用的運行二進制文件。

例如下面這個 Dockerfile,將 Golang 程序編譯好的二進制文件 app,構建到鏡像中:

FROM alpine:latestLABEL maintainer xcbeyondWORKDIR /appCOPY app /appCMD ["/app/app"]

3.5 刪除不需要的依賴項

Docker 鏡像應該盡可能小。在編寫 Dockerfile 時僅包含基本內容,不要引入無關內容,從而使得鏡像大小更小、構建速度更快,并且減少受攻擊的可能面。

鏡像更小,也更利于存放到鏡像倉庫,減少網絡帶寬開銷。

不要安裝應用程序實際不使用的任何包、庫。

3.6 避免憑證構建到鏡像

這是最常見和最危險的 Dockerfile 問題之一。在構建鏡像過程中,復制配置文件可能很誘人,但你切記可能會引入很大的安全隱患。

在 Dockerfile 中通過 COPY 指令將任何配置文件內容都復制到你的鏡像,并且任何可以訪問它的人都可以訪問它。如果這個配置文件中,無意間包含了數據庫密碼配置,那么你就徹底將這些密碼暴露給了所有使用該鏡像的所有人。

為了避免這類問題,必須將配置密鑰、敏感數據只能提供給具體的容器,而不是提供給構建它們的鏡像。可使用環境變量、掛載卷等方式在容器啟動時注入數據。這樣就避免了意外的信息暴露,并確保你的鏡像可跨環境重復使用。


感謝您的閱讀,也歡迎您發表關于這篇文章的任何建議,關注我,技術不迷茫!

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 容器
    +關注

    關注

    0

    文章

    494

    瀏覽量

    22044
  • 鏡像
    +關注

    關注

    0

    文章

    162

    瀏覽量

    10697
  • Docker
    +關注

    關注

    0

    文章

    454

    瀏覽量

    11812
收藏 人收藏

    評論

    相關推薦

    C編程最佳實踐.doc

    C編程最佳實踐.doc
    發表于 08-17 14:37

    Dockerfile最佳實踐

    ”微服務一條龍“最佳指南-“最佳實踐”篇:Dockerfile
    發表于 07-11 16:22

    Dockerfile使用規則

    Dockerfile編寫規范
    發表于 08-12 14:30

    變量聲明最佳實踐

    所以我們開始編寫32位和16位代碼,并過渡到MPLAB X和XC編譯器。我想到的一個主題是聲明變量的最佳實踐。常規IpType。h或類型。h pr STDIN。或It8或字節char等任何想法,走哪條路?
    發表于 09-30 12:01

    虛幻引擎的紋理最佳實踐

    紋理是游戲不可或缺的一部分。 這是一個藝術家可以直接控制的領域,以提高游戲的性能。 本最佳實踐指南介紹了幾種紋理優化,這些優化可以幫助您的游戲運行得更流暢、看起來更好。 最佳實踐系列指
    發表于 08-28 06:39

    MySql5.6性能優化最佳實踐

    MySql5.6性能優化最佳實踐
    發表于 09-08 08:47 ?13次下載
    MySql5.6性能優化<b class='flag-5'>最佳</b><b class='flag-5'>實踐</b>

    全面詳解Dockerfile文件

    Docker 可以通過讀取 Dockerfile 中的指令自動構建鏡像。Dockerfile 是一個文本文檔,其中包含了用戶創建鏡像的所有命令和說明。 一、 變量 變量用
    的頭像 發表于 09-22 15:38 ?1851次閱讀

    DevOps最佳實踐

      遵循上述最佳實踐,組織可以開發和自動化其解決方案的交付過程,以有效地實現其業務目標。
    的頭像 發表于 08-15 14:41 ?923次閱讀

    鏡像構建Dockerfile的介紹

    Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。
    的頭像 發表于 09-06 09:36 ?1108次閱讀

    圖像傳感器處理和最佳實踐

    圖像傳感器處理和最佳實踐
    發表于 11-15 20:30 ?0次下載
    圖像傳感器處理和<b class='flag-5'>最佳</b><b class='flag-5'>實踐</b>

    SAN管理最佳實踐指南

    電子發燒友網站提供《SAN管理最佳實踐指南.pdf》資料免費下載
    發表于 08-29 09:20 ?0次下載
    SAN管理<b class='flag-5'>最佳</b><b class='flag-5'>實踐</b>指南

    SAN設計和最佳實踐指南

    電子發燒友網站提供《SAN設計和最佳實踐指南.pdf》資料免費下載
    發表于 09-01 11:02 ?0次下載
    SAN設計和<b class='flag-5'>最佳</b><b class='flag-5'>實踐</b>指南

    Windows 10遷移的最佳實踐

    電子發燒友網站提供《Windows 10遷移的最佳實踐.pdf》資料免費下載
    發表于 09-07 15:37 ?0次下載
    Windows 10遷移的<b class='flag-5'>最佳</b><b class='flag-5'>實踐</b>

    Dockerfile定義Docker鏡像的構建過程

    了解Dockerfile Dockerfile 是一個文本文件,用于定義 Docker 鏡像的構建過程。它以指令的形式描述了如何構建鏡像,從基礎鏡像開始逐步添加配置、文件和依賴,最終形成我們所需
    的頭像 發表于 09-30 10:22 ?2506次閱讀

    如何使用dockerfile創建鏡像

    Docker是一個開源的平臺,用于快速構建、打包、部署應用程序的容器化工具。而Dockerfile是一個文本文件,包含了一組可自動化構建Docker鏡像的指令。本文將詳細介紹
    的頭像 發表于 11-23 09:52 ?706次閱讀