溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么精簡Docker鏡像

發(fā)布時間:2021-12-13 17:32:41 來源:億速云 閱讀:174 作者:iii 欄目:云計算

本篇內(nèi)容介紹了“怎么精簡Docker鏡像”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

介紹

前段時間網(wǎng)易蜂巢曾經(jīng)推出蜂巢 Logo T恤,用的正是 Docker 鏡像制作,最神奇的是,它最終的鏡像大小只有 585 字節(jié)。

$ docker images | grep hub.c.163.com/public/logo
REPOSITORY                      TAG           IMAGE ID         CREATED       SIZE
hub.c.163.com/public/logo       latest        6fbdd13cd204     11 days ago   585 B

點擊此處,可以了解該鏡像的制作過程,這其中就用到了不少精簡鏡像的技術(shù),尤其是針對 C 程序的優(yōu)化和精簡。但我們平常開發(fā)肯定不止用 C 語言,甚至有些鏡像都不是我們自己來打包的(比如下載公共鏡像),那是否有一些通用的精簡 Docker 鏡像的手段呢? 答案是肯定的 ,甚至有的鏡像可以精簡 98%。精簡鏡像大小的好處不言而喻,既節(jié)省了存儲空間,又能節(jié)省帶寬,加快傳輸。那好,接下來就請跟隨我來學(xué)習(xí)怎么一步步精簡 Docker 鏡像吧。

鏡像層(Layers)

在開始制作鏡像之前,首先了解下鏡像的原理,而這其中最重要的概念就是鏡像層(Layers)。鏡像層依賴于一系列的底層技術(shù),比如文件系統(tǒng)(filesystems)、寫時復(fù)制(copy-on-write)、聯(lián)合掛載(union mounts)等,幸運的是你可以在很多地方學(xué)習(xí)到這些技術(shù),這里就不再贅述技術(shù)細節(jié)。

怎么精簡Docker鏡像

總的來說,你最需要記住這點:

在 Dockerfile 中, 每一條指令都會創(chuàng)建一個鏡像層,繼而會增加整體鏡像的大小。

舉例來說:

FROM busybox
RUN mkdir /tmp/foo
RUN dd if=/dev/zero of=/tmp/foo/bar bs=1048576 count=100
RUN rm /tmp/foo/bar

以上 Dockerfile 干了這幾件事:

  1. 基于一個官方的基礎(chǔ)鏡像 busybox(只有1M多)

  2. 創(chuàng)建一個文件夾(/tmp/foo)和一個文件(bar)

  3. 為該文件分配了100M大小

  4. 再把這個大文件刪除

事實上,它最終什么也沒做,我們把它構(gòu)建成鏡像看看(構(gòu)建可以參考一期):

docker build -t busybox:test .

再讓我們來對比下原生的 busybox 鏡像大小和我們生成的鏡像大?。?/p>

$ docker images | grep busybox
busybox    test     896c63dbdb96    2 seconds ago    106 MB
busybox    latest   2b8fd9751c4c    9 weeks ago      1.093 MB

出乎意料的是,卻生成了 106 MB 的鏡像。

多出了 100 M,這是為何?這點和 git 類似(都用到了Copy-On-Write技術(shù)),我用 git 做了如下兩次提交(添加了又刪除),請問 A_VERY_LARGE_FILE 還在 git 倉庫中嗎?

$ git add  A_VERY_LARGE_FILE
$ git commit
$ git rm  A_VERY_LARGE_FILE
$ git commit

答案是: 在的 ,并且會占用倉庫的大小。Git 會保存每一次提交的文件版本,而 Dockerfile 中每一條指令都可能增加整體鏡像的大小,即使它最終什么事情都沒做。

精簡步驟

了解了鏡像層知識,有助于我們接下來制作精簡鏡像。這里開始,以最常用的開源緩存軟件 Redis 為例,從一步步試驗,來介紹如何制作更精簡的 Docker 鏡像。

步驟 1:初始化構(gòu)建 Redis 鏡像

直接上 Dockerfile

FROM ubuntu:trusty
ENV VER     3.0.0
ENV TARBALL http://download.redis.io/releases/redis-$VER.tar.gz
# ==> Install curl and helper tools...
RUN apt-get update
RUN apt-get install -y  curl make gcc
# ==> Download, compile, and install...
RUN curl -L $TARBALL | tar zxv
WORKDIR  redis-$VER
RUN make
RUN make install
#...
# ==> Clean up...
WORKDIR /
RUN apt-get remove -y --auto-remove curl make gcc
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*  /redis-$VER
#...
CMD ["redis-server"]

結(jié)合注釋,讀起來并不困難,用到的都是常規(guī)的幾個命令,簡要介紹如下:

  • FROM:頂頭寫,指定一個基礎(chǔ)鏡像,此處基于 ubuntu:trusty

  • ENV:設(shè)置環(huán)境變量,這里設(shè)置了 VERTARBALL 兩個環(huán)境變量

  • RUN:最常用的 Dockerfile 指令,用于運行各種命令,這里調(diào)用了 8 次 RUN 指令

  • WORKDIR:指定工作目錄,相當于指令 cd

  • CMD:指定鏡像默認執(zhí)行的命令,此處默認執(zhí)行 redis-server 命令來啟動 redis

執(zhí)行構(gòu)建:

$ docker build  -t redis:lab-1  .

注:國內(nèi)網(wǎng)絡(luò),更新下載可能會較慢

查看大?。?/strong>

