Dockerfile 最佳實踐
1. 只添加需要的文件
1.1 使用 .dockerignore
temp?
!README.md
Dockerfile
1.2 用到什么就添加什么
FROM alpine
ADD app /bin/
RUN apk -Uuv add --no-cache ca-certificates tini tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
mkdir /kuu
WORKDIR /kuu
COPY kuu.json .
ADD docs ./docs
ADD assets ./assets
ENTRYPOINT ["/sbin/tini","--", "app"]
目的
- 忽略多余的文件和目錄,精簡鏡像體積。
- 不必要的文件變動,不影響docker構(gòu)建過程使用緩存。
2. 一個容器運行單一進程
原子性,環(huán)境獨立。
gogs
gogs-db
3. 打上易讀的鏡像倉庫名和標簽
貼標簽,方便快速知道它的用途。
gogs
gogs-db
4. 精簡基礎(chǔ)鏡像
精簡,體積小。 可靠,推薦試用官方鏡像。alpine版本最好
Alpine Linux是一個獨立的,非商業(yè)的通用Linux發(fā)行版,專為那些喜歡安全性,簡單性和資源效率的高級用戶而設(shè)計。(官網(wǎng)介紹)
FROM alpine
4.1 再精簡一下
比如使用 --no-install-recommends 參數(shù)告訴 apt-get 不要安裝推薦的軟件包
安裝完軟件包,清 /var/lib/apt/list/ 緩存 (ubuntu)
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
libcap-dev \
libsqlite3-dev \
mercurial \
reprepro \
ruby1.9.1 \
ruby1.9.1-dev \
&& rm -rf /var/lib/apt/lists/*
- alpine 中使用 --no-cache
FROM alpine
ADD app /bin/
RUN apk -Uuv add --no-cache ca-certificates tini tzdata
刪除中間文件:比如下載的壓縮包
刪除臨時文件:如果命令產(chǎn)生了臨時文件,也要及時刪除
5. 緩存問題
5.1 層級順序
經(jīng)常變化的內(nèi)容和基本不會變化的內(nèi)容要分開,把不怎么變化的內(nèi)容放在上層,可以更好使用緩存
FROM alpine
ADD app /bin/
RUN apk -Uuv add --no-cache ca-certificates tini tzdata
Run ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
Run mkdir /kuu
5.2 減少層級
一行RUN 就會生成一個鏡像的緩存層, 使用換號符號 “\”。
FROM alpine
ADD app /bin/
RUN apk -Uuv add --no-cache ca-certificates tini tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
mkdir /kuu
5.3 解決5.2產(chǎn)生的可讀性問題
盡量按字母排序
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
6. 掛載 VOLUME
包括數(shù)據(jù)庫文件、代碼庫、配置文件……都應(yīng)該使用 VOLUME 掛載
7. EXPOSE
- Dockerfile 內(nèi)不做映射外部端口, 保證鏡像靈活性。
EXPOSE 80
- 應(yīng)該為應(yīng)用程序使用通用的傳統(tǒng)端口。 例如,包含Nginx服務(wù)器的映像將使用EXPOSE 80,而包含MongoDB的映像將使用EXPOSE 27017等。
8. 盡量使用明確版本
當(dāng)鏡像沒有指定標簽時,將默認使用latest 標簽。當(dāng)版本有大迭代升級,可能會導(dǎo)致鏡像不可用。
FROM node:alpine
FROM node:carbon-alpine 或 FROM node:8-alpine
9. 利用好CMD與ENTRYPOINT
-
CMD
The main purpose of a CMD is to provide defaults for an executing container.
CMD的作用在于執(zhí)行容器時提供默認的命令操作
-
ENTRYPOINT
An ENTRYPOINT allows you to configure a container that will run as an executable.
它可以讓你的容器功能表現(xiàn)得像一個可執(zhí)行程序一樣
9.1 CMD
CMD echo "Hello world"
執(zhí)行docker run -it [image]
但當(dāng)后面加上 docker run -it [image] /bin/bash,CMD 會被忽略掉,命令 bash 將被執(zhí)行:
root@10a32dc7d3d3:/#
9.2 ENTRYPOINT
ENTRYPOINT ["/bin/echo", "Hello"]
docker run -it [image] 啟動, 輸出 :Hello
docker run -it [image] World, 輸出:Hello World
參數(shù)化使用,可執(zhí)行的程序
10. 添加HEALTHCHECK
? ? 運行容器時,可以指定 --restart always 選項。這樣的話,容器崩潰時,Docker守護進程(docker daemon)會重啟容器。對于需要長時間運行的容器,這個選項非常有用。
但是,如果容器的確在運行,但是不可(陷入死循環(huán),配置錯誤)用怎么辦?使用HEALTHCHECK指令可以讓Docker周期性的檢查容器的健康狀況。我們只需要指定一個命令,如果一切正常的話返回0,否則返回1。
11. 多階段構(gòu)建 (可以了解一下)
當(dāng)編譯階段需要依賴特定系統(tǒng)環(huán)境,而運行時依賴少量庫或包, 最終上傳小鏡像即可。(例如: c語言編輯環(huán)境)
from debian as build-essential
arg APT_MIRROR
run apt-get update
run apt-get install -y make gcc
workdir /src
from build-essential as foo
copy src1 .
run make
from build-essential as bar
copy src2 .
run make
from alpine
copy --from=foo bin1 .
copy --from=bar bin2 .
cmd ...
參考資料
https://mp.weixin.qq.com/s/wNCfYERWU3GOBHI2juTpmg
http://www.itdecent.cn/p/9f15b81759bd
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
https://docs.docker.com/engine/reference/builder/#entrypoint