指定基礎鏡像,而且必須是第一條指令。若是不以任何鏡像爲基礎,那麼寫法爲:FROM scratch。同時意味着接下來所寫的指令將做爲鏡像的第一層開始,語法:python
FROM <image> FROM <image>:<tag> FROM <image>:<digest>
三種寫法,其中<tag>和<digest> 是可選項,若是沒有選擇,那麼默認值爲latest,爲了安全,儘可能使用官方image做爲base imagemysql
例:linux
FROM scratch #製做base image FROM centos #以centos做爲base image
爲鏡像指定標籤,語法:sql
LABEL <key>=<value> <key>=<value> <key>=<value> ...
一個Dockerfile種能夠有多個LABEL,以下:docker
LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
可是並不建議這樣寫,最好就寫成一行,如太長鬚要換行的話則使用\符號shell
以下:vim
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
說明:LABEL會繼承基礎鏡像種的LABEL,如遇到key相同,則值覆蓋windows
例:centos
LABEL maintainer="asd@163.com" #維護者信息 LABEL version="1.0" #版本 LABEL description="這是描述" #鏡像描述信息
功能爲運行指定的命令,每運行一次RUN對image而言都生成新的一層,RUN命令有兩種格式安全
1. RUN <command> 2. RUN ["executable", "param1", "param2"]
第一種後邊直接跟shell命令
在linux操做系統上默認 /bin/sh -c
在windows操做系統上默認 cmd /S /C
第二種是相似於函數調用。可將executable理解成爲可執行文件,後面就是兩個參數。
兩種寫法比對:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
RUN ["/bin/bash", "-c", "echo hello"]
注意:多行命令不要寫多個RUN,緣由是Dockerfile中每個指令都會創建一層.多少個RUN就構建了多少層鏡像,會形成鏡像的臃腫、多層,不只僅增長了構件部署的時間,還容易出錯。
當命令較多,或較長時,建議將命令換行,RUN書寫時的換行符是 \
例:
RUN yum update && yum install -y vim \ python-dev
RUN apt-get update && apt-get install -y perl \ pwgen --no-install-recommends && rm -rf \ /var/lib/apt/list/*
設置工做目錄,對RUN,CMD,ENTRYPOINT,COPY,ADD生效。至關於 cd,若是不存在要打開的目錄則會建立,能夠設置屢次。語法:
WORKDIR /path/to/workdir
例:
WORKDIR /ROOT #將工做目錄切換到root下
WORKDIR /test #將工做目錄切換到test目錄 沒有則建立 WORKDIR demo #結合上一句 此時工做目錄被切換到/test/demo目錄下
儘可能使用WORKDIR,而不使用RUN cd,儘可能使用局對目錄。
一個複製命令,把文件複製到鏡像中。若是把宿主機與容器想象成兩臺linux服務器的話,那麼這個命令就相似於scp,只是scp須要加用戶名和密碼的權限驗證,而ADD不用。語法以下:
1. ADD <src>... <dest> 2. ADD ["<src>",... "<dest>"]
<dest>路徑的填寫能夠是容器內的絕對路徑,也能夠是相對於工做目錄的相對路徑
<src>能夠是一個本地文件或者是一個本地壓縮文件,還能夠是一個url,若是把<src>寫成一個url,那麼ADD就相似於wget命令,ADD不只能夠添加一個文件到指定目錄,並且還能夠將添加的壓縮文件解壓縮,
如如下寫法都是能夠的:
ADD test relativeDir/ #將test複製到容器內,相對於當前工做目錄下的relativeDir目錄中
ADD test /relativeDir #將test複製到容器內根目錄下relativeDir目錄中
ADD http://example.com/foobar / #將網絡文件下載到根目錄下
儘可能不要把<scr>寫成一個文件夾,若是<src>是一個文件夾了,將複製整個目錄的內容,包括文件系統元數據
有以下注意事項:
一、若是源路徑是個文件,且目標路徑是以 / 結尾, 則docker會把目標路徑看成一個目錄,會把源文件拷貝到該目錄下。若是目標路徑不存在,則會自動建立目標路徑。
二、若是源路徑是個文件,且目標路徑是否是以 / 結尾,則docker會把目標路徑看成一個文件。若是目標路徑不存在,會以目標路徑爲名建立一個文件,內容同源文件;若是目標文件是個存在的文件,會用源文件覆蓋它,固然只是內容覆蓋,文件名仍是目標文件名。若是目標文件實際是個存在的目錄,則會源文件拷貝到該目錄下。 注意,這種狀況下,最好顯示的以 / 結尾,以免混淆。
三、若是源路徑是個目錄,且目標路徑不存在,則docker會自動以目標路徑建立一個目錄,把源路徑目錄下的文件拷貝進來。若是目標路徑是個已經存在的目錄,則docker會把源路徑目錄下的文件拷貝到該目錄下。
四、若是源文件是個歸檔文件(壓縮文件),則docker會自動幫解壓。
看這個名字就知道,又是一個複製命令,與ADD用法基本相同,COPY的<src>只能是本地文件,語法以下:
1. COPY <src>... <dest> 2. COPY ["<src>",... "<dest>"]
例:
ADD hello / #將hello文件複製到容器內根目錄下 ADD test.tar.gz / #將壓縮文件添加到容器內根目錄下並解壓
WORKDIR /root #將工做目錄切換到root目錄下 ADD hello test/ #將hello文件添加到/root/test目錄下
WORKDIR /root #將工做目錄切換到root目錄下 copy hello test/ #將hello文件複製到/root/test
功能爲設置環境變量設置常量,語法有兩種:
1. ENV <key> <value> 2. ENV <key>=<value> ...
二者的區別就是第一種是一次設置一個,第二種是一次設置多個。
例:
ENV MYSQL_VERSION 5.6 #設置常量 RUN apt-get install -y mysql-server="${MYSQL_VERSION}" \ #使用常量 && rm -rf /var/lib/apt/list/*
功能爲容器啓動時要運行的命令,語法有三種寫法
1. CMD ["executable","param1","param2"] 2. CMD ["param1","param2"] 3. CMD command param1 param2
第三種比較好理解了,就時shell這種執行方式和寫法,第一種和第二種其實都是可執行文件加上參數的形式,舉例說明兩種寫法:
CMD [ "sh", "-c", "echo $HOME"
CMD [ "echo", "$HOME" ]
補充細節:這裏邊包括參數的必定要用雙引號,就是",不能是單引號。千萬不能寫成單引號,緣由是參數傳遞後,docker解析的是一個JSON array
注意事項:
不要把RUN和CMD搞混了。RUN是構件容器時就運行的命令以及提交運行結果,CMD是容器啓動時執行的命令,在構件時並不運行,構件時牢牢指定了這個命令究竟是個什麼樣子
功能是啓動時的默認命令,語法以下:
1. ENTRYPOINT ["executable", "param1", "param2"] 2. ENTRYPOINT command param1 param2
與CMD比較說明(這倆命令太像了,並且還能夠配合使用):
1. 相同點:
只能寫一條,若是寫了多條,那麼只有最後一條生效
容器啓動時才運行,運行時機相同
2. 不一樣點:
ENTRYPOINT不會被運行的command覆蓋,而CMD則會被覆蓋
若是咱們在Dockerfile種同時寫了ENTRYPOINT和CMD,而且CMD指令不是一個完整的可執行命令,那麼CMD指定的內容將會做爲ENTRYPOINT的參數
RUN apt-get install -y vim CMD echo "hello docker" ENTRYPOINT echo "hello docker"
RUN ["apt-get", "install", "-y", "vim"] CMD ["/bin/echo", "hello docker"] ENTRYPOINT ["/bin/echo", "hello docker"]
例:如下兩個dockerfile結果相同
FROM centos #指定基礎鏡像爲centos EVN name Docker #設定常量name 值爲Docker ENTRYPOINT echo "hello $name" #執行acho命令
以上dockerfile生成的鏡像運行容器時輸出 hello Docker
FROM centos #指定基礎鏡像爲centos EVN name Docker #設定常量name 值爲Docker ENTRYPOINT ["/bin/echo", "hello $name"] #執行acho命令
以上dockerfile生成的鏡像運行容器時輸出 hello $name,由於 ENTRYPOINT ["/bin/echo", "hello $name"] 指定容器啓動時運行的就是echo命令 不會識別$爲變量,作以下修改:
FROM centos #指定基礎鏡像爲centos EVN name Docker #設定常量name 值爲Docker ENTRYPOINT ["/bin/bash", "-c", "echo", "hello $name"] #在shell中執行acho命令
容器啓動時輸出 hello Docker