| Lab |  iamge  | Base       | Lang    | .red[*] |  Size (MB) |    Memo               |
|:---:|:--------|:-----------|:-----:|:---:|---------------:|:--------------------------------|
|  1 |  redis  |  `ubuntu`  |   C   | dyn |   347.3        |    base ubuntu        |

動輒就有 300多 M 的大小,不能忍,下面我們開始一步步優(yōu)化。

步驟 2: 優(yōu)化基礎(chǔ)鏡像

方法:選用更小的基礎(chǔ)鏡像。

常用的 Linux 系統(tǒng)鏡像一般有 ubuntucentos、debian,其中debian 更輕量,而且夠用,對比如下:

REPOSITORY          TAG        IMAGE ID         VIRTUAL SIZE
---------------     ------     ------------     ------------
centos              7          214a4932132a     215.7 MB
centos              6          f6808a3e4d9e     202.6 MB
ubuntu              trusty     d0955f21bf24     188.3 MB
ubuntu              precise    9c5e4be642b7     131.9 MB
debian              jessie     65688f7c61c4     122.8 MB
debian              wheezy     1265e16d0c28     84.96 MB

替換 debian:jessie 作為我們的基礎(chǔ)鏡像。

優(yōu)化 Dockerfile:

FROM debian:jessie

#...

執(zhí)行構(gòu)建:

$ docker build  -t redis:lab-2  .

查看大?。?/strong>

| Lab |  image  | Base       | Lang    | .red[*] |  Size (MB) |    Memo               |
|:---:|:--------|:-----------|:-----:|:---:|---------------:|:--------------------------------|
|  01 |  redis  |  `ubuntu`  |   C   | dyn |   347.3        |    base ubuntu        |
|  02 |  redis  |  `debian`  |   C   | dyn |   305.7        |    base debian        |

減少了42M,稍有成效,但并不明顯。細心的同學(xué)應(yīng)該發(fā)現(xiàn),只有 122 MB 的 debian 基礎(chǔ)鏡像,構(gòu)建后增加到了 305 MB,看來這里面肯定有優(yōu)化的空間,如何優(yōu)化就要用到我們開頭說到的 Image Layer 知識了。

步驟 3:串聯(lián) Dockerfile 指令

方法: 串聯(lián)你的 Dockerfile 指令(一般是 RUN 指令)。

Dockerfile 中的 RUN 指令通過 &&/ 支持將命令串聯(lián)在一起,有時能達到意想不到的精簡效果。

優(yōu)化 Dockerfile:

FROM debian:jessie

ENV VER     3.0.0
ENV TARBALL http://download.redis.io/releases/redis-$VER.tar.gz


RUN echo "==> Install curl and helper tools..."  && \
    apt-get update                      && \
    apt-get install -y  curl make gcc   && \
    \
    echo "==> Download, compile, and install..."  && \
    curl -L $TARBALL | tar zxv  && \
    cd redis-$VER               && \
    make                        && \
    make install                && \
    ...
    echo "==> Clean up..."  && \
    apt-get remove -y --auto-remove curl make gcc  && \
    apt-get clean                                  && \
    rm -rf /var/lib/apt/lists/*  /redis-$VER

#...
CMD ["redis-server"]

構(gòu)建:

$ docker build  -t redis:lab-3  .

查看大?。?/p>

| Lab |  Image  | Base       | Lang    | .red[*] |  Size (MB) |    Memo               |
|:---:|:--------|:-----------|:-----:|:---:|---------------:|:--------------------------------|
|  01 |  redis  |  `ubuntu`  |   C   | dyn |   347.3        |    base ubuntu        |
|  02 |  redis  |  `debian`  |   C   | dyn |   305.7        |    base debian        |
|  03 |  redis  |  `debian`  |   C   | dyn |   151.4        |    cmd chaining       |

哇!一下子減少了 50%,效果明顯啊!這是最常用的一個精簡手段了。

步驟 4:壓縮你的鏡像

方法:試著用命令或工具壓縮你的鏡像。

docker 自帶的一些命令還能協(xié)助壓縮鏡像,比如 exportimport

$ docker run -d redis:lab-3
$ docker export 71b1c0ad0a2b | docker import - redis:lab-4

但麻煩的是需要先將容器運行起來,而且這個過程中你會丟失鏡像原有的一些信息,比如:導(dǎo)出端口,環(huán)境變量,默認指令。

所以一般通過命令行來精簡鏡像都是實驗性的,那么這里再推薦一個小工具: docker-squash。用起來更簡單方便,并且不會丟失原有鏡像的自帶信息。

下載安裝:

壓縮操作:

$ docker save redis:lab-3 \
  | sudo docker-squash -verbose -t redis:lab-4  \
  | docker load

注: 該工具在 Mac 下并不好使,請在 Linux 下使用

對比大小:

| Lab |  Image  | Base       | PL    | .red[*] |  Size (MB) |    Memo               |
|:---:|:--------|:-----------|:-----:|:---:|---------------:|:--------------------------------|
|  01 |  redis  |  `ubuntu`  |   C   | dyn |   347.3        |    base ubuntu        |
|  02 |  redis  |  `debian`  |   C   | dyn |   305.7        |    base debian        |
|  03 |  redis  |  `debian`  |   C   | dyn |   151.4        |    cmd chaining       |
|  04 |  redis  |  `debian`  |   C   | dyn |   151.4        |    docker-squash      |

“怎么精簡Docker鏡像”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI