Docker 鏡像制作最佳實踐

Dockerfile編寫規(guī)范檢查工具

hadolint是一個檢查Dockerfile是否符合編寫規(guī)范的工具。使用起來非常簡單拴袭,從GitHub上下載對應(yīng)系統(tǒng)的可執(zhí)行文件然后執(zhí)行:

hadolint Dockerfile

GitHub官網(wǎng)和介紹:https://github.com/hadolint/hadolint/blob/master/README.md

查看Docker構(gòu)建歷史

對于已有鏡像,可以查看docker image構(gòu)建歷史和每層大小沽损,決定是否需要優(yōu)化渐排。

docker history <image>

最佳實踐

Docker官網(wǎng)最佳實踐講解:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

保持鏡像簡單

  • 不要將多個應(yīng)用打包到一個鏡像中屈暗。
  • 不要安裝用不到的軟件包。
  • 減少鏡像的層數(shù)屏富。將RUN命令的內(nèi)容合并在一起晴竞,形成一條RUN命令。

使用.dockerignore

在不影響項目結(jié)構(gòu)的情況下役听,可以使用.dockerignore文件(寫法和.gitignore類似)颓鲜,排除不需要加入鏡像的文件。

使用多階段構(gòu)建

多階段構(gòu)建可以顯著減少最終鏡像占用的空間大小典予。

一個典型的用法是將項目編譯和和最終使用環(huán)境分離開甜滨。這樣最終鏡像不會包含編譯過程的中間產(chǎn)物。

# syntax=docker/dockerfile:1
FROM golang:1.16-alpine AS build

# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep

# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only

# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project

# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]

Dockerfile指令順序

Dockerfile中盡量把可能發(fā)生變化的指令放在后面瘤袖。這樣構(gòu)建時可以充分利用鏡像緩存衣摩。

容器內(nèi)不要使用sudo

不能使用sudo。sudo和su命令處理signal的時候會有非常奇怪的問題捂敌。sudo的進程號為1艾扮,sudo后命令的進程號不是1。只有PID為1的進程才會響應(yīng)系統(tǒng)發(fā)送過來的信號量占婉。所以容器內(nèi)不能使用sudo su等命令啟動應(yīng)用進程泡嘴。

解決方法:

  1. 如果入口腳本不需要root用戶執(zhí)行,建議使用Dockerfile的USER指令逆济,在CMD/ENTRYPOINT之前切換用戶酌予。
  2. 如果入口腳本需要用root執(zhí)行,但是啟動主進程的時候需要其他用戶奖慌,建議使用gosu抛虫。可參考:https://blog.csdn.net/boling_cavalry/article/details/93380447

主進程PID需要為1

如果主進程PID不為1简僧,Docker容器主進程無法響應(yīng)系統(tǒng)signal建椰。

為了確保主進程PID為1,入口腳本執(zhí)行主進程的時候必須使用exec <啟動命令>方式調(diào)用岛马。例如:

exec gosu redis "$0" "@"

apt-get之后需要清理

不推薦的使用方式:

RUN apt-get update && apt-get install -y python

推薦的使用方式:

RUN apt-get update && apt-get install -y python \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

WORKDIR 需要使用絕對路徑

WORKDIR使用相對路徑的話棉姐,需要搞清楚上文中的WORKDIR屠列。上文中的WORKDIR可能隱藏在了base image中,出現(xiàn)問題非常難以排查伞矩。因此WORKDIR需要使用絕對路徑脸哀。

Dockerfile中使用root用戶執(zhí)行命令之后,一定要切換會非root用戶

不推薦使用:

FROM debian:buster
USER root
RUN ...

推薦使用:

FROM debian:buster
USER root
RUN ...
USER guest

使用WORKDIR 切換工作目錄扭吁,盡量不要使用cd命令。

建議所有的路徑使用絕對路徑盲镶。

RUN命令中如果使用了cd命令侥袜,僅在這一條RUN中生效。后面RUN命令的目錄會回到WORKDIR溉贿。

base image需要指定版本

不推薦使用:

FROM debian:latest

推薦使用:

FROM debian:jessie

yum apt-get等命令安裝軟件包時使用-y參數(shù)

不加-y很容易遇到問題中斷構(gòu)建過程枫吧。

pip安裝時添加參數(shù)--no-cache-dir

在Docker鏡像中沒有緩存軟件包的必要。加上此參數(shù)可減小鏡像空間占用宇色。

RUN pip3 install --no-cache-dir foobar

apk安裝軟件使用--no-cache參數(shù)

FROM alpine:3.7
RUN apk --no-cache add foo=1.0

apt yum pip等包管理工具安裝軟件時需要指定軟件包版本

如果不指定版本號九杂,隨著軟件包的更新,不同時間構(gòu)建出的鏡像中安裝的軟件包版本可能會不同宣蠕。

不要使用apt命令例隆,使用apt-get

apt是一個用戶終端工具。它的行為不穩(wěn)定抢蚀,可能隨著版本的變化而變化镀层。不推薦使用。

yum dnf zypper 等安裝軟件包之后需要執(zhí)行clean all

例如:

RUN yum install -y httpd-2.24.2 && yum clean all
RUN dnf install -y httpd-2.24.2 && dnf clean all
RUN zypper install -y httpd=2.4.46 && zypper clean

添加文件和目錄的時候使用COPY命令

僅僅在需要使用自動解壓(將tar或者zip解壓到鏡像某個目錄中)的時候才允許使用ADD皿曲。其他情況一律使用COPY唱逢。

useradd需要指定-l參數(shù)

英文解釋如下:

Without the -l or the --no-log-init flag, useradd will add the user to the lastlog and faillog databases. This can result in the creation of logically large (sparse) files under /var/log, which in turn unnecessarily inflates container image sizes. This is due to the lack of support for sparse files in overlay filesystems.

大致解釋為如果不添加-l或者是--no-log-inituseradd命令會把用戶加入lastlog和faillog數(shù)據(jù)庫屋休。會在/var/log目錄創(chuàng)建大量的疏松文件坞古。Docker image用的是overlay文件系統(tǒng),對這種疏松文件的支持不足劫樟。建議創(chuàng)建用戶時添加-l或者--no-log-init痪枫。

使用cd ... || exit代替簡單的cd

構(gòu)建時cd命令可能會失敗,但是構(gòu)建會繼續(xù)執(zhí)行毅哗。后續(xù)的構(gòu)建命令會在錯誤的目錄中執(zhí)行听怕。

需要使用cd ... || exit(function內(nèi)使用cd ... || return)可以在cd遇到錯誤的時候退出構(gòu)建。

wget大文件需要使用--progress參數(shù)

可以避免打印過多的日志虑绵。

FROM ubuntu:20
RUN wget --progress=dot:giga https://example.com/big_file.tar

參考鏈接

https://zhuanlan.zhihu.com/p/457069205

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尿瞭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翅睛,更是在濱河造成了極大的恐慌声搁,老刑警劉巖黑竞,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異疏旨,居然都是意外死亡很魂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門檐涝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來遏匆,“玉大人,你說我怎么就攤上這事谁榜》福” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵窃植,是天一觀的道長帝蒿。 經(jīng)常有香客問我,道長巷怜,這世上最難降的妖魔是什么葛超? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮延塑,結(jié)果婚禮上绣张,老公的妹妹穿的比我還像新娘。我一直安慰自己关带,他們只是感情好胖替,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豫缨,像睡著了一般独令。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上好芭,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天燃箭,我揣著相機與錄音,去河邊找鬼舍败。 笑死招狸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的邻薯。 我是一名探鬼主播裙戏,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼厕诡!你這毒婦竟也來了累榜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎壹罚,沒想到半個月后葛作,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡猖凛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年赂蠢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辨泳。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡虱岂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出菠红,到底是詐尸還是另有隱情量瓜,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布途乃,位于F島的核電站,受9級特大地震影響扔傅,放射性物質(zhì)發(fā)生泄漏耍共。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一猎塞、第九天 我趴在偏房一處隱蔽的房頂上張望试读。 院中可真熱鬧,春花似錦荠耽、人聲如沸钩骇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倘屹。三九已至,卻和暖如春慢叨,著一層夾襖步出監(jiān)牢的瞬間纽匙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工拍谐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烛缔,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓轩拨,卻偏偏與公主長得像践瓷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子亡蓉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容