本文章是在網易云課堂的課程學習中編寫,部分圖片從網易云課堂ppt引用
【基礎概念】
鏡像的定制實際上就是定制每一層所添加的配置、文件。我們可以把每一層修改、安裝、構建、操作的命令都寫入一個腳本,這個腳本就是 Dockerfile,用這個腳本來構建、定制鏡像。
Dockerfile 是一個文本文件,里面包含了一條條的指令(Instruction),每一條指令構建一層。
【使用 Dockerfile構建私有鏡像】
接下來,使用 Dockerfile 定制 nginx 鏡像為例:
1、新建Dockerfile文件
在一個空白目錄中,建立一個文本文件,并命名為Dockerfile
mkdir mynginx
cd mynginx
touch Dockerfile
2、編輯Dockerfile文件
在Dockerfile文件寫入以下兩條指令
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
FROM 指定基礎鏡像
我們定制鏡像,是以一個鏡像為基礎,在其上進行定制。基礎鏡像是必須指定的,一個 Dockerfile中,FROM 是必備的指令,并且必須是第一條指令。如果不使用任何現有鏡像為基礎,則可使用 **scratch **鏡像,這是一個虛擬的空白鏡像。RUN 執行命令
RUN命令有兩種格式:
- shell 格式:RUN <命令>
比如:RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
- exec 格式:RUN ["可執行文件", "參數1", "參數2"]
比如:RUN make -C /usr/src/redis
3、構建鏡像
在 Dockerfile 文件所在目錄執行:
docker build -t mynginx:1.0 .
現在通過docker images命令,可以查看到我們自己定制的鏡像了
4、基于該鏡像運行容器
docker run --name mynginx -p 80:80 mynginx:1.0
【Dockerfile指令詳解】
Dockerfile提供了十多個指令,除了上面已經用到的FROM、RUN指令,我們來繼續學習一下其他的指令。
1、COPY 復制文件
COPY 指令將 從構建上下文目錄中 <源路徑> 的文件/目錄 復制到 新的一層的鏡像內的 <目標路徑> 位置。
有兩種格式:
COPY <源路徑>... <目標路徑>
COPY ["<源路徑1>",... "<目標路徑>"]
比如:
COPY package.json/usr/src/app/
加上通配符也可以,要滿足 Go 的 filepath.Match 規則
COPY hom* /mydir/
COPY hom?.txt /mydir/
2、ADD 更高級的復制文件
ADD 指令和COPY 的格式和性質基本一致,但是在 COPY 基礎上增加了一些功能。
ADD ubuntu -xenial-core-cloudimg -amd64-root.tar.gz /
根據官方推薦,復制文件推薦還是使用COPY指令。適合使用 ADD 的場合,是需要自動解壓縮的場合。
在 COPY 和 ADD 指令中選擇的時候,可以遵循這樣的原則,所有的文件復制均使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD。
3、CMD 容器啟動命令
CMD 指令的格式和 RUN 相似,也是兩種格式:
shell 格式:CMD <命令>
exec 格式:CMD ["可執行文件", "參數1", "參數2"...]
- 參數列表格式:CMD ["參數1", "參數2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具體的參數。
Docker容器是進程,在啟動容器的時候,需要指定所運行的程序及參數。CMD 指令就是用于指定默認的容器主進程的啟動命令。
4、ENTRYPOINT 入口點
ENTRYPOINT 的目的和CMD 一樣,都是在指定容器啟動程序及參數。ENTRYPOINT 在運行時也可以替代,不過比 CMD 要略顯繁瑣,需要通過 docker run 的參數 --entrypoint 來指定
5、ENV 設置環境變量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2> ...
比如:ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
6、ARG 構建參數
ARG <參數名>[=<默認值>]
構建參數和 ENV 的效果一樣,都是設置環境變量。不同的是,ARG 所構建的環境變量,在將來容器運行時,是不會存在這些環境變量的。但是不要使用 ARG 保存密碼之類的信息,因為 docker history 還是可以看到所有值的。
7、VOLUME 定義匿名卷
VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>
容器運行時應該盡量保持容器存儲層不發生寫操作,對于數據庫類需要保存動態數據的應用,其數據庫文件應該保存于卷(volume)中。
為了防止運行時用戶忘記將動態文件所保存目錄掛載為卷,在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷,這樣在運行時如果用戶不指定掛載,其應用也可以正常運行,不會向容器存儲層寫入大量數據。
8、EXPOSE 暴露端口
EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時并不會因為這個聲明應用就會開啟這個端口的服務。
在 Dockerfile 中寫入這樣的聲明有兩個好處,一個是幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射;另一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。
9、WORKDIR 指定工作目錄
WORKDIR <工作目錄路徑>
使用 WORKDIR 指令可以來指定工作目錄(或者稱為當前目錄),以后各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR 會幫你建立目錄。如果需要改變以后各層的工作目錄的位置,那么應該使用 WORKDIR 指令。
10、USER 指定當前用戶
USER <用戶名>
USER 指令和 WORKDIR 相似,都是改變環境狀態并影響以后的層。WORKDIR 是改變工作目錄,USER 則是改變之后層的執行 RUN, CMD 以及 ENTRYPOINT 這類命令的身份。
當然,USER 只是幫助你切換到指定用戶而已,這個用戶必須是事先建立好的,否則無法切換。
11、HEALTHCHECK 健康檢查
HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康狀況的命令
HEALTHCHECK NONE:如果基礎鏡像有健康檢查指令,使用這行可以屏蔽掉其健康檢查指令
HEALTHCHECK 指令是告訴 Docker 應該如何進行判斷容器的狀態是否正常,這是 Docker 1.12 引入的新指令。
假設有個鏡像是個簡單的 Web 服務,我們希望增加健康檢查來判斷其 Web 服務是否在正常工作,我們可以用 curl 來幫助判斷,其 Dockerfile 的 HEALTHCHECK 可以這么寫:
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
這里我們設置的是每 5 秒檢查一次,如果健康檢查命令超過 3 秒沒響應就視為失敗,并且使用 curl -fs http://localhost/ || exit 1 作為健康檢查命令。
12、ONBUILD 為他人作嫁衣
ONBUILD <其它指令>
ONBUILD 是一個特殊的指令,它后面跟的是其它指令,比如 RUN,COPY 等,而這些指令,在當前鏡像構建時并不會被執行。只有當以當前鏡像為基礎鏡像,去構建下一級鏡像的時候才會被執行。