如何使用 Dockerfile自定義鏡像?

如何使用 Dockerfile自定義鏡像?

開始之前

之前在隔壁專題(公衆號出門左轉 Nginx專題) 推送過一篇文章 Nginx 緩存服務器(番外)定製Docker鏡像 我們將 ngx_cache_purge模塊添加到自定義的 Nginx鏡像中,避免每次創建容器後再次安裝 ngx_cache_purge模塊這個繁瑣的步驟。

今天使用一個 Java項目的示例,介紹下如何使用 Dockerfile 創建一個自定義Java鏡像,以及在 Dockerfile 中常用的一些指令。

環境描述

容器鏡像: openjdk:8-jre
容器系統: debian 8 (jessie)
Docker主機: Ubuntu Server 16.04
CI工具: Jenkins & Maven 
項目程序: 編譯好的可執行jar包

操作步驟

  1. 準備 Dockerfile 文件
cat bms/Dockerfile

# bms
FROM openjdk:8-jre
MAINTAINER dongnan

# apt
COPY conf/sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y \
        wkhtmltopdf xvfb \
        && apt-get clean && rm -r /var/lib/apt/lists/*

# env
ENV TZ=Asia/Shanghai \
    LANG=C.UTF-8

# package
COPY src/bms.jar /root/bms.jar

# workdir
WORKDIR /root/

# statement Port
EXPOSE 8080

# cmd
CMD ["java","-jar","/root/bms.jar"]
  1. 構建鏡像
    守護進程讀取 Dockerfile 文件然後按照文件中的指令順序執行。構建鏡像時會一層層構建,前一層是後一層的基礎,每一層構建完就不會再發生改變,後一層上的任何改變只發生在自己這一層。
docker build -t bms:0.0.1 .
Sending build context to Docker daemon 2.048 mb
# 省略....
Successfully built cd34135ed904

注意: docker build 命令最後有一個. 表示當前目錄,而 Dockerfile 就在當前目錄,是在指定上下文路徑

  1. 驗證鏡像
    嘗試使用這個鏡像創建一個容器,如果容器正常運行說明構建成功。
docker run --name test -tid bms:0.0.1

鏡像使用的是分層存儲容器也是如此,每個容器運行時是以鏡像爲基礎層,在其上創建一個當前容器的存儲層。

容器運行後修改了容器內的文件,也就是改動了容器的存儲層,通過 docker diff 命令看到具體的改動。

docker container diff test
C /root         # C 改變
A /root/logs    # A 添加
A /root/logs/bms.log
C /tmp
A /tmp/tomcat-docbase.1383372449962167136.9290
  1. 命令幫助
docker build --help

如何使用 Dockerfile自定義鏡像?

Dockerfile 常用指令

Dockerfile 中每一個指令都會建立一層,上面的示例創建了9層鏡像。

FROM: 用於指定基礎鏡像,一個有效的 Dockerfile 必須使用 FROM做第一個指令。
MAINTAINER: 用於設置作者信息。
RUN: 是用來執行命令的,並將結果提交到當前鏡像層。
ENV: 設置環境變量,無論是後面的其它指令,還是運行時的容器,都可以直接使用這個環境變量。
COPY: 將從構建上下文目錄中 <源> 文件/目錄複製到新的一層的鏡像內的 <目標> 位置。
ADD: 與 `COPY` 指令功能基本一致。但是在 COPY 基礎上增加了一些功能,例如 ADD會做自動解壓工作。
WORKDIR: 用來指定工作目錄(**當前目錄**),如該目錄不存在則會幫你建立目錄。
EXPOSE: 是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會因爲這個聲明就會開啓這個端口。
CMD: 用於指定默認容器主進程的啓動命令(容器就是進程,在啓動容器的時候需要指定所運行的程序及參數)。

Dockerfile 最佳實踐

部分摘選

  1. 在 Docker 官方的 Dockerfile 最佳實踐文檔中要求儘可能的使用 COPY,因爲COPY 的語義很明確,就是複製文件而已,而 ADD 最適合使用的場景就是需要自動解壓縮的場景。

  2. 另外需要注意的是ADD 指令會令鏡像構建緩存失效,從而可能會令鏡像構建變得比較緩慢。

  3. CMD 指令用於執行目標鏡像中包含的軟件可以包含參數,CMD 大多數情況下都應該以 CMD ["executable", "param1", "param2"...] 的形式使用,例如 CMD ["nginx", "-g", "daemon off;"]

  4. RUN 與 CMD 的區別,RUN 在構建鏡像時執行,CMD則是在鏡像構建成功後在容器中執行。

更多內容請參考2號文。

參考文章

doker&k8s Qun [703906133]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章