-
Notifications
You must be signed in to change notification settings - Fork 8
20190224_using cache from can speed up your docker builds
title: "在 docker-in-docker 環境中使用 cache-from 提升編譯速度" date: 2019-02-24 type: blog author: AppleBoy link: https://blog.wu-boy.com/2019/02/using-cache-from-can-speed-up-your-docker-builds/ layout: post comments: true
在現代 CI/CD 的環境流程中,使用 Docker In Docker 來編譯容器已經相當流行了,像是 GitLab CI 或 Drone 都是全走 Docker 環境,然而有很多人建議盡量不要在 CI 環境使用 Docker In Docker,原因在於 CI 環境無法使用 Host Image 資料,導致每次要上傳 Image 到 Docker Hub 時都需要重新下載所有的 Docker Layer,造成每次跑一次流程都會重複花費不少時間,而這個問題在 v1.13 時被解決,現在只要在編譯過程指定一個或者是多個 Image 列表,先把 Layer 下載到 Docker 內,接著對照 Dockerfile 內只要有被 Cache 到就不會重新再執行,講得有點模糊,底下直接拿實際例子來看看。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Taa6QkStg78" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>歡迎訂閱我的 Youtube 頻道: http://bit.ly/youtube-boy
更多實戰影片可以參考我的 Udemy 教學系列
- Go 語言實戰課程: http://bit.ly/golang-2019
- Drone CI/CD 自動化課程: http://bit.ly/drone-2019
在 Docker v1.13 版本中新增了 --cache-from
功能讓開發者可以在編譯 Dockerfile 時,同時指定先下載特定的 Docker Image,透過先下載好的 Docker Layer 在跟 Dockerfile 內文比較,如果有重複的就不會在被執行,這樣可以省下蠻多編譯時間,底下拿個簡單例子做說明,假設我們有底下的 Dockerfile
FROM alpine:3.9
LABEL maintainer="[email protected]"
EXPOSE 22 3000
RUN apk --no-cache add
bash
ca-certificates
curl
gettext
git
linux-pam
openssh
s6
sqlite
su-exec
tzdata
RUN addgroup
-S -g 1000
git &&
adduser
-S -H -D
-h /data/git
-s /bin/bash
-u 1000
-G git
git &&
echo "git:$(dd if=/dev/urandom bs=24 count=1 status=none | base64)" | chpasswd
ENV USER git
ENV GITEA_CUSTOM /data/gitea
VOLUME ["/data"]
ENTRYPOINT ["/usr/bin/entrypoint"]
CMD ["/bin/s6-svscan", "/etc/s6"]
COPY docker /
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
RUN ln -s /app/gitea/gitea /usr/local/bin/gitea
透過底下命令列可以編譯出 Image
$ docker build -t gitea/gitea .
而在命令列內可以看到花最多時間的是底下這個步驟
RUN apk --no-cache add \
bash \
ca-certificates \
curl \
gettext \
git \
linux-pam \
openssh \
s6 \
sqlite \
su-exec \
tzdata
該如何透過 --cache-from
機制繞過此步驟加速 Docker 編譯時間,其實很簡單只要在網路上找到原本 image 就可以繞過此步驟,開發者總會知道原本的 Dockerfile 是用來編譯出哪一個 Image 名稱
$ docker build --cache-frome=gitea/gitea -t gitea/gitea .
從上圖可以知道時間最久的步驟已經被 cache 下來了,所以 cache-from 會事先把 Image 下載下來,接著就可以使用該 Image 內的 cache layer 享受簡短 build time 的好處。
在 Gitlab CI 如何使用,其實很簡單,請參考此範例
image: docker:latest
services:
- docker:dind
stages:
- build
- test
- release
variables:
CONTAINER_IMAGE: registry.anuary.com/$CI_PROJECT_PATH
DOCKER_DRIVER: overlay2
build:
stage: build
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.anuary.com
- docker pull $CONTAINER_IMAGE:latest
- docker build --cache-from $CONTAINER_IMAGE:latest --build-arg NPM_TOKEN=${NPM_TOKEN} -t $CONTAINER_IMAGE:$CI_BUILD_REF -t $CONTAINER_IMAGE:latest .
- docker push $CONTAINER_IMAGE:$CI_BUILD_REF
- docker push $CONTAINER_IMAGE:latest
這時候你會問時間到底差了多久,在 Node.js 內如果沒有使用 cache,每次 CI 時間至少會多不少時間,取決於開發者安裝多少套件,我會建議如果是使用 multiple stage build 請務必使用 cache-from
。
在 Drone 1.0 架構內,可以架設多台 Agent 服務加速 CI/CD 流程,但是如果想要跨機器的 storage 非常困難,所以有了 cache-from
後,就可以確保多台 agent 享有 docker cache layer 機制。底下來看看 plugins/docker 該如何設定。
- name: publish
pull: always
image: plugins/docker:linux-amd64
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
cache_from: appleboy/drone-telegram
daemon_off: false
dockerfile: docker/Dockerfile.linux.amd64
password:
from_secret: docker_password
repo: appleboy/drone-telegram
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
這邊拿公司的一個環境當作範例,在還沒使用 cache 前編譯時間為 2 分 30 秒,後來使用 cache-from
則變成 30 秒。
使用 --cache-from
需要額外多花下載 Image 檔案的時間,所以開發者需要評估下載 Image 時間跟直接在 Dockerfile 內直接執行的時間差,如果差很多就務必使用 --cache-from
。不管是不是應用在 Docker In Docker 內,假如您需要改別人 Dockerfile,請務必先下載對應的 Docker Image 在執行端,這樣可以省去不少 docker build 時間,尤其是在 Dockerfile 內使用到 apt-get instll
或 npm install
這類型的命令。
-
Drone 自動觸發 GitLab CI 或 Jenkins 任務 (4)
-
10 分鐘內用 Traefik 架設 Drone 搭配 GitHub 服務 (0)
-
Drone CI/CD 系統簡介 (0)
-
用 Traefik 搭配 Docker 快速架設服務 (1)
-
Drone 支援單機版安裝 (內附影片) (0)
-
為什麼我用 Drone 取代 Jenkins 及 GitLab CI (10)
-
Cronjob 搭配 Drone 服務 (1)
-
用 Docker 發送 Line 訊息 (10)
-
用 Docker 整合測試 Flutter 框架 (0)
-
開源專案 Gitea 支援 OAuth Provider (0)