日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

开发者如何快速精简容器云镜像?| 技术头条

發布時間:2024/9/27 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开发者如何快速精简容器云镜像?| 技术头条 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

戳藍字“CSDN云計算”關注我們哦!



作者:阿木


接觸過容器云或者用過容器的同學一般都會遇到容器鏡像占用空間很大的問題,遇到此類問題的時候大部分同學可能更加習慣于為容器的鏡像倉庫增加磁盤空間,當然這種方式無可厚非,畢竟這種方式可以幫助我們快速的解決掉手里的問題。

?

除了上面擴磁盤的解決方式,其實我們還可以采用縮減容器鏡像的方式,此種方式不但可以幫助我們節省添加新磁盤的開支還可減少我們制作鏡像和傳輸鏡像的時間。優化的比較好的鏡像占用的空間基本和應用的文件占用的空間相當,基本不會占用太多的額外存儲空間。下面我們會具體看一下。?

?

?

接觸過Docker 的同學都知道Dockerfile 是一些指令的組成,且Dockerfile?文件中的每條指令對應著Linux?操作系統中的一條命令,當我們構建鏡像時Docker 程序會將這些Dockerfile指令翻譯成Linux可執行的命令。

?

Dockerfile 中每一條指令都會創建一個鏡像層,隨著指令的執行繼而會增加鏡像整體的大小。

?

Dockerfile?文件有自己的書寫格式和支持的命令,常用Dockerfile 指令如下:

FROM ?指定基鏡像。

?

MAINTAINER ?設置鏡像的作者信息,如作者姓名、郵箱等。

?

COPY ?將文件從本地復制到鏡像,拷貝前需要保證本地源文件存在。

?

ADD ?與 COPY 類似,復制文件到鏡像。不同的是,如果文件是歸檔文件(tar, zip, tgz, xz 等),會被自動解壓。

?

ENV ?設置環境變量,格式: ENV key=value或ENV key value,運行容器后,可直接在容器中使用。

?

EXPOSE ?暴露容器中指定的端口,只是一個聲明,主要用戶了解應用監聽的端口。

?

VOLUME ?掛載卷到容器,需要注意的是,保存鏡像時不會保存卷中的數據。

?

WORKDIR ?設置當前工作目錄,后續各層的當前目錄都被指定。

?

RUN ?在容器中運行指定的命令。

?

CMD ?容器啟動時運行的命令。Dockerfile 中可以有多個 CMD 指令,但只有最后一個生效。CMD 可以被 docker run 之后的參數替換。

?

ENTRYPOINT ?設置容器啟動時運行的命令。Dockerfile 中可以有多個 ENTRYPOINT 指令,但只有最后一個生效。CMD 或 docker run 之后的參數會被當做參數傳遞給 ENTRYPOINT,這個是與CMD的區別。

?

精簡鏡像的好處不言而喻,即可以節省存儲存儲空間也可,也可減少鏡像傳輸時間,減少帶寬的消耗,加快傳輸。

?

在開始制作鏡像之前,我們先了解一下容器鏡像的基本基本理論知識。

?

容器鏡像中最重要的概念就是layers,即鏡像層。

?

?

