[TOC]html
Dockerfile
咱們若是使用Dockerfile
來構建Docker鏡像,若是一不當心就會致使鏡像大小超過1G,這是很是恐怖的。通常也都是好幾百兆。較大的鏡像每每會致使移植,遷移緩慢,部署上線也就慢。Dockerfile
就像代碼同樣須要持續去進行優化。使用下面的幾個優化方案,能夠大幅度的減少鏡像的大小。node
最重要的因素是減小鏡像的層數,這樣能大大減少鏡像的大小;
固然在減小層數和增長層數但能減小編譯時長上,能夠適當衡量。linux
說明:nginx
- docker鏡像能夠看出是分層的,分層方向與
Dockerfile
相反,自下而上;- docker鏡像每一層是共享的,即同一臺機器中,若是
Dockerfile
編譯的時候,前面的內容相同,則相應的層是引用相同的,固然內容自Dockerfile
中要自上而下相同,有出現不同的層數的時候,後面的層內容都會不一樣,基於這個原理,在沒有任何修改的狀況下,後面的編譯都是使用以前的鏡像緩存;- 一層新的命令造成新的一層,若是涉及磁盤更新,並且沒有在同一層刪除,不管文件是否最後刪除,都會帶到下一層。
基於上面的說明,層數越小,每一層大小越小,鏡像整體就越小。git
如下爲一個示例,其優化原理是相鄰的命令間用&&
讓其只造成一層。github
# 基礎鏡像 FROM node:10.16-alpine as builder # 拷貝靜態資源文件 COPY . /app/ # 工做目錄 WORKDIR /app RUN yarn config set registry https://registry.npm.taobao.org \ && yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass \ && yarn global add http-server@0.9.0 \ && yarn install \ && yarn build # 暴露端口 EXPOSE 80 # 啓動參數 CMD [ "http-server", "build", "-p", "80" ]
可是,有種狀況是分層更優的,共目的是爲了減小docker編譯時間,好比:docker
FROM alpine:latest # command1耗時久,且比較穩定 RUN command1 # command2涉及更新內容頻繁 RUN command2
由於command1
耗時久,好比安裝依賴包,而command2
更新頻繁,好比代碼修改。這種場景下,若是每次編譯都須要安裝好久的依賴包,這樣體驗很是差,由於安裝依賴包這部分不多有變化,因此若是分開2層,前面安裝依賴包就會使用緩存,這樣編譯就很是快了。npm
在保證功能前提下,儘可能使用更小的鏡像。好比使用基於alpine
製做的鏡像,或者帶alpine
tag的鏡像。
還有使用谷歌Distrolessubuntu
Alpine Linux 是:一個基於 musl libc 和 busybox 的面向安全的輕量級 Linux 發行版。
換句話說,它是一個體積更小也更安全的 Linux 發行版。centos
好比如下示例,選擇帶alpine
FROM node:lts-alpine RUN apk --no-cache add ca-certificates curl git \ && rm -rf /var/cache/apk/* \ && update-ca-certificates
如下整理了經常使用的基礎鏡像的清理命令:
基礎鏡像 | 清理命令 |
---|---|
alpine |
rm -rf /var/cache/apk/* |
centos /oraclelinux |
rm -rf /var/cache/yum/* |
ubuntu /debian |
apt autoclean -y && apt autoremove -y && rm -rf /var/lib/apt/* |
仍然是這個示例,如下含有刪除緩存命令rm -rf /var/cache/apk/*
。
FROM node:lts-alpine RUN apk --no-cache add ca-certificates curl git \ && rm -rf /var/cache/apk/* \ && update-ca-certificates
.dockerignore
.dockerignore
文件的做用相似於 git 工程中的 .gitignore
。不一樣的是 .dockerignore
應用於 docker 鏡像的構建,它存在於 docker 構建上下文的根目錄,用來排除不須要上傳到 docker 服務端的文件或目錄。
docker 在構建鏡像時首先從構建上下文找有沒有 .dockerignore
文件,若是有的話則在上傳上下文到 docker 服務端時忽略掉 .dockerignore
裏面的文件列表。這麼作顯然帶來的好處是:
.dockerignore
示例:
.codeclimate .gitlab-ci.yml Dockerfile .git .gitignore ci
使用方法具體參考:
https://docs.docker.com/engine/reference/builder/#dockerignore-file
前提:docker版本17.05
或更高
示例Dockerfile
# 基礎鏡像 FROM node:10.16-alpine as builder # 拷貝靜態資源文件 COPY . /app/ # 工做目錄 WORKDIR /app ################# 舊版本使用http-server插件 ##################### # 舊運行命令 #RUN yarn config set registry https://registry.npm.taobao.org \ # && yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass \ # && yarn global add http-server@0.9.0 \ # && yarn install \ # && yarn build ## 暴露端口 #EXPOSE 80 # ## 啓動參數 #CMD [ "http-server", "build", "-p", "80" ] ################# 舊版本使用http-server插件 ##################### # 新運行命令 RUN yarn config set registry https://registry.npm.taobao.org \ && yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass \ && yarn install \ && yarn build FROM nginx:1.17.5-alpine # 維護人 LABEL maintainer="ygqygq2" # 工做目錄 WORKDIR /usr/share/nginx/html copy --from=builder /app/build . ######################## 使用默認,可沒必要添加 ####################### # 暴露端口 #EXPOSE 80 # 啓動命令及參數 #ENTRYPOINT ["nginx", "-g", "daemon off;"] ######################## 使用默認,可沒必要添加 #######################
關鍵的地方是 FROM image:tag AS name
copy --from name /path/ /path/
參考資料:
[1] https://docs.docker.com/engine/reference/builder/#dockerignore-file
[2] https://docs.docker.com/develop/develop-images/multistage-build/