Dockerfile指令

原文發表於cu2016-06-01html

參考文檔: docker

  1. 官方文檔: https://docs.docker.com/engine/reference/builder/
  2. 官方最佳實踐:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
  3. http://seanlook.com/2014/11/17/dockerfile-introduction/
  4. CMD與ENTRYPOINT的區別:http://www.cnblogs.com/programfish/p/4101884.html

 Dockefile建立image是被推薦的方式,不一樣於"docker build"須要手動commit與rm中間層鏡像,dockerfile是自動化的建立image(二者原理均是使用基礎鏡像啓動容器後commit)。shell

一.Dockerfile構建image的優化建議

如下優化建議僅爲我的觀點。vim

1. 精簡程序

在構建image時,不須要安裝沒必要要的程序,這樣能夠保證構建出的image輕小,依賴性小且構建速度快。centos

2. 1個容器運行1個服務

大多數狀況下,建議1個容器運行1個服務便可,這樣能夠減小服務的耦合性,充分發揮容器複用及快速橫向擴展的優點。緩存

3. 合理控制鏡像層數

1條dockerfile指令會生成1層新的鏡像,鏡像層越多,image越大,容器啓動速度越慢;建議儘量減小image層數,但同時須要注意dockerfile的可讀性,即合理控制image層數。bash

4. Dockerfile指令參數排序

對指令參數的排序主要是爲了dockerfile的可讀性與確保不會重複輸入參數。如:ssh

RUN yum install -y \
Git \
net-tools \
openssh-server

5. 使用緩存

前面講到1條dockerfile指令會生成1層新的鏡像,下一條指令會基於上一步生成的鏡像構建新的鏡像層,若是一個鏡像存在相同的父鏡像與指令("ADD"指令除外),默認docker會使用緩存的鏡像,而不是從新執行dockerfile指令。ide

因此在修改Dockerfile時,爲了有效利用鏡像,能夠儘可能不動Dockerfile的前面幾行。優化

例如"MAINTAINER"通常在第二行,若是修改此處,那後續的"RUN"指令會所有執行,而不是使用緩存的鏡像層。

二.Dockerfile主要指令及語法

1. FROM

 Dockerfile第一條指令,此指令指定dockerfile構建image的基礎鏡像,若是宿主機倉庫沒有指定的基礎鏡像,則從遠端倉庫pull。

 語法:FROM <image>:<tag>

2. MAINTAINER

指明image做者,方便聯繫。

語法:MAINTAINER <author name> (author information, email and so on)

3. RUN

在當前鏡像生成的容器的外層(可讀寫層)執行命令,並commit成1個新的鏡像層,接下來的指令會在這個新的鏡像層生成的容器裏執行。

語法(2種):

  1. RUN <command>

    #shell form:在shell環境下執行,調用"/bin/sh –c"

  2. RUN ["executable", "param1", "param2"]

    #exec form:不會觸發shell,因此環境變量沒法調用,但能夠在沒有bash的image中執行

4. ADD

複製文件,有兩個參數<source>和<destination>。

注意:

  1. destination是容器內的絕對路徑,若是路徑不存在則自動建立;source能夠是文件/文件夾/URL,若是是文件/文件夾,必須是Dockerfile所在目錄的一個相對路徑,且不能含"../path/";
  2. ADD支持自動解壓tar文件,解壓以後再copy到容器內。

語法:ADD <source> <destination> 

5. COPY

基本與ADD相同,但不支持遠程URL(source),與自動解壓的功能。

注意:官方最佳實踐中建議儘可能使用copy,使用RUN與COPY的組合代替ADD,由於COPY處理更透明。

6. ENTRYPOINT

配置給容器一個可執行的命令,相似將容器變爲1個可執行文件/命令。

意味着在每次使用鏡像建立容器時,一個特定的應用程序能夠被設置爲默認程序;同時也意味着該鏡像每次被調用時僅能運行指定的應用。

注意:

  1. 多個ENTRYPOINT指令只有最後一個生效(後面覆蓋前面);
  2. exec格式時,"docker run <image>"的全部參數會追加到ENTRYPOINT以後,即"docker run <image>"的參數能夠傳遞給ENTRYPOINT,不會被覆蓋,但"docker run <image>"的參數會覆蓋CMD指令;
  3. exec格式時,由於CMD能夠爲ENTRYPOINT提供參數,ENTRYPOINT自己也能夠包含參數,且"docker run <image>"的參數能夠覆蓋CMD指令,因此能夠把那些可能須要變更的參數寫到CMD裏,而把那些不須要變更的參數寫到ENTRYPOINT裏面。
  4. exec格式時,在啓動容器時使用--entrypoint參數會覆蓋dockerfile裏的ENTRYPOINT;
  5. shell form格式會屏蔽掉docker run啓動容器後面帶的命令參數或者CMD裏的參數;

