Dockerfile

ABEE發表於2022-01-07

Dockerfile 是由一系列指令和引數構成的指令碼,一個 Dockerfile 裡面包含了構建整個映象的完整命令。

工作中,由於業務水平與技術選型不同,在使用 Docker 起服務時,需要定製專案映象。透過兩種方式:

  • Docker commit
  • Dockerfile
Docker commit

基於一個執行狀態的容器,在容器內安裝專案執行所需要的環境依賴,再建立出一個新的映象。

$ docker commit -a "author" -m "commit info" container_id image_name:tag

使用這種方式製作的映象,對外不可解釋,不知道映象內的環境組成,不方便排查問題,可維護性差。

Dockerfile

Dockerfile 是一個文字文件,透過 docker build 命令去執行檔案內部定義的指令,自動構建映象。推薦使用這種方法,可以直觀的看到映象構建記錄。

構建映象時,Dockerfile 的目錄最好不要放其他檔案,因為構建時會將該目錄下全部檔案傳輸到 docker daemon,檔案過大時,影響構建效能。

構建命令如下:

  • -t 指定映象名稱和標籤
  • -f 指定 Dockerfile 檔案路徑
  • . 代表當前路徑,千萬別忘記寫 bash $ docker build -t pytest:v1 -f Dockerfile .

Dockerfile 常用指令

指令不區分大小寫,為方便區分指令和引數,約定指令統一大寫。

FROM    # 指定基礎映象,Dockerfile 必須以 FROM 指令開始(除 ARG)
LABEL   # 標籤資訊,作者、版本等;<key>=<value> <key>=<value> ...
ENV     # 容器啟動的環境變數;<key>=<value> ...
ARG     # 僅作用於 Dockerfile 的環境變數,可以出現在 FROM 指令之前
USER    # 指定執行容器時的使用者名稱或 UID,預設管理員使用者,後續 RUN 也會使用指定使用者
WORKDIR # 設定工作目錄,作用於 RUN、CMD、ENTRYPOINT、ADD 指令
ADD     # 新增壓縮檔案到映象中,自動解壓縮
COPY    # 複製檔案到映象中
VOLUME  # 掛載目錄
RUN     # 執行命令,每條 RUN 指令在當前基礎映象上執行,並且會提交一個新的映象層
EXPOSE  # 對外暴漏埠號,可以被容器執行時的 -p 引數覆蓋掉
CMD     # 容器啟動時執行的預設命令
ENTRYPOINT   # 容器啟動時指定引數
HEALTHCHECK  # 容器健康狀態檢查

編寫 Dockerfile 的最佳實踐參考官方文件:

Best practices for writing Dockerfiles

這裡簡單列出幾點:

  • 多行引數使用換行符
  • 不要安裝非必要的包
  • 每個容器只幹一件事,解耦應用程式
  • 儘量減少映象層數
  • 充分利用構建快取

映象製作過程中,每個指令代表一層,映象是由多層映象累加起來的。指令會產生快取,構建過程中會優先使用快取,所以當開發映象時,先用多個 RUN 命令,充分利用下載的快取,提高除錯的效率。當然也可以指定 --no-cache 引數停用快取。

Dockerfile 開發完成後,用 && 符號把 RUN 指令合併換行,作為同一層映象進行構建。因為映象的分層原理,每多一層就會多一次 IO 開銷,當指令過多,可能會影響系統效能。

演示

使用 Dockerfile 構建 nginx 容器。

# index.html
<h1>Hello Nginx!</h1>
# Dockerfile

# 匯入基礎映象
FROM nginx:latest

# 指定資訊
LABEL Description="Nginx Testing Service."

# 設定環境變數
ENV WELCOME "hello, nginx!"

# ARG 設定的環境變數只在 dockerfile 生效
ARG dir=/usr/share/nginx

# 設定工作目錄
WORKDIR $dir/html

# 切換使用者
USER root

# 執行安裝命令
RUN apt-get -y update && apt-get install -y curl

# 複製 index.html 檔案到工作目錄下
COPY index.html .

# 對映 80 埠
EXPOSE 80

# 容器啟動引數
CMD ["nginx", "-g", "daemon off;"]

# 健康檢查,透過訪問 Nginx 服務 80 埠,來判斷容器是否正常執行
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1
構建並驗證
# 構建映象
$ docker build -t nginx:test .
...
# 啟動容器
$ docker run -d -p 80:80 --name demo nginx:test
...

# 訪問 IP 地址,即可看到自定義的歡迎頁

# 進入容器
$ docker exec -it demo bash
# 使用者為 root
# 開始目錄為設定的工作目錄
# 執行 env 命令,出現設定的環境變數
root@*:/usr/share/nginx/html $ env
WELCOME=hello, nginx!

# 檢視容器日誌;健康檢查生效
$ docker logs -f demo
127.0.0.1 - - [07/Jan/2022:09:52:12 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"

以上內容在官方文件都可以找到詳細的介紹,這裡摘要出來,方便查閱。

相關文章