學(xué)習(xí)Docker就應(yīng)該掌握的dockerfile語法與指令
在日常的工作中,常常需要制作自己的項(xiàng)目的鏡像,一般通過以下兩種方式制作鏡像:Docker commit、Dockerfile。
Docker commit
Docker commit一般用做從一個(gè)運(yùn)行狀態(tài)的容器來創(chuàng)建一個(gè)新的鏡像。定制鏡像應(yīng)該使用Dockerfile來完成。
docker commit 容器名 新鏡像名:tag
使用這種方式的缺點(diǎn)是:1.對外不可解釋,不方便排查問題, 2.可維護(hù)性差、可閱讀性差。
Dockerfile
Dockerfile 是由一系列指令和參數(shù)構(gòu)成的腳本,一個(gè) Dockerfile 里面包含了構(gòu)建整個(gè)鏡像的完整命令。Docker 通過docker build執(zhí)行 Dockerfile 中的一系列指令自動構(gòu)建鏡像。以下是 Dockerfile 中一些常用字段的含義:
FROM:基礎(chǔ)鏡像,F(xiàn)ROM 命令必須是 Dockerfile 的首個(gè)命令。
LABEL:為鏡像生成元數(shù)據(jù)標(biāo)簽信息。原有指令 MAINTAINER 已經(jīng)放棄使用,用 LABEL?maintainer="hogwarts@testing-studio.com" 替代。
USER:指定運(yùn)行容器時(shí)的用戶名或 UID,后續(xù) RUN 也會使用指定用戶。
RUN:RUN 命令是 Dockerfile 執(zhí)行命令的核心部分。它接受命令作為參數(shù)并用于創(chuàng)建鏡像。每條 RUN 命令在當(dāng)前基礎(chǔ)鏡像上執(zhí)行,并且會提交一個(gè)新鏡像。
VOLUME:定義匿名卷,容器運(yùn)行時(shí)應(yīng)該盡量保持容器存儲層不發(fā)生寫操作,為了防止運(yùn)行時(shí)用戶忘記將動態(tài)文件保存的目錄掛載為卷,可以事先指定某些目錄掛載為匿名卷。這樣就不會向容器存儲層寫入大量數(shù)據(jù)。
WORKDIR:WORKDIR 命令用于設(shè)置 CMD 指明的命令的運(yùn)行目錄。為后續(xù)的 RUN、CMD、ENTRYPOINT、ADD 指令配置工作目錄??梢允褂枚鄠€(gè) WORKDIR 指令,后續(xù)命令如果參數(shù)是相對路徑,則會基于之前命令指定的路徑。使用 docker exec -it 進(jìn)入容器后,默認(rèn)也會進(jìn)入到 WORKDIR 指定的目錄。
ENV:指定容器啟動時(shí)的環(huán)境變量(注意,只有在容器啟動時(shí),啟動腳本能讀取到,如果希望其他用戶登錄到容器也生效的話,需要寫入 .bashrc)。
COPY:COPY 命令有兩個(gè)參數(shù),源和目標(biāo)。它的基本作用是從源系統(tǒng)的文件系統(tǒng)上復(fù)制文件到目標(biāo)容器的文件系統(tǒng)。
EXPOSE:指定端口轉(zhuǎn)發(fā)
CMD:設(shè)置容器創(chuàng)建是執(zhí)行的默認(rèn)命令。支持三種格式,默認(rèn)會被 docker run 指定的參數(shù)覆蓋。每個(gè)容器只能執(zhí)行一條 CMD 命令。執(zhí)行的命令和參數(shù)當(dāng)指定多個(gè)時(shí),只有最后一個(gè)起效。
CMD [“executable”, “參數(shù)1”,“參數(shù)2”]:使用 exec 方式執(zhí)行,推薦。
CMD command 參數(shù)1 參數(shù)2:shell 方式執(zhí)行。
CMD [“參數(shù)1”,“參數(shù)2”]:提供給 ENTRYPOINT 做默認(rèn)參數(shù)。
ENTRYPOINT:指定容器的“入口”。支持兩種格式,默認(rèn)不會被 docker run 指定的參數(shù)覆蓋??梢灾付?--entrypoint 參數(shù)去覆蓋。每個(gè) Dockerfile 中只能有一個(gè) ENTRYPOINT,當(dāng)指定多個(gè)時(shí),只有最后一個(gè)起效。
ENTRYPOINT [“executable”, “參數(shù)1”,“參數(shù)2”]:使用 exec 方式執(zhí)行。推薦 - ENTRYPOINT command 參數(shù)1 參數(shù)2:shell 方式執(zhí)行。
shell 方式下不能接受 CMD 的參數(shù)。
HEALTHCHECK:Docker 1.12版本后引入的判斷容器運(yùn)行狀態(tài)是否正常。
通過上面對指令的了解后,我們最后通過一個(gè)小小的 demo 來給大家演示一下怎么組合使用這些指令。
1.新建一個(gè) index.html 文件,內(nèi)容
<h1>Hogwarts.</h1>
2.新建 Dockerfile 文件
# 基于 nginx:1.17.9?
鏡像構(gòu)建?
FROM nginx:1.17.9?
# 指定信息?
LABEL maintainer="hogwarts@testing-studio.com>"?
?# 設(shè)置環(huán)境變量?
ENV NGINX_VERSION 1.17.9?
# 切換 root?
用戶 USER root?
# 執(zhí)行命令,安裝 curl 軟件,設(shè)置軟鏈接把 nginx 服務(wù)的日志顯示到終端輸出上。 RUN apt-get -yq update && apt-get install -y curl && \?
ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log?
# 設(shè)置容器內(nèi) /data 目錄為匿名卷
?VOLUME ["/data"]?
# 設(shè)置工作目錄?
WORKDIR /data/html/?
# 復(fù)制 index.html 文件到 WORKDIR 目錄下。
?COPY index.html .?
?# 映射 80 端口?
EXPOSE 80?
?# 此處 CMD 作為 ENTRYPOINT 的參數(shù)。
# CMD ["nginx", "-g", "daemon off;"]
?CMD ["-g", "daemon off;"]?
# 設(shè)置容器啟動的命令
?ENTRYPOINT ["nginx"]?
?# 檢查容器健康,通過訪問 Nginx 服務(wù) 80 端口,來判斷容器服務(wù)是否運(yùn)行正常。 HEALTHCHECK --interval=5s --timeout=3s \
?CMD curl -fs http://localhost/ || exit 1
3.構(gòu)建鏡像
docker build -t n:v1 .
4.運(yùn)行容器
docker run --name nv1 -p 8080:80 n:v1
啟動后,HEALTHCHECK 就會5秒鐘訪問一次 Nginx 服務(wù),來確保容器運(yùn)行的狀態(tài)。

服務(wù)正常的狀態(tài)。COMMAND 欄顯示的命令,為 ENTRYPOINT 指令和 CMD 指令合并后的命令。

5.進(jìn)入容器,驗(yàn)證結(jié)果。
docker exec -it nv1 bash
exec:執(zhí)行命令 - it:交互式 tty 終端 - nv1:容器啟動的名字 - bash:使用的 shell 類型
進(jìn)入容器后,默認(rèn)會切換到 /data/html 目錄,這個(gè)是 WORKDIR 指令指定的目錄。
可以使用 id 命令查看當(dāng)前用戶信息,顯示為 root。這個(gè)是 USER 指令指定的用戶。
使用 ls 命令來查看當(dāng)前目錄的文件,會看到 index.html 文件,這個(gè)是 COPY 指令復(fù)制到容器的文件。
使用 env 命令可以查看當(dāng)前環(huán)境下有一個(gè)變量 NGINX_VERSION=1.17.9 這個(gè)是 ENV 指令指定的信息。

項(xiàng)目的鏡像的內(nèi)容就先說到這里,對Docker commit、Dockerfile是不是有了更多一些的了解了呢?