天天看點

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

Docker鏡像

  • 一、Docker鏡像的分層結構
  • 二、Docker鏡像的建構
    • 建構方法一(正常)
    • 建構方法二(Dockerfile)
  • 三、Dockerfile詳解
  • 四、鏡像的封裝及優化
    • Docker封裝rhel7+nginx鏡像執行個體
    • 封裝後鏡像的優化

一、Docker鏡像的分層結構

鏡像的分層結構:

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化
  • 共享主控端的kernel
  • base鏡像提供的是最小的Linux發行版
  • 同一docker主機支援運作多種Linux發行版
  • 采用分層結構的最大好處是:共享資源
Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化
  • Copy-on-Write 可寫容器層
  • 容器層以下所有鏡像層都是隻讀的
  • docker從上往下依次查找檔案
  • 容器層儲存鏡像變化的部分,并不會對鏡像本身進行任何修改
  • 一個鏡像最多127層

二、Docker鏡像的建構

鏡像的分層結構:base image提供了根檔案系統,所有容器資料都分類存放在/var/lib/docker目錄中,可以共享資源,減少網絡帶寬資源占用

建構方法一(正常)

  • docker commit 建構新鏡像三部曲
    • 運作容器
    • 修改容器
    • 将容器儲存為新的鏡像
  • 缺點:

    效率低、可重複性弱、容易出錯

    使用者無法對鏡像進行審計,存在安全隐患

這裡我們先在server1上拉取busybox鏡像

然後進行建構新鏡像三部曲

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化
#運作容器
docker run -it --name demo busybox
#修改容器 (以下指令在容器内運作)
echo helloworld > testfile
#将容器儲存為新的鏡像
docker commit  demo demo:v1
#檢視鏡像
docker images demo:v1
           

将demo容器送出儲存為demo:v1新的鏡像後,檢視比較busybox和demo:v1可以看到demo:v1是在busybox鏡像的基礎上新加了一層

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

建構方法二(Dockerfile)

建立一個Dockerfile

此處需要注意:

  • dockerfile有審計功能,每新加一層鏡像都會有動作審計說明
  • dockerfile不能放在根下,否則會把根下所有資料發送給docker引擎

(1)建立docker目錄,在目錄中建立編輯dockerfile

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

(2)使用dockerfile建立一個demo:v2新的鏡像

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

(3)新的鏡像已經建立為demo:v2,檢視比較busybox和demo:v2可以看到demo:v2是在busybox鏡像的基礎上新加了一層

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

三、Dockerfile詳解

dockerfile常用指令

  • FROM

    指定base鏡像,如果本地不存在會從遠端倉庫下載下傳。

  • MAINTAINER

    設定鏡像的作者,比如使用者郵箱等。

  • COPY

    把檔案從build context複制到鏡像

    支援兩種形式:COPY src dest 和 COPY [“src”, “dest”]

    src必須指定build context中的檔案或目錄

  • ADD

    用法與COPY類似,不同的是src可以是歸檔壓縮檔案,檔案會被自動解壓到dest,也可以自動下載下傳URL并拷貝到鏡像:

    ADD html.tar /var/www

    ADD http://ip/html.tar /var/www

  • ENV

    設定環境變量,變量可以被後續的指令使用:

    ENV HOSTNAME sevrer1.example.com

  • EXPOSE

    如果容器中運作應用服務,可以把服務端口暴露出去:

    EXPOSE 80

  • VOLUME

    申明資料卷,通常指定的是應用的資料挂在點:

    VOLUME ["/var/www/html"]

  • WORKDIR

    為RUN、CMD、ENTRYPOINT、ADD和COPY指令設定鏡像中的目前工作目錄,如果目錄不存在會自動建立。

  • RUN

    在容器中運作指令并建立新的鏡像層,常用于安裝軟體包:

    RUN yum install -y vim

  • CMD 與 ENTRYPOINT

    這兩個指令都是用于設定容器啟動後執行的指令,但CMD會被docker run後面的指令行覆寫,而ENTRYPOINT不會被忽略,一定會被執行。

    docker run後面的參數可以傳遞給ENTRYPOINT指令當作參數。

    Dockerfile中隻能指定一個ENTRYPOINT,如果指定了很多,隻有最後一個有效。

Shell和exec格式的差別

Shell格式底層會調用/bin/sh -c來執行指令,可以解析變量,而下面的exec格式不會:

cat Dockerfile 
///
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo", "hello, $name"]
           

shell需要改寫成以下形式:

cat Dockerfile 
///
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]
           

Exec格式時,ENTRYPOINT可以通過CMD提供額外參數,CMD的額外參數可以在容器啟動時動态替換。在shell格式時ENTRYPOINT會忽略任何CMD或docker run提供的參數。

cat Dockerfile 
///
FROM busybox
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]
           

下面可以看出在運作容器時的差別:

官方推薦使用exec格式書寫

///Exec
docker run --rm busybox:v1
hello world
///Sell
docker run --rm busybox:v1 linux
hello linux
           

四、鏡像的封裝及優化

  • 選擇最精簡的基礎鏡像
  • 減少鏡像的層數
  • 清理鏡像建構的中間産物
  • 注意優化網絡請求
  • 盡量去用建構緩存
  • 使用多階段建構鏡像

Docker封裝rhel7+nginx鏡像執行個體

(1)删除之前建立的所有demo容器,真實主機下載下傳rhel7和nginx的鏡像源壓縮包并發送給server1

docker rmi `docker images | grep ^demo | awk '{print $3}'`   #删除之前所有的demo容器
///真機中
scp rhel7.tar nginx-1.20.1.tar server1:
           

(2)準備軟體倉庫檔案

(3)建立互動式容器,用于測試鏡像環境是否損壞

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

(4)将nginx和倉庫檔案拷貝到容器中,并編輯Dockerfile檔案,建立新的鏡像

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化
Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

(5)使用rhel7鏡像建立一個容器demo

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

docker inspect demo檢視容器資訊,看到配置設定的ip和在真實主機上挂載的路徑

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

(6)在真實主機挂載路徑上建立預設釋出檔案index.html,curl進行通路,可以擷取到釋出内容

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

封裝後鏡像的優化

封裝好的鏡像就可以正常運作了,但是檢視鏡像曆史及清單,會發現該鏡像的空間占用較大,不符合輕量化的原則,是以需要進行優化

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

1.減少鏡像層數,減少中間産物

重新編輯Dockerfile

vim Dockerfile

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

建立鏡像v2,可以看到鏡像大小減少了

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

2.使用多階段建構鏡像進行優化

再次編輯Dockerfile:

vim Dockerfile

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

建立鏡像v3,可以看到鏡像更小了

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

最終優化需要下載下傳base-debian10.tar ,下載下傳并導入

Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化
vim Dockerfile
////
FROM nginx as base
ARG Asia/Shanghai

RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /usr/sbin/nginx-debug /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

FROM gcr.io/distroless/base-debian10

COPY --from=base /opt /

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]
////

docker build -t rhel7:v4     #建立新的rhel7鏡像
docker images rhel7    #檢視鏡像大小發現筆之前小了很多
           
Linux企業運維——Docker鏡像(二)一、Docker鏡像的分層結構二、Docker鏡像的建構三、Dockerfile詳解四、鏡像的封裝及優化

優化為如此小之後依然可以運作一個容器,通過curl看到nginx釋出的頁面!