Dockerfile的結構分紅了若干部分,每一個部分之間的前後順序有明確的要求:java
部分 | 命令 |
---|---|
基礎鏡像信息 | FROM |
維護者信息 | MAINTAINER |
鏡像操做指令 | RUN 、COPY 、ADD 、EXPOSE 、WORKDIR 、ONBUILD 、USER 、VOLUME 等 |
啓動時命令 | CMD , ENTRYPOINT |
以攜程Apollo開源項目的Dockerfile爲例:nginx
# Dockerfile for apollo-adminservice # 1. Copy apollo-adminservice-${VERSION}-github.zip to current directory # 2. Build with: docker build -t apollo-adminservice . # 3. Run with: docker run -p 8090:8090 -d -v /tmp/logs:/opt/logs --name apollo-adminservice apollo-adminservice FROM openjdk:8-jre-alpine MAINTAINER ameizi <sxyx2008@163.com> ENV VERSION 1.5.0-SNAPSHOT ENV SERVER_PORT 8090 # DataSource Info ENV DS_URL "" ENV DS_USERNAME "" ENV DS_PASSWORD "" RUN echo "http://mirrors.aliyun.com/alpine/v3.8/main" > /etc/apk/repositories \ && echo "http://mirrors.aliyun.com/alpine/v3.8/community" >> /etc/apk/repositories \ && apk update upgrade \ && apk add --no-cache procps unzip curl bash tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone ADD apollo-adminservice-${VERSION}-github.zip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip RUN unzip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip -d /apollo-adminservice \ && rm -rf /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip \ && sed -i '$d' /apollo-adminservice/scripts/startup.sh \ && chmod +x /apollo-adminservice/scripts/startup.sh \ && echo "tail -f /dev/null" >> /apollo-adminservice/scripts/startup.sh EXPOSE $SERVER_PORT CMD ["/apollo-adminservice/scripts/startup.sh"]
Dockerfile中使用#
進行行註釋。git
格式:github
ADD <src> <dest>
從src
複製文件到容器中的dest
。web
注意:docker
src
能夠是文件、目錄、URL或壓縮包,可是必須在構建上下文也就是Dockerfile所在的目錄中dest
以/
結尾,則認爲src
是一個目錄;dest
不以/
結尾,則認爲src
是一個文件。src
是可識別的壓縮包格式(gzip, bzip2, xz),則Docker會自動解壓到容器的指定dest
,dest
中重名的文件不會被覆蓋。dest
不存在,則會自動建立dest
(含路徑中的任何目錄),新建立的文件和目錄的模式爲755
,UIG和GID都是0。ARG
設置構建時的環境變量,這些指定的參數在容器運行時再也不有用。ubuntu
示例數組
ARG build # 聲明一個構建參數,但沒有賦缺省值 ARG webapp_user=wasuser # 聲明一個構建參數並指定缺省值
在docker build
命令構建鏡像時,經過--build-arg
指定構建參數的值,例如:bash
docker build --build-arg build=12345 -t darren/test_image .
此時構建Dockerfile中使用到的build
的實際值是12345
,而webapp_user
的實際值是其缺省值。app
CMD
指定容器啓動時執行的一條命令。
不一樣於RUN
命令,RUN
指令指定鏡像被構建時要執行的命令,CMD
指定容器啓動時要執行的命令。
每一個Dockerfile只有一個CMD
命令,若是指定了多條CMD
命令,則只有最後一條會被執行。
啓動容器時若是經過命令行指定了運行的命令,將會覆蓋Dockerfile中指定的CMD
命令。
Docker推薦使用數組語法設置要執行的命令:
CMD ["/bin/bash", "-l"]
COPY
相似於ADD
:
格式:
COPY <src> <dest>
注意:
COPY
不支持URL和壓縮包。src
是一個目錄,則將其中的全部文件拷貝到dest
,而不含src
自己;dest
必須是一個絕對路徑與CMD
指令相似,一樣指定容器啓動時執行的命令。
docker run
命令中指定的任何參數都會被當作參數再次傳遞給ENTRYPOINT
指定的命令。
格式:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command arg1 arg2
示例:
在Dockerfile中:
ENTRYPOIINT ["/usr/sbin/nginx"]
在docker run
命令中:
docker run -t -i darren/test_image -g "daemon off;"
其中的參數-g "daemon off;"
會傳遞給ENTRYPOINT
指定的命令,接在ENTRYPOINT
以後,所以,最終實際在啓動容器時執行的至關於ENTRYPOINT
指令:
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
其含義是前臺進程的形式運行Nginx守護進程。
當ENTRYPOINT
和CMD
同時使用時,全部命令行中指定的參數會傳遞給ENTRYPOINT
指令,覆蓋CMD
指定的參數;當命令行沒有額外指定參數時,則ENTRYPOINT
以CMD
指定的參數做爲默認的輸入。
示例:
ENTRYPOINT ["/usr/sbin/nginx"] CMD ["-h"]
此時能夠在docker run
命令中顯示指定參數從而修改ENTRYPOINT
指令的參數,或者使用CMD
傳給ENTRYPOINT
指令的參數,至關於/usr/sbin/nginx -h
,即顯示Nginx的幫助。
ENV
設置環境變量,設置的環境變量在容器運行時能夠在容器內獲取和使用,後續的RUN
指令等可使用ENV
指令設置的環境變量。
示例:
ENV RVM_PATH=/home/rvm RVM_ARCHFLAGS="-arch amd64"
ENV JAVA_HOME /path/to/java WORKDIR $JAVA_HOME
ENV
指令指定的環境變量會保存到構建的全部容器中,例如Linux容器中經過env
命令來查看容器運行時的環境變量。
docker run
命令中經過-e
選項傳遞的環境變量只對該命令啓動的容器當次運行生效。
聲明容器對外暴露的端口號:
EXPOSE <port1> EXPOSE <port1> <port2> <port3>
運行時容器真實暴露的端口以命令行中的設定爲準,若是在啓動一個容器時但願使用其Dockerfile中聲明的端口,則使用-P
選項:
docker run -P your-docker-image
FROM
指定構建使用的基礎鏡像,FROM
命令必須寫在其餘的指令前。
格式:
FROM <image> FROM <image>:<tag> FROM <image>@<digest>
LABEL
指令添加的元數據須要以鍵值對的形式指定。
示例:
LABEL version="1.0.0" LABEL description="This description illustrates \ that label-values can span multi lines." LABEL key1="v1" k2="v2" k3="v3"
注意:
LABEL
指令的值中,\
能夠用來換行。LABEL
中執行docker inspect
命令來查看鏡像的標籤用於爲Dockerfile署名。
示例:
MAINTAINER darren<darren@darren_s.com>
RUN
不一樣於CMD
指令,RUN
能夠在Dockerfile中出現和執行屢次。
在Shell終端中執行命令,Linux中默認是/bin/sh -c
,Windows中是cmd /s /c
。
格式:
RUN <command> RUN ["executable", "arg1", "arg2", ..., "argN"]
示例:
RUN ["/bin/sh", "-c", "echo Hello Wolrd!"]
指定啓動時的用戶,後續的指令都將以該用戶執行命令。
示例:
USER wasuser
使用USER
指令的各類方式
USER user USER user:group USER uid USER uid:gid USER user:gid USER uid:group
如不經過USER
指令指定用戶,默認的用戶爲root
。
能夠在docker run
命令中經過-u
選項覆蓋該指令的值。
向容器添加捲,一個卷是能夠存在於一個或多個容器內的特定目錄。
使容器內的一個目錄具備持久化存儲的功能,被指定的目錄既能夠被容器自己使用,也能夠共享給其餘容器。
示例:
VOLUME /mnt/data
該指令爲每一個基於該鏡像建立的容器建立一個名爲/mnt/data
的掛載點。也能夠指定多個卷:
VOLUME ["/mnt/project1", "/mnt/project2"]
從鏡像建立容器時,在容器內設置一個工做目錄。
至關於Linux中的cd
命令,用於切換到指定的工做目錄,後續的指令都將在指定的工做目錄下執行。
WORKDIR
指令能夠屢次出現,在不一樣的工做目錄之間進行切換:
WORKDIR /opt/webapp/db RUN bundle install WORKDIR /opt/webapp RUN [ "rackup" ]
啓動容器時可使用-w
選項覆蓋工做目錄:
docker run -it -w /var/log ubuntu pwd
會將容器內的工做目錄設置爲/var/log
。
爲鏡像添加觸發器,當鏡像A被做爲鏡像B的基礎鏡像,在構建鏡像B時,會執行鏡像A的ONBUILD
指令。
注意:
ONBUILD
指令按照其在鏡像A中聲明的順序依次執行ONBUILD
指令只能被繼承一次,即若是鏡像C再以鏡像B做爲基礎鏡像,構建鏡像C時不會觸發鏡像A的ONBUILD
指令。ONBUILD
指令在鏡像B的FROM
指令後當即執行。FROM
、MAINTAINER
、ONBUILD
指令是不能出如今ONBUILD
指令中的。示例
鏡像A中:
ONBUILD ADD . /var/www
鏡像B
FROM 鏡像A
則會在構建鏡像B的Step 0 : FROM
階段就執行鏡像A的ONBUILD
指令,即將構建上下文中的全部內容添加到/var/www
目錄