2019年5月7日 星期二

Dockerfile Best Practice

來源是從這份 簡報

這份簡報主要提出改進的目標如下:
  • build time
  • image size
  • maintainability
  • security
  • consistency/repeatability
簡報開頭先建議使用 buildkit 功能
先摘錄一下官網路個人認為比較重要的部分:
  • docker build 新選項
    --secret 可以避免在 Dockerfile 中直接寫入密碼
    --ssh 可以讓 build 出來的 image 直接有 ssh daemon
  • 使用 buildkit
    從環境變數打開 : DOCKER_BUILDKIT=1 docker build .
    修改設定檔: /etc/docker/daemon.json : { "features": { "buildkit": true } }

然後簡報開始針對上面的目標提出改善方式
  1. 減少 build time
    a. 善用 cache ,把比較容易變動的指令放到後面
    b. 指定 copy 的範圍可以減少 cache 使用,例如 
        COPY . /app  改成 COPY target/app.jar /app
    c. 避免使用到過期的套件,例如將 apt-get update 和 install 合併為一行
        apt-get update && apt-get -y install ssh vim
  2. 減少 image size
    a. 移除非必要的套件, apt-get -y install --no-install-recommends
    b. 移除安裝套件的 cache , rm -fr /var/lib/apt/lists/*
  3. 維護性
    a. 盡量使用官方出的 image
    b. 盡量指定 image 的 tag ,例如 FROM openjdk:8
    c. 從官網尋找符合需求下 size 最小的 image tag
  4. 重複使用性
    a. 盡量維持 build 環境的一致性
    b. 透過 multi-stage build 來減少 build iamge 時的相依性

簡報提出 multi-stage 的適用情境
  • separate build from runtime envrionment ( 降低 image size )
  • 降低 image 的變動
  • Build /dev /test /lint /... specific envrionments
  • 將相依性變成非線性化 (concurrency)
  • Platform-specific stages

使用 multi-stage 情境的範例
  • 用 --target 來指定要 build 的 stage

    Dockerfile:
    From image_or_stage AS stage_name

    Build Command: 
    docker build --target stage_name
  • use global Arguments

    Dockerfile:
    ARG flavor=alpine
    FROM openjdk:8-jre-$flavor AS release

    Build Command:
    docker build --target release --build-arg flavor=jessie .
  • buildkit 可以在 build 時排除非必要的 stage,並且可以多個 stage 同時進行 build

Dockerfile 新的語法 (experimental) ,以下語法都是在 docker v18.09+ w/ BuildKit 使用
  • context mounts
    COPY . /app => RUN --mount=target=. mvn -e -B package -DoutputDirectory=/
  • cache dependencies
    RUN --mount=target=. --mount=type=cache,target=/root/.m2 && mvn package -DoutputDirectory=/
  • serects

    錯誤的方法:
    (1) ENV AWs-ACCESS_KEY_ID  (直接寫在 Dockerfile)
    (2) ARG AWs-ACCESS_KEY_ID  (會保存在 docker history)

    建議的方式:
    Dockerfile:
    RUN --mount=type=secret,id=aws,target=/root/.aws/credentials,required

    Build Command:
    docker build --secret id=aws,src=~/.aws/credentials .
  • 使用 private git repos

    錯誤的方法:
    COPY ./keys/private.pem /root/.ssh/private.pem

    建議的方式:
    Dockerfile:
    RUN --mount=type=ssh,required git clone git@xxx:/repo /work

    Build Command:
    docker build --ssh=default .

沒有留言: