1. COPY 復(fù)制文件
格式:
COPY [--chown=<user>:<group>] <源路徑>... <目標(biāo)路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標(biāo)路徑>"]
COPY 指令將從構(gòu)建上下文目錄中 <源路徑> 的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑> 位置。
<源路徑> 可以是多個(gè),甚至可以是通配符,其通配符規(guī)則要滿足 Go 的filepath.Match 規(guī)則。
源文件的各種元數(shù)據(jù)都會(huì)保留。比如讀、寫(xiě)、執(zhí)行權(quán)限、文件變更時(shí)間等。這個(gè)特性對(duì)于鏡像定制很有用。特別是構(gòu)建相關(guān)文件都在使用 Git 進(jìn)行管理的時(shí)候。
2. ADD 更高級(jí)的復(fù)制文件
ADD 指令和 COPY 的格式和性質(zhì)基本一致。但是在 COPY 基礎(chǔ)上增加了一些功能。
- 比如 <源路徑> 可以是一個(gè) URL。Docker 引擎會(huì)試圖去下載這個(gè)鏈接的文件放到 <目標(biāo)路徑> 去。下載后的文件權(quán)限自動(dòng)設(shè)置為 600。
- 如果 <源路徑> 為一個(gè) tar 壓縮文件的話,壓縮格式為 gzip , bzip2 以及xz 的情況下, ADD 指令將會(huì)自動(dòng)解壓縮這個(gè)壓縮文件到 <目標(biāo)路徑> 去。
但需要注意的是:
ADD 指令會(huì)令鏡像構(gòu)建緩存失效,從而可能會(huì)令鏡像構(gòu)建變得比較緩慢。
COPY 和 ADD 指令中選擇的時(shí)候,可以遵循這樣的原則,所有的文件復(fù)制均使用 COPY 指令,僅在需要自動(dòng)解壓縮的場(chǎng)合使用 ADD 。
3. CMD 容器啟動(dòng)命令
shell 格式: CMD <命令>
exec 格式: CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...]
參數(shù)列表格式: CMD ["參數(shù)1", "參數(shù)2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具體的參數(shù)。
Docker 不是虛擬機(jī),容器就是進(jìn)程。既然是進(jìn)程,那么在啟動(dòng)容器的時(shí)候,需要指定所運(yùn)行的程序及參數(shù)。CMD 指令就是用于指定默認(rèn)的容器主進(jìn)程的啟動(dòng)命令的。
在指令格式上,一般推薦使用 exec 格式,這類格式在解析時(shí)會(huì)被解析為 JSON數(shù)組,因此一定要使用雙引號(hào),而不要使用單引號(hào)。
如果使用 shell 格式的話,實(shí)際的命令會(huì)被包裝為 sh -c 的參數(shù)的形式進(jìn)行
執(zhí)行.比如:
CMD echo $HOME
CMD [ "sh", "-c", "echo $HOME" ]
Docker 不是虛擬機(jī),容器中的應(yīng)用都應(yīng)該以前臺(tái)執(zhí)行,而不是像虛擬機(jī)、物理機(jī)里面那樣,用 upstart/systemd 去啟動(dòng)后臺(tái)服務(wù),容器內(nèi)沒(méi)有后臺(tái)服務(wù)的概念.
CMD service nginx start
使用 service nginx start 命令,則是希望 upstart 來(lái)以后臺(tái)守護(hù)進(jìn)程形式啟
動(dòng) nginx 服務(wù)。而剛才說(shuō)了 CMD service nginx start 會(huì)被理解為 CMD [
"sh", "-c", "service nginx start"] ,因此主進(jìn)程實(shí)際上是 sh 。那么當(dāng)
service nginx start 命令結(jié)束后, sh 也就結(jié)束了, sh 作為主進(jìn)程退出
了,自然就會(huì)令容器退出。
正確的做法是直接執(zhí)行 nginx 可執(zhí)行文件,并且要求以前臺(tái)形式運(yùn)行。
CMD ["nginx", "-g", "daemon off;"]
4. ENTRYPOINT 入口點(diǎn)
ENTRYPOINT 的目的和 CMD 一樣,都是在指定容器啟動(dòng)程序及參數(shù)。ENTRYPOINT 在運(yùn)行時(shí)也可以替代,不過(guò)需要通過(guò)docker run 的參數(shù) --entrypoint 來(lái)指定。
當(dāng)指定了 ENTRYPOINT 后, CMD 的含義就發(fā)生了改變,不再是直接的運(yùn)行其命
令,而是將 CMD 的內(nèi)容作為參數(shù)傳給 ENTRYPOINT 指令.
<ENTRYPOINT> "<CMD>"
這個(gè)鏡像在運(yùn)行時(shí),無(wú)法接受任何參數(shù)。
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "https://ip.cn" ]
使用ENTRYPOINT就可以在運(yùn)行鏡像時(shí),docker run myip -i 執(zhí)行成功。這里 -i 是新的 CMD ,因此會(huì)作為參數(shù)傳給curl。
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
5. ENV 設(shè)置環(huán)境
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>.
6. ARG 構(gòu)建
格式: ARG <參數(shù)名>[=<默認(rèn)值>]
構(gòu)建參數(shù)和 ENV 的效果一樣,都是設(shè)置環(huán)境變量。所不同的是, ARG 所設(shè)置的構(gòu)建環(huán)境的環(huán)境變量,在將來(lái)容器運(yùn)行時(shí)是不會(huì)存在的。
Dockerfile 中的 ARG 指令是定義參數(shù)名稱,以及定義其默認(rèn)值。該默認(rèn)值可以在構(gòu)建命令 docker build 中用 --build-arg <參數(shù)名>=<值> 來(lái)覆蓋。
注意:
在 1.13 之前的版本,要求 --build-arg 中的參數(shù)名,必須在 Dockerfile 中用 ARG 定義過(guò).
7. VOLUME 定義匿名卷
VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>
為了防止運(yùn)行時(shí)用戶忘記將動(dòng)態(tài)文件所保存目錄掛載為卷,在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷,這樣在運(yùn)行時(shí)如果用戶不指定掛載,其應(yīng)用也可以正常運(yùn)行,不會(huì)向容器存儲(chǔ)層寫(xiě)入大量數(shù)據(jù)。
8. EXPOSE 聲明端口
EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是聲明運(yùn)行時(shí)容器提供服務(wù)端口,這只是一個(gè)聲明,在運(yùn)行時(shí)并不會(huì)因?yàn)檫@個(gè)聲明應(yīng)用就會(huì)開(kāi)啟這個(gè)端口的服務(wù).
在 Dockerfile 中寫(xiě)入這樣的聲明有兩個(gè)好處:
一,是幫助鏡像使用者理解這個(gè)鏡像服務(wù)的守護(hù)端口,以方便配置映射;
二,是在運(yùn)行時(shí)使用隨機(jī)端口映射時(shí),也就是 docker run -P時(shí),會(huì)自動(dòng)隨機(jī)映射 EXPOSE 的端口。
9. WORKDIR 指定工作目錄
WORKDIR <工作目錄路徑>
使用 WORKDIR 指令可以來(lái)指定工作目錄(或者稱為當(dāng)前目錄),以后各層的當(dāng)前目錄就被改為指定的目錄,如該目錄不存在, WORKDIR 會(huì)幫你建立目錄。
10. USER 指定當(dāng)前用戶
USER <用戶名>[:<用戶組>]
USER 指令和 WORKDIR 相似,都是改變環(huán)境狀態(tài)并影響以后的層。 WORKDIR是改變工作目錄, USER 則是改變之后層的執(zhí)行 RUN , CMD 以及ENTRYPOINT 這類命令的身份.
# 建立 redis 用戶,并使用 gosu 換另一個(gè)用戶執(zhí)行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下載 gosu
RUN wget -O /usr/local/bin/gosu "https://github.creleases/download/1.7/gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# 設(shè)置 CMD,并以另外的用戶執(zhí)行
CMD [ "exec", "gosu", "redis", "redis-server" ]
11. HEALTHCHECK 健康檢查
HEALTHCHECK [選項(xiàng)] CMD <命令> :設(shè)置檢查容器健康狀況的命令
HEALTHCHECK NONE :如果基礎(chǔ)鏡像有健康檢查指令,使用這行可以屏蔽掉
其健康檢查指令
這是Docker 1.12 引入的新指令.
當(dāng)在一個(gè)鏡像指定了 HEALTHCHECK 指令后,用其啟動(dòng)容器,初始狀態(tài)會(huì)為starting ,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy ,如果連續(xù)一定次數(shù)失敗,則會(huì)變?yōu)?unhealthy .
--interval=<間隔> :兩次健康檢查的間隔,默認(rèn)為 30 秒;
--timeout=<時(shí)長(zhǎng)> :健康檢查命令運(yùn)行超時(shí)時(shí)間,如果超過(guò)這個(gè)時(shí)間,本次健康檢查就被視為失敗,默認(rèn) 30 秒;
--retries=<次數(shù)> :當(dāng)連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為unhealthy ,默認(rèn) 3 次
和 CMD , ENTRYPOINT 一樣, HEALTHCHECK 只可以出現(xiàn)一次,如果寫(xiě)了多個(gè),
只有最后一個(gè)生效。
命令的返回值決定了該次健康檢查的成功與否: 0 :成功; 1 :失敗; 2 :保留
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib
/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
為了幫助排障,健康檢查命令的輸出(包括 stdout 以及 stderr )都會(huì)被存儲(chǔ)于健康狀態(tài)里,可以用 docker inspect 來(lái)查看。
$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
12. ONBUILD 為他人做嫁衣裳
ONBUILD <其它指令>
ONBUILD 是一個(gè)特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而這些指令,在當(dāng)前鏡像構(gòu)建時(shí)并不會(huì)被執(zhí)行。只有當(dāng)以當(dāng)前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級(jí)鏡像的時(shí)候才會(huì)被執(zhí)行。