語法(2種):

  1. ENTRYPOINT ["executable", "param1","param2"]

    #exec form:推薦使用的格式

  2. ENTRYPOINT command param1 param2

    #shell form:會屏蔽掉docker run時後面加的命令參數與CMD裏的參數

7. CMD

指定製做出的image在啓動成容器時運行的默認命令或參數。

注意:

  1. 1個dockerfile只有1個CMD指令,若是使用多個CMD指令,只有最後1個指令生效;
  2. docker run命令若是指定容器運行參數,會把CMD裏的參數覆蓋;
  3. RUN指令是在構建image時執行,將命令固化在image中;而CMD指令在構建image時並不執行,而是在容器啓動時執行(切記docker run指定的容器參數會覆蓋CMD指令)。
  4. 若是CMD提供的是默認參數,執行命令須要提早在ENTRYPORINT中指定。

語法(3種):

  1. CMD ["executable","param1","param2"]

    #exec form:推薦使用的格式,可執行文件+參數

  2. CMD ["param1","param2"]

    #傳遞到ENTRYPOINT,做爲ENTRYPOINT的參數

  3. CMD command param1 param2

    #shell form:做爲"/bin/sh –c"的參數

8. EXPOSE

指定容器運行時須要監聽的端口,用在多容器之間通訊使用。

語法:EXPOSE <port> 

9. ENV

設置環境變量,增長運行程序的靈活性,使用鍵值對格式。

若是須要更改鏡像生成容器時改變環境變量,可在運行"docker run"是帶"-env <key>=<value>"參數修改既定環境變量。

語法:ENV <key> <value> 

10. ONBUILD

指令用來設置一些觸發的指令,用於在當該鏡像被做爲基礎鏡像來建立其餘鏡像時執行一些操做,ONBUILD中定義的指令會在用於生成其餘鏡像的Dockerfile文件的FROM指令以後被執行,能夠用來執行一些由於環境而變化的操做,使鏡像更加通用,dockerfile全部指令均可以用於ONBUILD指令

注意:

  1. ONBUILD定義的指令在生成當前image的"docker build"中不會執行;
  2. 經過查看docker inspect <image>命令執行結果的OnBuild鍵來查看某個鏡像ONBUILD指令定義的內容;
  3. ONBUILD中定義的指令會當作引用該鏡像的Dockerfile文件的FROM指令的一部分來執行,執行順序會按ONBUILD定義的前後順序執行,若是ONBUILD中定義的任何一個指令運行失敗,則會使FROM指令中斷並致使整個build失敗,當全部的ONBUILD中定義的指令成功完成後,會按正常順序繼續執行build;
  4. ONBUILD中定義的指令不會繼承到當前引用的鏡像中,即當引用ONBUILD的鏡像建立完成後將會清除全部引用的ONBUILD指令;
  5. ONBUILD指令不容許嵌套;
  6. ONBUILD指令不會執行其定義的FROM或MAINTAINER指令。

11. USER

鏡像正在運行時或接下來的RUN指令設定用戶名或UID。

語法:USER <uid> 

12. WORKDIR

指定RUN、CMD與ENTRYPOINT命令的工做目錄,默認爲"/"目錄。

可在dockerfile中屢次出現,若是使用相對路徑,後一次的相對路徑是上一次WORKDIR的值。

語法:WORKDIR /path/to/workdir 

13. VOLUME

指定掛載點,能夠用來讓其餘容器掛載以實現數據共享或對容器數據的備份、恢復或遷移。

語法:VOLUME ["path"] 

三.Dockerfile示例

1. Dockerfile

#使用Dockerfile構建1個可ssh的image
[root@localhost ~]# touch Dockerfile

#注意"Dockerfile"首字母大寫;
#此示例將RUN須要執行的指令合併爲1條指令,可減小image層數;
#yum安裝程序是按字母順序排列的(非強制要求)
[root@localhost ~]# vim Dockerfile

# Get a base image.
FROM centos:latest

# Author
MAINTAINER Netonline "xxxxx@gmail.com"

# Install some CLI tools.
RUN yum install -y \
net-tools \
openssh-clients \
openssh-server && \
sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config && \

# Modify root password.
echo "root:123456" | chpasswd && \

# Generate keys for sshd.
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

# Open sshd port and execute service.
EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]

2. 構建image

#"docker build"執行時使用同目錄的"Dockerfile"文件;另外"centos:ssh"爲構建的image名,注意命令最後帶的"."
[root@localhost ~]# docker build -t centos:ssh . 

 

3. 驗證

[root@localhost ~]# docker images

相關文章
相關標籤/搜索