<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          七步制作精簡鏡像,So easy

          共 9997字,需瀏覽 20分鐘

           ·

          2021-10-30 16:30

          文章來自黃慶兵老師的網(wǎng)易蜂巢《玩轉(zhuǎn) Docker 鏡像》系列https://github.com/bingohuang/play-docker-images,原本分為上下兩篇,這里由生態(tài)君整合成一篇便于閱讀。希望能對大家有所幫助。

          目錄

          • 介紹

          • 鏡像層(Layers)

          • 制作步驟

            • lab-1:初始化構(gòu)建 Redis 鏡像

            • lab-2:優(yōu)化基礎(chǔ)鏡像

            • lab-3:串聯(lián) Dockerfile 指令

            • lab-4:壓縮你的鏡像

            • lab-5:使用最精簡的 base image

            • lab-6:提取動態(tài)鏈接的 .so 文件

            • lab-7:為 Go 應(yīng)用構(gòu)建精簡鏡像

          • 總結(jié)

          • 參考

          作者簡介: 黃慶兵,畢業(yè)于浙大,工作于網(wǎng)易,從事云計算、Docker和Go相關(guān)開發(fā)及布道工作;喜歡開源,樂于分享,勤于布道,折騰過開源小工具,制作過Docker課程,分享過 Gopher Meetup。我的 Github 賬號:https://github.com/bingohuang,歡迎一起來 寫 Go 玩 Docker!

          img

          介紹

          前段時間網(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

          有些鏡像都不是我們自己來打包的(比如下載公共鏡像),那是否有一些通用的精簡 Docker 鏡像的手段呢?答案是肯定的,甚至有的鏡像可以精簡 98%。精簡鏡像大小的好處不言而喻,既節(jié)省了存儲空間,又能節(jié)省帶寬,加快傳輸?shù)?。那好,接下來就請跟隨我來學(xué)習(xí)怎么制作精簡 Docker 鏡像。

          鏡像層(Layers)

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

          img

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

          在 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),該文件分配了100M大小
          3. 再把這個大文件刪除

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

          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 鏡像。

          lab-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:指定工作目錄,相當(dāng)于指令 cd
          • CMD:指定鏡像默認(rèn)執(zhí)行的命令,此處默認(rèn)執(zhí)行 redis-server 命令來啟動 redis

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

          $?docker?build??-t?redis:lab-1??.

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

          查看大?。?/strong>

          LabiamgeBaseLang.red[*]Size (MB)?? Memo
          1redisubuntuCdyn347.3?? base ubuntu

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

          lab-2:優(yōu)化基礎(chǔ)鏡像

          精簡1:選用更小的基礎(chǔ)鏡像。

          常用的 Linux 系統(tǒng)鏡像一般有 ubuntu、centos、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>

          LabimageBaseLang.red[*]Size (MB)?? Memo
          01redisubuntuCdyn347.3?? base ubuntu
          02redisdebianCdyn305.7?? base debian

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

          lab-3:串聯(lián) Dockerfile 指令

          精簡2:串聯(lián)你的 Dockerfile 指令(一般是 RUN 指令)。

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

          優(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>

          LabImageBaseLang.red[*]Size (MB)?? Memo
          01redisubuntuCdyn347.3?? base ubuntu
          02redisdebianCdyn305.7?? base debian
          03redisdebianCdyn151.4?? cmd chaining

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

          lab-4:壓縮你的鏡像

          優(yōu)化3:試著用命令或工具壓縮你的鏡像。

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

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

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

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

          下載安裝:

          https://github.com/jwilder/docker-squash#installation

          壓縮操作:

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

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

          對比大小:

          LabImageBasePL.red[*]Size (MB)?? Memo
          01redisubuntuCdyn347.3?? base ubuntu
          02redisdebianCdyn305.7?? base debian
          03redisdebianCdyn151.4?? cmd chaining
          04redisdebianCdyn151.4?? docker-squash

          好吧,從這里看起來并沒有太大作用,所以我只能說試著,而不要報太大期望。

          lab-5:使用最精簡的 base image

          img

          使用 scratch 或者 busybox 作為基礎(chǔ)鏡像。

          關(guān)于 scratch:

          • 一個空鏡像,只能用于構(gòu)建鏡像,通過 FROM scratch
          • 在構(gòu)建一些基礎(chǔ)鏡像,比如 debianbusybox,非常有用
          • 用于構(gòu)建超少鏡像,比如構(gòu)建一個包含所有庫的二進制文件

          關(guān)于 busybox

          • 只有 1~5M 的大小
          • 包含了常用的 UNIX 工具
          • 非常方便構(gòu)建小鏡像

          這些超小的基礎(chǔ)鏡像,結(jié)合能生成靜態(tài)原生 ELF 文件的編譯語言,比如C/C++,比如 Go,特別方便構(gòu)建超小的鏡像。

          cloudcomb-logo(C語言開發(fā)) 就是用到了該原理,才能構(gòu)建出 585 字節(jié)的鏡像。

          redis 同樣使用 C語言 開發(fā),看來也有很大的優(yōu)化空間,下面這個實驗,讓我們介紹具體的操作方法。

          lab-6:提取動態(tài)鏈接的 .so 文件

          實驗上下文:

          $?cat?/etc/os-release

          NAME="Ubuntu"
          VERSION="14.04.2?LTS,?Trusty?Tahr"
          $?uname?-a
          Linux?localhost?3.13.0-46-generic?#77-Ubuntu?SMP
          Mon?Mar?2?18:23:39?UTC?2015
          x86_64?x86_64?x86_64?GNU/Linux

          隆重推出 ldd:打印共享的依賴庫

          $?ldd??redis-3.0.0/src/redis-server
          ????linux-vdso.so.1?=>??(0x00007fffde365000)
          ????libm.so.6?=>?/lib/x86_64-linux-gnu/libm.so.6?(0x00007f307d5aa000)
          ????libpthread.so.0?=>?/lib/x86_64-linux-gnu/libpthread.so.0?(0x00007f307d38c000)
          ????libc.so.6?=>?/lib/x86_64-linux-gnu/libc.so.6?(0x00007f307cfc6000)
          ????/lib64/ld-linux-x86-64.so.2?(0x00007f307d8b9000)

          將所有需要的 .so 文件打包:

          $?tar?ztvf?rootfs.tar.gz
          4485167??2015-04-21?22:54??usr/local/bin/redis-server
          1071552??2015-02-25?16:56??lib/x86_64-linux-gnu/libm.so.6
          ?141574??2015-02-25?16:56??lib/x86_64-linux-gnu/libpthread.so.0
          1840928??2015-02-25?16:56??lib/x86_64-linux-gnu/libc.so.6
          ?149120??2015-02-25?16:56??lib64/ld-linux-x86-64.so.2

          再制作成 Dockerfile:

          FROM?scratch
          ADD??rootfs.tar.gz??/
          COPY?redis.conf?????/etc/redis/redis.conf
          EXPOSE?6379
          CMD?["redis-server"]

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

          $?docker?build??-t?redis-05??.

          查看大?。?/p>

          Lab
          BasePL.red[*]Size (MB)?? Memo
          01redisubuntuCdyn347.3?? base ubuntu
          02redisdebianCdyn305.7?? base debian
          03redisdebianCdyn151.4?? cmd chaining
          04redisdebianCdyn151.4?? docker-squash
          05redisscratchCdyn7.73?? rootfs: .so

          哇!顯著提高啦!

          測試一下:

          $?docker?run?-d?--name?redis-05?redis-05

          $?redis-cli??-h??\
          ??$(docker?inspect?-f?'{{.NetworkSettings.IPAddress}}'?redis-05)

          $?redis-benchmark??-h??\
          ??$(docker?inspect?-f?'{{.NetworkSettings.IPAddress}}'?redis-05)

          總結(jié)一下:

          1. ldd 查出所需的 .so 文件
          2. 將所有依賴壓縮成 rootfs.tarrootfs.tar.gz,之后打進 scratch 基礎(chǔ)鏡像

          lab-7:為 Go 應(yīng)用構(gòu)建精簡鏡像

          Go 語言天生就方便用來構(gòu)建精簡鏡像,得益于它能方便的打包成包含靜態(tài)鏈接的二進制文件。

          打個比方,你有一個 4 MB 大小的包含靜態(tài)鏈接的 Go 二進制,并且將其打進 scratch 這樣的基礎(chǔ)鏡像,你得到的鏡像大小也只有區(qū)區(qū)的 4 MB。這可是包含同樣功能的 Ruby 程序的百分之一啊。

          這里再給大家介紹一個非常好用開源的 Go 編譯工具:golang-builder,并給大家實際演示一個例子

          程序代碼:

          package?main?//?import?"github.com/CenturyLinkLabs/hello"

          import?"fmt"

          func?main()?{
          ????fmt.Println("Hello?World")
          }

          Dockerfile:

          FROM?scratch
          COPY?hello?/
          ENTRYPOINT?["/hello"]

          通過 golang-builder 打包成鏡像:

          docker?run?--rm?\
          ????-v?$(pwd):/src?\
          ????-v?/var/run/docker.sock:/var/run/docker.sock?\
          ????centurylink/golang-builder

          查看鏡像大小(Mac下測試):

          $?docker?images
          REPOSITORY???TAG??????IMAGE?ID???????CREATED??????????VIRTUAL?SIZE
          hello????????latest???1a42948d3224???24?seconds?ago???1.59?MB

          哇!這么省力,就能創(chuàng)建幾 M 大小的鏡像,Go 簡介就是為 Docker 鏡像量身定做的!

          總結(jié)

          我們介紹了鏡像層的知識,并且通過實驗,介紹三種如何精簡鏡像的技巧。這里主要介紹了三種精簡方法:選用更精小的鏡像,串聯(lián) Dockerfile 運行指令,以及試著壓縮你的鏡像。通過這幾個技巧,已經(jīng)可以將 300M 大小的鏡像壓縮到 150M,壓縮率50%到98%,效果還是不錯。

          1. 優(yōu)化基礎(chǔ)鏡像
          2. 串接 Dockerfile 命令:
          3. 壓縮 Docker images
          4. 優(yōu)化程序依賴
          5. 選用更合適的開發(fā)語言


          文章的最后,插播一個福利

          雙十一快到了,阿里云也開始搞活動了,剛好我這邊可以帶大家白Piao?阿里云的服務(wù)器。

          說白了就是大家?可以一分錢不花,就可以領(lǐng)到服務(wù)器,規(guī)格是 2c2m(2vcpu 2G memory) 的機器。

          昨天在朋友圈發(fā)了下,已經(jīng)有 400 人報名參與了,今天這篇文章再說一下,有想參加的朋友,可以加我下微信,備注『服務(wù)器,我統(tǒng)一拉群,帶大家一起薅羊毛。


          參考

          • scratch in Docker Hub[4]

          • Make FROM scratch a special cased 'no-base' spec[5]

          • vDSO (virtual dynamic shared object)[6]

          • Small Docker Images For Go Apps[7] (with golang-builder[8])

          • Building Docker Images for Static Go Binaries[9]

          • Dockerfile Best Practices - take 2[10] - by Michael Crosby, 2014-03-09.

          • Optimizing Docker Images[11] - by Brian DeHamer, 2014-07-28.

          • Squashing Docker Images[12] - by Jason Wilder, 2014-08-19.

          參考資料

          [1]

          這些技術(shù): https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/

          [2]

          一期: https://github.com/bingohuang/play-docker-images/tree/master/stage-01

          [3]

          docker-squash: https://github.com/jwilder/docker-squash

          [4]

          scratch in Docker Hub: https://registry.hub.docker.com/_/scratch/

          [5]

          Make FROM scratch a special cased 'no-base' spec: https://github.com/docker/docker/pull/8827

          [6]

          vDSO (virtual dynamic shared object): http://en.wikipedia.org/wiki/VDSO

          [7]

          Small Docker Images For Go Apps: http://www.centurylinklabs.com/small-docker-images-for-go-apps/

          [8]

          golang-builder: https://github.com/CenturyLinkLabs/golang-builder

          [9]

          Building Docker Images for Static Go Binaries: https://medium.com/@kelseyhightower/optimizing-docker-images-for-static-binaries-b5696e26eb07

          [10]

          Dockerfile Best Practices - take 2: http://crosbymichael.com/dockerfile-best-practices-take-2.html

          [11]

          Optimizing Docker Images: http://www.centurylinklabs.com/optimizing-docker-images/

          [12]

          Squashing Docker Images: http://jasonwilder.com/blog/2014/08/19/squashing-docker-images/



          瀏覽 71
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    欧美三级在线观看视频 | 色婷婷五月在线 | 日本调教视频 | 亚洲人成电影在线播放 | 青青草激情视频 |