1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        基于Dockerfile構(gòu)建容器鏡像的最佳實(shí)踐

        共 16466字,需瀏覽 33分鐘

         ·

        2021-11-30 04:29

        目錄

        • 1、背景概述

        • 2、為什么鏡像會(huì)這么大

          • 2.1 基礎(chǔ)鏡像過(guò)大

          • 2.2 基礎(chǔ)鏡像過(guò)大,而且找不到了

          • 2.3 .git 目錄(非必要目錄)

          • 2.4 Dockerfile 本身有其他問(wèn)題

        • 3、Dockerfile 如何優(yōu)化

          • 3.1 從哪里入手

          • 3.2 方案

          • 3.3 樣例

        • 4、除了這些優(yōu)化還可以做什么

          • 4.1 設(shè)置字符集

          • 4.2 時(shí)區(qū)校正

          • 4.3 進(jìn)程管理

          • 4.4 降權(quán)啟動(dòng)

          • 4.5 底層庫(kù)依賴(lài)

        • 5、小結(jié)


        1、背景概述

        容器鏡像是容器化落地轉(zhuǎn)型的第一步,總結(jié)幾點(diǎn)需要做鏡像優(yōu)化的原因

        隨著應(yīng)用容器化部署的大規(guī)模遷移以及版本迭代的加快,優(yōu)化基礎(chǔ)設(shè)施之docker鏡像主要有以下目的

        • 縮短部署時(shí)的鏡像下載時(shí)間

        • 提升安全性,減少可供攻擊的目標(biāo)

        • 減少故障恢復(fù)時(shí)間

        • 節(jié)省存儲(chǔ)開(kāi)銷(xiāo)

        2、為什么鏡像會(huì)這么大

        這里簡(jiǎn)要分析了幾個(gè)典型的Repo,總結(jié)了現(xiàn)有Docker鏡像較大的幾個(gè)原因

        2.1 基礎(chǔ)鏡像過(guò)大

        舉例:倉(cāng)庫(kù)A,制作出來(lái)的鏡像大小9.67GB

        用到的基礎(chǔ)鏡像:鏡像大小8.72GB

        逆向分析了一下,為啥基礎(chǔ)鏡像還這么大?結(jié)果就不用多說(shuō)了 0.0

        2.2 基礎(chǔ)鏡像過(guò)大,而且找不到了

        舉例:倉(cāng)庫(kù)B,制作出來(lái)的鏡像大小22.7GB

        用到的基礎(chǔ)鏡像:404 not found,沒(méi)錯(cuò),找不到了 0.0

        2.3 .git 目錄(非必要目錄)

        這個(gè)問(wèn)題更多內(nèi)容可以參考我之前的文章?Git目錄為什么這么大?[1]

        舉例:倉(cāng)庫(kù)C,代碼大小795MB

        其中.git目錄大小225MB ,dockerfile中的指令如下(全部添加到了鏡像中)

        ADD?.?/app/startapp/

        其中還包含了d目錄大小約300MB,是否需要使用不得而知,但目測(cè)不需要使用,僅為測(cè)試數(shù)據(jù)

        d
        ├──?[?503]??test_421.json
        ├──?[?483]??test_havalB9.json
        ...
        ├──?[?484]??test_144.json
        ├──?[?104]??.gitmodules
        ├──?[?122]??.idea
        ├──?[???0]??__init__.py
        ├──?[?11M]??164103.zip
        ├──?[108M]??test_180753.csv
        ├──?[?68M]??test_180753.txt
        ...
        └──?[?335]??README.md

        以上其實(shí)都不需要提交到鏡像中制作成鏡像

        2.4 Dockerfile 本身有其他問(wèn)題

        這個(gè)原因不言而喻,不是專(zhuān)業(yè)的人寫(xiě)的Dockerfile可能都有一定的優(yōu)化空間,只是暫時(shí)沒(méi)關(guān)注這些細(xì)節(jié)而已

        例如,放任各路repo研發(fā)自行寫(xiě)Dockerfile,沒(méi)有一定的標(biāo)準(zhǔn),前期可能無(wú)所謂,到后期問(wèn)題就慢慢浮現(xiàn)了

        正所謂《能用就行》~

        3、Dockerfile 如何優(yōu)化

        3.1 從哪里入手

        優(yōu)化docker鏡像應(yīng)該從鏡像分層概念入手

        3.1.1 舉個(gè)栗子

        一個(gè)實(shí)際的例子

        nginx:alpine 鏡像 23.2MB

        #?docker?history?nginx:alpine
        IMAGE??????????CREATED???????CREATED?BY??????????????????????????????????????SIZE??????COMMENT
        b46db85084b8???9?days?ago????/bin/sh?-c?#(nop)??CMD?["nginx"?"-g"?"daemon…???0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??STOPSIGNAL?SIGQUIT???????????0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??EXPOSE?80????????????????????0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??ENTRYPOINT?["/docker-entr…???0B
        ??????9?days?ago????/bin/sh?-c?#(nop)?COPY?file:09a214a3e07c919a…???4.61kB
        ??????9?days?ago????/bin/sh?-c?#(nop)?COPY?file:0fd5fca330dcd6a7…???1.04kB
        ??????9?days?ago????/bin/sh?-c?#(nop)?COPY?file:0b866ff3fc1ef5b0…???1.96kB
        ??????9?days?ago????/bin/sh?-c?#(nop)?COPY?file:65504f71f5855ca0…???1.2kB
        ??????9?days?ago????/bin/sh?-c?set?-x?????&&?addgroup?-g?101?-S?…???17.6MB
        ??????9?days?ago????/bin/sh?-c?#(nop)??ENV?PKG_RELEASE=1????????????0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??ENV?NJS_VERSION=0.7.0????????0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??ENV?NGINX_VERSION=1.21.4?????0B
        ??????9?days?ago????/bin/sh?-c?#(nop)??LABEL?maintainer=NGINX?Do…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??CMD?["/bin/sh"]??????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)?ADD?file:762c899ec0505d1a3…???5.61MB

        python:alpine 鏡像 45.5MB

        #?docker?history?python:alpine
        IMAGE??????????CREATED???????CREATED?BY??????????????????????????????????????SIZE??????COMMENT
        382a63bb2f25???10?days?ago???/bin/sh?-c?#(nop)??CMD?["python3"]??????????????0B
        ??????10?days?ago???/bin/sh?-c?set?-ex;???wget?-O?get-pip.py?"$P…???8.31MB
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PYTHON_GET_PIP_SHA256…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PYTHON_GET_PIP_URL=ht…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PYTHON_SETUPTOOLS_VER…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PYTHON_PIP_VERSION=21…???0B
        ??????10?days?ago???/bin/sh?-c?cd?/usr/local/bin??&&?ln?-s?idle3…???32B
        ??????10?days?ago???/bin/sh?-c?set?-ex??&&?apk?add?--no-cache?--…???29.8MB
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PYTHON_VERSION=3.10.0????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?GPG_KEY=A035C8C19219B…???0B
        ??????10?days?ago???/bin/sh?-c?set?-eux;??apk?add?--no-cache???c…???1.82MB
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?LANG=C.UTF-8?????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PATH=/usr/local/bin:/…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??CMD?["/bin/sh"]??????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)?ADD?file:762c899ec0505d1a3…???5.61MB

        實(shí)際存儲(chǔ)

        #?docker?inspect?nginx:alpine|?jq?'.[0]|{GraphDriver}'
        {
        ??"GraphDriver":?{
        ????"Data":?{
        ??????"LowerDir":?"/data/docker-overlay2/overlay2/3d.../diff:/data/docker-overlay2/overlay2/ae.../diff:/data/docker-overlay2/overlay2/ea.../diff:/data/docker-overlay2/overlay2/29.../diff:/data/docker-overlay2/overlay2/5e.../diff",
        ??????"MergedDir":?"/data/docker-overlay2/overlay2/b7.../merged",
        ??????"UpperDir":?"/data/docker-overlay2/overlay2/b7.../diff",
        ??????"WorkDir":?"/data/docker-overlay2/overlay2/b7.../work"
        ????},
        ????"Name":?"overlay2"
        ??}
        }

        分層概念的描述

        鏡像解決了應(yīng)用運(yùn)行及環(huán)境的打包問(wèn)題,實(shí)際應(yīng)用中應(yīng)用都是基于同一個(gè)rootfs來(lái)打包和迭代的,但并不是每個(gè)rootfs都會(huì)多份,實(shí)際上docker利用了存儲(chǔ)驅(qū)動(dòng)AUFS,devicemapperoverlay,overlay2的存儲(chǔ)技術(shù)實(shí)現(xiàn)了分層

        例如上面查看一個(gè)docker鏡像會(huì)發(fā)現(xiàn)這些層

        • LowerDir:鏡像層

        • MergedDir:整合了 lower 層和 upper 讀寫(xiě)層顯示出來(lái)的視圖

        • UpperDir:讀寫(xiě)層

        • WorkDir:中間層,對(duì) Upper 層的寫(xiě)入,先寫(xiě)入 WorkDir,再移入 UpperDir

        3.1.2 Copy on write

        當(dāng)Docker第一次啟動(dòng)一個(gè)容器時(shí),初始的讀寫(xiě)層是空的,當(dāng)文件系統(tǒng)發(fā)生變化時(shí),這些變化都會(huì)應(yīng)用到這一層之上。比如,如果想修改一個(gè)文件,這個(gè)文件首先會(huì)從該讀寫(xiě)層下面的只讀層復(fù)制到該讀寫(xiě)層。由此,該文件的只讀版本依然存在于只讀層,只是被讀寫(xiě)層的該文件副本所隱藏,該機(jī)制則被稱(chēng)之為寫(xiě)時(shí)復(fù)制

        3.1.3 UnionFS

        把多個(gè)目錄(也叫分支)內(nèi)容聯(lián)合掛載到同一個(gè)目錄下,而目錄的物理位置是分開(kāi)的

        一個(gè)直觀的效果,第一次拉取一個(gè)nginx:1.15版本鏡像,再次拉取nginx:1.16鏡像,速度要快很多

        3.2 方案

        了解了鏡像大小的主要構(gòu)成之后,就很容易知道從哪些方向入手減少鏡像大小了

        3.2.1 減少鏡像層數(shù)

        鏡像層數(shù)的增加,對(duì)Dockerfile來(lái)說(shuō)主要在于RUN指令出現(xiàn)的次數(shù),因此,合并RUN指令可以大大減少鏡像層數(shù)

        舉個(gè)栗子:

        合并前,三層

        RUN?apk?add?tzdata
        RUN?cp?/usr/share/zoneinfo/Asia/Shanghai?/etc/localtime
        RUN?echo?"Asia/Shanghai"?>?/etc/timezone

        合并后,一層

        RUN?apk?add?tzdata?\
        ????&&?cp?/usr/share/zoneinfo/Asia/Shanghai?/etc/localtime?\
        ????&&?echo?"Asia/Shanghai"?>?/etc/timezone

        3.2.2 減少每層鏡像大小

        3.2.2.1 選用更小的基礎(chǔ)鏡像
        • scratch:空鏡像,又叫鏡像之父!任何鏡像都需要有一個(gè)基礎(chǔ)鏡像,那么問(wèn)題來(lái)了,就好比是先有雞還是先有蛋的問(wèn)題,基礎(chǔ)鏡像的“祖宗”是什么呢?能不能在構(gòu)建時(shí)不以任何鏡像為基礎(chǔ)呢?答案是肯定的,可以選用scratch,具體就不展開(kāi)了,可以參考:baseimages[2],使用scratch鏡像的例子pause
        • busybox:對(duì)比scratch,多了常用的linux工具等
        • alpine:多了包管理工具apk
        3.3.2.2 多階段構(gòu)建

        多階段構(gòu)建非常適用于編譯性語(yǔ)言,簡(jiǎn)單來(lái)說(shuō)就是允許一個(gè)Dockerfile中出現(xiàn)多條FROM指令,只有最后一條FROM指令中指定的基礎(chǔ)鏡像作為本次構(gòu)建鏡像的基礎(chǔ)鏡像,其它的階段都可以認(rèn)為是只為中間步驟

        FROM … AS …COPY --from組合使用

        例如java鏡像,鏡像大小812MB

        FROM?centos?AS?jdk
        COPY?jdk-8u231-linux-x64.tar.gz?/usr/local/src
        RUN?cd?/usr/local/src?&&?\
        ????tar?-xzvf?jdk-8u231-linux-x64.tar.gz?-C?/usr/local

        使用多階段構(gòu)建,鏡像大小618MB

        FROM?centos?AS?jdk
        COPY?jdk-8u231-linux-x64.tar.gz?/usr/local/src
        RUN?cd?/usr/local/src?&&?\
        ????tar?-xzvf?jdk-8u231-linux-x64.tar.gz?-C?/usr/local


        FROM?centos
        COPY?--from=jdk?/usr/local/jdk1.8.0_231?/usr/local
        3.3.2.3 忽略文件

        構(gòu)建上下文build context,“上下文” 意為和現(xiàn)在這個(gè)工作相關(guān)的周?chē)h(huán)境

        docker build時(shí)當(dāng)前的工作目錄,不管構(gòu)建時(shí)有沒(méi)有用到當(dāng)前目錄下的某些文件及目錄,默認(rèn)情況下這個(gè)上下文中的文件及目錄都會(huì)作為構(gòu)建上下文內(nèi)容發(fā)送給Docker Daemon

        當(dāng)docker build開(kāi)始執(zhí)行時(shí),控制臺(tái)會(huì)輸出Sending build context to Docker daemon xxxMB,這就表示將當(dāng)前工作目錄下的文件及目錄都作為了構(gòu)建上下文

        前面提到可以在RUN指令中添加--no-cache不使用緩存,同樣也可以在執(zhí)行docker build命令時(shí)添加該指令以在鏡像構(gòu)建時(shí)不使用緩存

        構(gòu)建上下文中,使用.dockerignore 文件在構(gòu)建時(shí)就可以避免將本地模塊以及調(diào)試日志被拷貝進(jìn)入到Docker鏡像中,這和git版本控制的.gitignore很類(lèi)似

        3.3.2.4 遠(yuǎn)程下載

        使用遠(yuǎn)程下載代替ADD可以減少鏡像大小

        RUN?curl?-s?http://192.168.1.1/repository/tools/jdk-8u241-linux-x64.tar.gz?|?tar?-xC?/opt/
        3.3.2.5 拆分 COPY

        例如一個(gè)COPY指令的目錄下A4個(gè)子目錄AA/BB/CC/DDCOPY,但常變化的只有一個(gè) BB

        這個(gè)時(shí)候拆分COPY會(huì)更快

        COPY?A/AA?/app/A/AA
        COPY?A/BB?/app/A/BB
        COPY?A/CC?/app/A/CC
        COPY?A/DD?/app/A/DD
        3.3.2.6 構(gòu)建時(shí)掛載

        構(gòu)建時(shí)掛載(擴(kuò)展功能[3]

        配置

        • 修改 docker 啟動(dòng)參數(shù),添加--experimental
        • dockerfile 頭部添加# syntax=docker/dockerfile:1.1.1-experimental

        使用

        • 掛載本地 golang 緩存
        #?syntax?=?docker/dockerfile:experimental
        FROM?golang
        ...
        RUN?--mount=type=cache,target=/root/.cache/go-build?go?build?...
        • 掛載 cache 目錄
        #?syntax?=?docker/dockerfile:experimental
        FROM?ubuntu
        RUN?rm?-f?/etc/apt/apt.conf.d/docker-clean;?echo?'Binary::apt::APT::Keep-Downloaded-Packages?"true";'?>?/etc/apt/apt.conf.d/keep-cache
        RUN?--mount=type=cache,target=/var/cache/apt?--mount=type=cache,target=/var/lib/apt?\
        ??apt?update?&&?apt?install?-y?gcc

        • 掛載某些憑據(jù)
        #?syntax?=?docker/dockerfile:experimental
        FROM?python:3
        RUN?pip?install?awscli
        RUN?--mount=type=secret,id=aws,target=/root/.aws/credentials?aws?s3?cp?s3://...?...

        等等

        3.3.2.7 構(gòu)建后清理
        • 刪除壓縮包
        • 清理安裝緩存
          • --no-cache
          • rm -rf /var/lib/apt/lists/*
          • rm -rf /var/cache/yum/*
        3.3.2.8 鏡像壓縮

        exportimport組合進(jìn)行壓縮鏡像(壓縮效果不是很明顯)

        這種方法不好的就是會(huì)丟失一部分鏡像信息

        #?docker?run?-d?--name?nginx?nginx:alpine
        #?docker?export?nginx?|docker?import?-?nginx:alpine2
        sha256:dd6a3cf822ac3c3ad3e7f7b31675cd8cd99a6f80e360996e04da6fc2f3b98cb5
        #?docker?history?nginx:alpine
        IMAGE??????????CREATED???????CREATED?BY??????????????????????????????????????SIZE??????COMMENT
        b46db85084b8???10?days?ago???/bin/sh?-c?#(nop)??CMD?["nginx"?"-g"?"daemon…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??STOPSIGNAL?SIGQUIT???????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??EXPOSE?80????????????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENTRYPOINT?["/docker-entr…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)?COPY?file:09a214a3e07c919a…???4.61kB
        ??????10?days?ago???/bin/sh?-c?#(nop)?COPY?file:0fd5fca330dcd6a7…???1.04kB
        ??????10?days?ago???/bin/sh?-c?#(nop)?COPY?file:0b866ff3fc1ef5b0…???1.96kB
        ??????10?days?ago???/bin/sh?-c?#(nop)?COPY?file:65504f71f5855ca0…???1.2kB
        ??????10?days?ago???/bin/sh?-c?set?-x?????&&?addgroup?-g?101?-S?…???17.6MB
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?PKG_RELEASE=1????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?NJS_VERSION=0.7.0????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??ENV?NGINX_VERSION=1.21.4?????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??LABEL?maintainer=NGINX?Do…???0B
        ??????10?days?ago???/bin/sh?-c?#(nop)??CMD?["/bin/sh"]??????????????0B
        ??????10?days?ago???/bin/sh?-c?#(nop)?ADD?file:762c899ec0505d1a3…???5.61MB
        #?docker?history?nginx:alpine2
        IMAGE??????????CREATED??????????CREATED?BY???SIZE??????COMMENT
        dd6a3cf822ac???40?seconds?ago????????????????23MB??????Imported?from?-
        #?docker?images|grep?nginx
        nginx???????????????????????????????????????????????????????????????????????????????????????????????????????????????alpine2?????????????????????dd6a3cf822ac???54?seconds?ago???23MB
        nginx???????????????????????????????????????????????????????????????????????????????????????????????????????????????alpine??????????????????????b46db85084b8???10?days?ago??????23.2MB

        3.3 樣例

        3.3.1 go 樣例

        樣例一

        kubeadm安裝的k8s集群,kube-apiserver鏡像的Dockerfile是利用bazel編譯工具編譯的

        bazel?build?...
        LABEL?maintainers=Kubernetes?Authors
        LABEL?description=go?based?runner?for?distroless?scenarios
        WORKDIR?/
        COPY?/workspace/go-runner?.?#?buildkit
        ENTRYPOINT?["/go-runner"]
        COPY?file:2e904ea733ba0ded2a99947847de31414a19d83f8495dd8c1fbed3c70bf67a22?in?/usr/local/bin/kube-apiserver

        代碼目錄 28M(包含.git 目錄 20.5M)

        鏡像大小 122MB

        樣例二

        開(kāi)源編排引擎CadenceDockerfile

        ARG?TARGET=server

        #?Can?be?used?in?case?a?proxy?is?necessary
        ARG?GOPROXY

        #?Build?tcheck?binary
        FROM?golang:1.17-alpine3.13?AS?tcheck

        WORKDIR?/go/src/github.com/uber/tcheck

        COPY?go.*?./
        RUN?go?build?-mod=readonly?-o?/go/bin/tcheck?github.com/uber/tcheck

        #?Build?Cadence?binaries
        FROM?golang:1.17-alpine3.13?AS?builder

        ARG?RELEASE_VERSION

        RUN?apk?add?--update?--no-cache?ca-certificates?make?git?curl?mercurial?unzip

        WORKDIR?/cadence

        #?Making?sure?that?dependency?is?not?touched
        ENV?GOFLAGS="-mod=readonly"

        #?Copy?go?mod?dependencies?and?build?cache
        COPY?go.*?./
        RUN?go?mod?download

        COPY?.?.
        RUN?rm?-fr?.bin?.build

        ENV?CADENCE_RELEASE_VERSION=$RELEASE_VERSION

        #?bypass?codegen,?use?committed?files.??must?be?run?separately,?before?building?things.
        RUN?make?.fake-codegen
        RUN?CGO_ENABLED=0?make?copyright?cadence-cassandra-tool?cadence-sql-tool?cadence?cadence-server?cadence-bench?cadence-canary


        #?Download?dockerize
        FROM?alpine:3.11?AS?dockerize

        RUN?apk?add?--no-cache?openssl

        ENV?DOCKERIZE_VERSION?v0.6.1
        RUN?wget?https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz?\
        ????&&?tar?-C?/usr/local/bin?-xzvf?dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz?\
        ????&&?rm?dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz?\
        ????&&?echo?"****?fix?for?host?id?mapping?error?****"?\
        ????&&?chown?root:root?/usr/local/bin/dockerize



        #?Alpine?base?image
        FROM?alpine:3.11?AS?alpine

        RUN?apk?add?--update?--no-cache?ca-certificates?tzdata?bash?curl

        #?set?up?nsswitch.conf?for?Go's?"netgo"?implementation
        #?https://github.com/gliderlabs/docker-alpine/issues/367#issuecomment-424546457
        RUN?test?!?-e?/etc/nsswitch.conf?&&?echo?'hosts:?files?dns'?>?/etc/nsswitch.conf

        SHELL?["/bin/bash",?"-c"]


        #?Cadence?server
        FROM?alpine?AS?cadence-server

        ENV?CADENCE_HOME?/etc/cadence
        RUN?mkdir?-p?/etc/cadence

        COPY?--from=tcheck?/go/bin/tcheck?/usr/local/bin
        COPY?--from=dockerize?/usr/local/bin/dockerize?/usr/local/bin
        COPY?--from=builder?/cadence/cadence-cassandra-tool?/usr/local/bin
        COPY?--from=builder?/cadence/cadence-sql-tool?/usr/local/bin
        COPY?--from=builder?/cadence/cadence?/usr/local/bin
        COPY?--from=builder?/cadence/cadence-server?/usr/local/bin
        COPY?--from=builder?/cadence/schema?/etc/cadence/schema

        COPY?docker/entrypoint.sh?/docker-entrypoint.sh
        COPY?config/dynamicconfig?/etc/cadence/config/dynamicconfig
        COPY?config/credentials?/etc/cadence/config/credentials
        COPY?docker/config_template.yaml?/etc/cadence/config
        COPY?docker/start-cadence.sh?/start-cadence.sh

        WORKDIR?/etc/cadence

        ENV?SERVICES="history,matching,frontend,worker"

        EXPOSE?7933?7934?7935?7939
        ENTRYPOINT?["/docker-entrypoint.sh"]
        CMD?/start-cadence.sh


        #?All-in-one?Cadence?server
        FROM?cadence-server?AS?cadence-auto-setup

        RUN?apk?add?--update?--no-cache?ca-certificates?py-pip?mysql-client
        RUN?pip?install?cqlsh

        COPY?docker/start.sh?/start.sh

        CMD?/start.sh


        #?Cadence?CLI
        FROM?alpine?AS?cadence-cli

        COPY?--from=tcheck?/go/bin/tcheck?/usr/local/bin
        COPY?--from=builder?/cadence/cadence?/usr/local/bin

        ENTRYPOINT?["cadence"]

        #?Cadence?Canary
        FROM?alpine?AS?cadence-canary

        COPY?--from=builder?/cadence/cadence-canary?/usr/local/bin
        COPY?--from=builder?/cadence/cadence?/usr/local/bin

        CMD?["/usr/local/bin/cadence-canary",?"--root",?"/etc/cadence-canary",?"start"]

        #?Cadence?Bench
        FROM?alpine?AS?cadence-bench

        COPY?--from=builder?/cadence/cadence-bench?/usr/local/bin
        COPY?--from=builder?/cadence/cadence?/usr/local/bin

        CMD?["/usr/local/bin/cadence-bench",?"--root",?"/etc/cadence-bench",?"start"]

        #?Final?image
        FROM?cadence-${TARGET}

        代碼目錄 85.4M(包含.git 目錄 57.7M)

        鏡像大小 135.69MB

        3.3.2 py 樣例

        FROM?python:3.4

        RUN?apt-get?update?\
        ????&&?apt-get?install?-y?--no-install-recommends?\
        ????????postgresql-client?\
        ????&&?rm?-rf?/var/lib/apt/lists/*


        WORKDIR?/usr/src/app
        COPY?requirements.txt?./
        RUN?pip?install?-r?requirements.txt
        COPY?.?.

        EXPOSE?8000
        CMD?["python",?"manage.py",?"runserver",?"0.0.0.0:8000"]

        代碼目錄 275M(包含.git 目錄 222M)

        鏡像大小 436MB

        4、除了這些優(yōu)化還可以做什么

        4.1 設(shè)置字符集

        Dockerfile中設(shè)置通用的字符集

        #?Set?lang
        ENV?LANG?"en_US.UTF-8"

        4.2 時(shí)區(qū)校正

        這個(gè)問(wèn)題更多內(nèi)容可以參考我之前的文章?k8s環(huán)境下處理容器時(shí)間問(wèn)題的多種姿勢(shì)?[4]

        Dockerfile中設(shè)置通用的時(shí)區(qū)

        #?Set?timezone
        RUN?ln?-sf?/usr/share/zoneinfo/Asia/Shanghai?/etc/localtime?\
        ???&&?echo?"Asia/Shanghai"?>?/etc/timezone

        4.3 進(jìn)程管理

        docker容器運(yùn)行時(shí),默認(rèn)會(huì)以Dockerfile中的ENTRYPOINTCMD作為PID1的主進(jìn)程,這個(gè)進(jìn)程存在的目的,通俗來(lái)說(shuō)需要做的就是將容器"夯住",一旦這個(gè)進(jìn)程不存在了,那么容器就會(huì)退出

        除此之外,這個(gè)主進(jìn)程還有一個(gè)重要的作用就是管理“僵尸進(jìn)程”

        一個(gè)比較官方的定義,“僵尸進(jìn)程”是指完成執(zhí)行(通過(guò)exit系統(tǒng)調(diào)用,或運(yùn)行時(shí)發(fā)生致命錯(cuò)誤或收到終止信號(hào)所致),但在操作系統(tǒng)的進(jìn)程表中仍然存在其進(jìn)程控制塊,處于"終止?fàn)顟B(tài)"的進(jìn)程。

        清理“僵尸進(jìn)程”的思路主要有

        • 將父進(jìn)程中對(duì)SIGCHLD信號(hào)的處理函數(shù)設(shè)為SIG_IGN(忽略信號(hào));
        • fork兩次并殺死一級(jí)子進(jìn)程,令二級(jí)子進(jìn)程成為孤兒進(jìn)程而被init所“收養(yǎng)”、清理

        目前可以實(shí)現(xiàn)的開(kāi)源方案

        Tini

        tini容器init是一個(gè)最小化的init系統(tǒng),運(yùn)行在容器內(nèi)部,用于啟動(dòng)一個(gè)子進(jìn)程,并等待進(jìn)程退出時(shí)清理僵尸和執(zhí)行信號(hào)轉(zhuǎn)發(fā)

        優(yōu)點(diǎn)

        • tini可以避免應(yīng)用程序生成僵尸進(jìn)程

        • tini可以處理Docker進(jìn)程中運(yùn)行的程序的信號(hào),通過(guò)TiniSIGTERM 可以終止進(jìn)程,不需要你明確安裝一個(gè)信號(hào)處理器

        示例

        #?Add?Tini
        ENV?TINI_VERSION?v0.19.0
        ADD?https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini?/tini
        RUN?chmod?+x?/tini
        ENTRYPOINT?["/tini",?"--"]

        #?Run?your?program?under?Tini
        CMD?["/your/program",?"-and",?"-its",?"arguments"]
        #?or?docker?run?your-image?/your/program?...

        dumb-init

        dumb-init會(huì)向子進(jìn)程的進(jìn)程組發(fā)送其收到的信號(hào)。例如 bash 接收到信號(hào)之后,不會(huì)向子進(jìn)程發(fā)送信號(hào)

        dumb-init也可以通過(guò)設(shè)置環(huán)境變量DUMB_INIT_SETSID=0來(lái)控制只向它的直接子進(jìn)程發(fā)送信號(hào)

        另外dumb-init也會(huì)接管失去父進(jìn)程的進(jìn)程,確保其能正常退出

        示例

        FROM?alpine:3.11.5
        RUN?sed?-i?"s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g"?/etc/apk/repositories?\
        ????&&?apk?add?--no-cache?dumb-init


        #?Runs?"/usr/bin/dumb-init?--?/my/script?--with?--args"
        ENTRYPOINT?["dumb-init",?"--"]

        #?or?if?you?use?--rewrite?or?other?cli?flags
        #?ENTRYPOINT?["dumb-init",?"--rewrite",?"2:3",?"--"]

        CMD?["/my/script",?"--with",?"--args"]

        4.4 降權(quán)啟動(dòng)

        很多情況下,容器中的進(jìn)程需要降權(quán)啟動(dòng)以保證安全性,這就和我們?cè)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(150, 84, 181);">vm上運(yùn)行一個(gè)nginx服務(wù)一樣,最好通過(guò)特定的降權(quán)用戶(hù)去運(yùn)行

        舉例,tomcat鏡像

        ...
        USER?tomcat
        WORKDIR?/usr/local/tomcat
        EXPOSE?8080
        ENTRYPOINT?["catalina.sh","run"]

        如果在某些情況下需要使用sudo權(quán)限,在docker官方避免安裝或使用sudosudo因?yàn)樗哂胁豢深A(yù)測(cè)的TTY和可能導(dǎo)致問(wèn)題的信號(hào)轉(zhuǎn)發(fā)行為。如果必須,例如將守護(hù)進(jìn)程初始化為 root但將其作為非運(yùn)行root,推薦使用gosu

        例如,Postgres 官方鏡像[5] 使用以下腳本作為其ENTRYPOINT

        #!/bin/bash
        set?-e

        if?[?"$1"?=?'postgres'?];?then
        ????chown?-R?postgres?"$PGDATA"

        ????if?[?-z?"$(ls?-A?"$PGDATA")"?];?then
        ????????gosu?postgres?initdb
        ????fi

        ????exec?gosu?postgres?"$@"
        fi

        exec?"$@"

        4.5 底層庫(kù)依賴(lài)

        很多時(shí)候,服務(wù)依賴(lài)一些底層庫(kù)的支持,這里以基于alpine基礎(chǔ)鏡像構(gòu)建java鏡像舉個(gè)栗子

        alpine為了精簡(jiǎn)本身并沒(méi)有安裝太多的常用軟件,所以如果要使用jdk/jre的話就需要glibc,而glibc需要先得到ca-certificates證書(shū)服務(wù)(安裝glibc前置依賴(lài))才能安裝

        alpine跑了jdk8的鏡像結(jié)果發(fā)現(xiàn)jdk無(wú)法執(zhí)行。究其原因,java是基于GUN Standard C library(glibc),alpine是基于MUSL libc(mini libc),所以alpine需要安裝glibc的庫(kù)

        5、小結(jié)

        本文簡(jiǎn)要分析了Dockerfile為什么這么大的幾個(gè)主要原因,并且根據(jù)生產(chǎn)經(jīng)驗(yàn)羅列了一些優(yōu)化鏡像大小的措施以及其他方面常用的處理辦法,很多技巧性的內(nèi)容,比較雜亂,就不一一提及了 ~

        See you ~

        參考資料

        [1]

        https://www.ssgeek.com/post/git-mu-lu-wei-shi-me-zhe-me-da/

        [2]

        https://docs.docker.com/develop/develop-images/baseimages/

        [3]

        https://docs.docker.com/engine/reference/commandline/dockerd/#description

        [4]

        https://www.ssgeek.com/post/k8s-huan-jing-xia-chu-li-rong-qi-shi-jian-wen-ti-de-duo-chong-zi-shi/

        [5]

        https://hub.docker.com/_/postgres/

        歡迎進(jìn)群一起進(jìn)行技術(shù)交流

        加群方式:公眾號(hào)消息私信“加群或加我好友再加群均可

        瀏覽 58
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            放荡闺蜜高h季红豆 | 国产孕妇被猛烈进入A片一级 | 东京热二区 | 一级a做一级a做片性高清视频 | 成人无码区免费A片视频野外 | 天天综合—永久入口 | 91大香蕉视频在线观看 | 国产精视频 | 八重神子入夜狂飙游戏视频免费观看 | 国产女人操逼视频 |