鏡像層依賴于一系列的底層技術,比如文件系統(filesystems)、寫時復制(copy-on-write)、聯合掛載(union mounts)等技術,這些技術的細節在此我們不再贅述,感興趣的同學可以直接直接查看Docker 官方文檔(https://docs.docker.com/storage/storagedriver/)進行學習。

?

總的來說,精簡鏡像我們最需要記住的一句話即:

?

“在Dockerfile中,每條指令都會創建一個鏡像層,繼而會增加鏡像整體的大小。”

?

下面我們以一個示例來說明一下:

?

我們pull 一個鏡像,以busybox為例:

?

[root@work ~]# docker pull hub.c.163.com/library/busybox:latest

Trying to pull repository hub.c.163.com/library/busybox ...

latest: Pulling from hub.c.163.com/library/busybox

aab39f0bc16d: Pull compl`ete

Digest: sha256:662af1d642674367b721645652de96f9c147417c2efb708eee4e9b7212697762

Status: Downloaded newer image for hub.c.163.com/library/busybox:latest

?

#?看下鏡像大小

[root@work ~]# docker images | grep busybox

hub.c.163.com/library/busybox ?????????????????????????latest ??????????????????????????????????????????d20ae45477cb ???????18 months ago ??????1.129 MB

?

從上面結果看我們pull下來的鏡像大小只有1.129MB。

?

下面我們編寫一個Dockerfile文件,文件中我們新建一個目錄,目錄中新建一個100MB的文件,最后我們刪掉新建的文件。

?

Dockerfile?內容如下:

?

#基鏡像

FROM hub.c.163.com/library/busybox:latest

#新建目錄

RUN mkdir /tmp/dir1

#新建一個100MB的文件

RUN dd if=/dev/zero of=/tmp/dir1/file1 bs=1M count=100

#刪除文件

RUN rm /tmp/dir1/file1

?

從Dockerfile 內容看,其實我們基本什么都沒干。

?

然后我們用這個Dockerfile構建新建的鏡像,并查看新鏡像的大小:

?

[root@work ~]# docker build -t busybox:v1 .

Sending build context to Docker daemon 1.307 GB

Step 1 : FROM hub.c.163.com/library/busybox:latest

?---> d20ae45477cb

Step 2 : RUN mkdir /tmp/dir1

?---> Running in 63fa5f27c779

?---> da95ea8ae5ee

Removing intermediate container 63fa5f27c779

Step 3 : RUN dd if=/dev/zero of=/tmp/dir1/file1 bs=1M count=100

?---> Running in d3e8bbb4f151

100+0 records in

100+0 records out

104857600 bytes (100.0MB) copied, 0.247500 seconds, 404.0MB/s

?---> 42b721238144

Removing intermediate container d3e8bbb4f151

Step 4 : RUN rm -rf /tmp/dir1/file1

?---> Running in 6b51b633fb21

?---> 04096cc5d718

Removing intermediate container 6b51b633fb21

Successfully built 04096cc5d718

?

#?查看鏡像信息

[root@work ~]# docker images | grep busybox

busybox ???????????????????????????????????????????????v1 ??????????????????????????????????????????????04096cc5d718 ???????58 seconds ago ?????106 MB

hub.c.163.com/library/busybox ?????????????????????????latest ??????????????????????????????????????????d20ae45477cb ???????18 months ago ??????1.129 MB

?

從上面的結果可以看出,雖然在Dockerfile中我們將新建的100MB的文件刪除了,但新鏡像的大小仍大于100MB。

?

多出了100多MB,這是為何?其實這點和git類似,Docker鏡像和git都用到了寫時復制技術,git每次提交時都會保存一個文件的版本,Dockerfile每行指令都會增加整體鏡像的大小,即使我們什么都沒做。

?

下面我們開始說下本文的重點:鏡像精簡。

?

我們以最常見的nosql數據庫Redis為例,一步步來介紹如何制作更精簡的Docker 鏡像。

?

首先我們編寫下構建Redis鏡像的Dockerfile文件,具體內容如下:

FROM hub.c.163.com/library/ubuntu:trusty

#redis 版本

ENV VER ????3.0.0

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

RUN apt-get update

#安裝依賴的工具

RUN apt-get install -y ?curl make gcc

#下載redis源碼包并解壓

RUN curl -L $TARBALL | tar zxv

#進入解壓后的目錄

WORKDIR ?redis-$VER

#編譯redis源碼

RUN make

#安裝redis

RUN make install

WORKDIR /

#清理前面安裝的依賴工具

RUN apt-get remove -y --auto-remove curl make gcc

RUN apt-get clean

RUN rm -rf /var/lib/apt/lists/* ?/redis-$VER

#運行redis

CMD ["redis-server"]

?

利用上面的Dockerfile 構建鏡像:

[root@work ~]# docker build -t redis:3.0.0 .

……

……

Removing intermediate container b55656487022

Successfully built 7df9c7899ae3

????

查看構建出的鏡像大小:

[root@work ~]# docker images | grep redis

redis ?????????????????????????????????????????????????3.0.0 ???????????????????????????????????????????7df9c7899ae3 ???????10 hours ago ???????359.7 MB

從結果看構建出優化前的鏡像約為360MB。

?

下面我們逐步優化。?

?

1.?選用更小的基鏡像

?

常用的linux系統一般有CentOS、Debian、Ubuntu,三者中Debian更輕量,且Debian系統鏡像中提供的功能一般也是夠用的,三個系統鏡像尺寸對比如下:

????????

鏡像名稱????????????標簽?????????鏡像?ID ???????鏡像大小

-------- ?????????????------ ???????------------ ?????????--------

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:wheezy?作為即鏡像,重新進行構建:

?

Dockerfile內容:

FROM hub.c.163.com/library/debian:wheezy

#redis 版本

ENV VER ????3.0.0

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

RUN apt-get update

#安裝依賴的工具

RUN apt-get install -y ?curl make gcc

#下載redis源碼包并解壓

RUN curl -L $TARBALL | tar zxv

#進入解壓后的目錄

WORKDIR ?redis-$VER

#編譯redis源碼

RUN make

#安裝redis

RUN make install

WORKDIR /

#清理前面安裝的依賴工具

RUN apt-get remove -y --auto-remove curl make gcc

RUN apt-get clean

RUN rm -rf /var/lib/apt/lists/* ?/redis-$VER

#運行redis

CMD ["redis-server"]

?

構建新鏡像:

[root@work ~]# docker build -t redis:3.0.0-v2 .

……

……

Removing intermediate container 3498689792ce

Successfully built 4faa1aa0936d

?

對比兩個鏡像大小:

[root@work ~]# docker images | grep redis

redis ?????????????????????????????????????????????????3.0.0-v2 ????????????????????????????????????????4faa1aa0936d ???????38 seconds ago ?????228.5 MB

redis ?????????????????????????????????????????????????3.0.0 ???????????????????????????????????????????7df9c7899ae3 ???????11 hours ago

?

從結果看更換基鏡像后的新鏡像減少了37%,精簡效果還算可以,但精簡效果并未達到我們的目標。

?

如果仔細看的話我們會發現只有85MB的debian基鏡像,在構建后增加到了228MB可見此處還有很大的優化空間,后續的優化就需要用到我們在上文中說到的鏡像層相關的知識了。

??????

?

2.?合并Dockerfile中指令

?

Dockerfile?中指令的合并一般是指RUN指令的合并。

?

我們可以通過&&符號和/?將Dockerfile?中的多個RUN指令合并成一條RUN 指令,此種方式一般精簡效果較好。

?

優化后的Dockerfile 內容如下:

FROM hub.c.163.com/library/debian:wheezy

#redis 版本

ENV VER ????3.0.0

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

RUN apt-get update && \

apt-get install -y ?curl make gcc &&\

curl -L $TARBALL | tar zxv ?&& \

cd ?redis-$VER ?&& \

make ?&& \

make install && \

cd / ?&& \

apt-get remove -y --auto-remove curl make gcc && \

apt-get clean ?&& \

rm -rf /var/lib/apt/lists/* ?/redis-$VER

#運行redis

CMD ["redis-server"]

?

構建新鏡像:

?

[root@work ~]# docker build -t redis:3.0.0-v3 .

……

……

Removing intermediate container 9e5cffcd8bdb

Successfully built dafd91993dfb

?

查看鏡像大小:

[root@work ~]# docker images | grep redis

redis ?????????????????????????????????????????????????3.0.0-v3 ????????????????????????????????????????dafd91993dfb ???????33 seconds ago ?????102.3 MB

redis ?????????????????????????????????????????????????3.0.0-v2 ????????????????????????????????????????4faa1aa0936d ???????15 minutes ago ?????228.5 MB

redis ?????????????????????????????????????????????????3.0.0 ???????????????????????????????????????????7df9c7899ae3 ???????11 hours ago ???????359.7 MB

?

從結果看鏡像大小約縮減72%,可見合并Dockerfile指令的方式精簡效果較明顯,新鏡像只比基鏡像增加約10MB。

合并Dockerfilec指令精簡鏡像這種方式是最常用的精簡鏡像尺寸的方式。

?

3.?使用最精簡的基鏡像

?

上文中第1步中,我們使用的基鏡像為Debian鏡像,約89MB,但如果我們只是安裝Redis 服務的話不一定非得使用這么大的系統鏡像,我們可以借助一些更小的鏡像,如scratch、busybox、alpine等,這些鏡像大小往往小于5MB,因此我們可以直接以此作為基鏡像來構建新的Redis鏡像。

?

此處我們以scratch作為基鏡像構建Redis。scratch鏡像往往只有1~5MB大小。

?

Scrach?是一個空鏡像,只能用于構建鏡像。在構建一些基礎鏡像,如debian、busybox時非常有用。Scrach也常用于構建超小的鏡像,如構建一個只包含所有庫的二進制文件。

?

但使用最精簡的基鏡像我們還需要做些額外的工作,具體過程見下文。

?

4.?提取.so庫

?

了解過Redis源碼的話大家會知道Redis?開發語言為C語言,會依賴一些.so庫,因此我們需要先準備好編譯Redis 所需的.so文件。

?

我們通過前面構建好的redis:3.0.0-v3鏡像運行容器,然后進入容器中獲取下redis依賴的.so文件。

?

# 后臺運行容器:

[root@work ~]# docker run --name redisv3 -d ?redis:3.0.0-v3

ab361e7fc2e70b5b45fa1545917ee92158bb859e833c3f7fcfb80e43bb69cb0c

?

# 查看容器運行狀態

[root@work ~]# docker ps

CONTAINER ID ???????IMAGE ??????????????COMMAND ????????????CREATED ????????????STATUS ?????????????PORTS ??????????????NAMES

ab361e7fc2e7 ???????redis:3.0.0-v3 ?????"redis-server" ?????3 seconds ago ??????Up 3 seconds ???????????????????????????redisv3

?

#?進入容器

[root@work ~]# docker exec -ti redisv3 /bin/bash

root@ab361e7fc2e7:/#

?

#?查看redis-server?二進制文件位置

root@ab361e7fc2e7:/# which redis-server

/usr/local/bin/redis-server

?

#?查看redis-server依賴的.so文件

root@ab361e7fc2e7:/# ldd /usr/local/bin/redis-server

linux-vdso.so.1 => ?(0x00007ffedfd01000)

libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0de7a5e000)

libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0de785a000)

libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0de763d000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0de72b0000)

/lib64/ld-linux-x86-64.so.2 (0x00007f0de7ce4000)

?

將編譯Redis 需要的所有依賴打包:

root@ab361e7fc2e7:/# mkdir so

root@ab361e7fc2e7:/# cp usr/local/bin/redis-server so/

root@ab361e7fc2e7:/# cp lib/x86_64-linux-gnu/libm.so.6 so/

root@ab361e7fc2e7:/# cp lib/x86_64-linux-gnu/libpthread.so.0 so/

root@ab361e7fc2e7:/# cp lib/x86_64-linux-gnu/libc.so.6 so/ ?????

root@ab361e7fc2e7:/# cp lib64/ld-linux-x86-64.so.2 so/ ?

root@ab361e7fc2e7:/# cd so

root@ab361e7fc2e7:/# tar zcvf so.tar.gz ./*

so/

so/redis-server

so/libm.so.6

so/libpthread.so.0

so/libc.so.6

so/ld-linux-x86-64.so.2

?

#?將打包好的文件從容器拷貝出來

[root@work ~]# docker cp redisv3:/so/so.tar.gz .

?

編寫Dockerfile 文件,具體內容如下:

?

FROM scratch

# 添加依賴的庫文件

ADD ?so.tar.gz ?/

# redis 配置文件,需要自己準備一份

COPY redis.conf ????/etc/redis/redis.conf

# 暴露的端口

EXPOSE 6379

CMD ["redis-server"]

?

構建新鏡像:

?

[root@work ~]# docker build -t redis:3.0.0-v4 .

Sending build context to Docker daemon 1.316 GB

Step 1 : FROM scratch

?--->

Step 2 : ADD so.tar.gz /

?---> Using cache

?---> 82b2b6def214

Step 3 : COPY redis.conf /etc/redis/redis.conf

?---> 3f382da261be

Removing intermediate container 60af6a5ab042

Step 4 : EXPOSE 6379

?---> Running in 78c541686668

?---> 043ed6cf87e0

Removing intermediate container 78c541686668

Step 5 : CMD redis-server

?---> Running in 2c8b9fb0547d

?---> 75d828ebf3aa

Removing intermediate container 2c8b9fb0547d

Successfully built 75d828ebf3aa

?

對比鏡像大小:

[root@work ~]# docker images | grep redis

redis ?????????????????????????????????????????????????3.0.0-v4 ????????????????????????????????????????75d828ebf3aa ???????30 seconds ago ?????6.938 MB

redis ?????????????????????????????????????????????????3.0.0-v3 ????????????????????????????????????????dafd91993dfb ???????About an hour ago ??102.3 MB

redis ?????????????????????????????????????????????????3.0.0-v2 ????????????????????????????????????????4faa1aa0936d ???????About an hour ago ??228.5 MB

redis ?????????????????????????????????????????????????3.0.0 ???????????????????????????????????????????7df9c7899ae3 ???????12 hours ago ???????359.7 MB

?

從結果看精簡效果顯著提高,基于scratch構建的新鏡像大小只有6.9MB,相比之前的359MB、228MB、102MB,新鏡像空間占用已經很少。

?

以上即是本文精簡Docker 鏡像的整個過程。

?

除了上面我們介紹的精簡方法之外還有一些常見的精簡方式,如使用鏡像壓縮工具docker-squash,但此種方式壓縮效果并不明顯,因此在此我們并未介紹,感興趣的同學可以自己嘗試下。




福利

掃描添加小編微信,備注“姓名+公司職位”,加入【云計算學習交流群】,和志同道合的朋友們共同打卡學習!



推薦閱讀:

  • 趣挨踢 | 用大數據扒一扒蔡徐坤的真假流量粉

  • 姚期智提出的"百萬富翁"難題被破解? 多方安全計算MPC到底是個什么鬼?

  • 全民 AI !教育部宣布 35 所高校新增 AI 本科專業

  • 深度 | 人工智能究竟能否實現?

  • 程序媛報告:調查了 12,000 名女性開發者發現,女性比男性更懂 Java!

  • 程序員怒了!你敢削減專利獎金,我敢拒絕提交代碼!


喜歡就點擊“在看”吧


總結

以上是生活随笔為你收集整理的开发者如何快速精简容器云镜像?| 技术头条的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。