Dockerfile是一個文本格式的配置文件,用戶可使用Dockerfile來快速建立自定義的鏡像。python
Dockerfile典型的基本結構和它支持的衆多指令,並具體講解經過這些指令來編寫定製鏡像的Dockerfile,以及如何生成鏡像。nginx
最後介紹使用Dockerfile的一些最佳實踐經驗。git
Dockerfile由一行行命令語句組成,而且支持以#開頭的註釋行。docker
通常而言,Dockerfile分爲四部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時執行指令。shell
例如:數據庫
# This Dockerfile uses the ubuntu imageubuntu
# VERSION 2 - EDITION 1數組
# Author: docker_user緩存
# Command format: Instruction [arguments / command] ..ruby
# Base image to use, this must be set as the first line
FROM ubuntu
# Maintainer: docker_user <docker_user at="" email.com="">(@docker_user)
MAINTAINER docker_user docker_user@email.com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx
其中,一開始必須指明所基於的鏡像名稱,接下來通常是說明維護者信息。後面則是鏡像操做指令,例如RUN指令,RUN指令將對鏡像執行跟隨的命令。每運行一條RUN指令,鏡像就添加新的一層,並提交。最後是CMD指令,用來指定運行容器時的操做命令。
下面是Docker Hub上兩個熱門鏡像的Dockerfile的例子,能夠幫助對Dockerfile結構有個基本的認識。
第一個例子是在debian:jessie基礎鏡像基礎上安裝Nginx環境,從而建立一個新的nginx鏡像:
FROM debian:jessie
MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"
ENV NGINX_VERSION 1.10.1-1
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \ && echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/ apt/sources.list \ && apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ ca-certificates \ nginx=${NGINX_VERSION} \ nginx-module-xslt \ nginx-module-geoip \ nginx-module-image-filter \ nginx-module-perl \ nginx-module-njs \ gettext-base \ && rm -rf /var/lib/apt/lists/* # forward request and error logs to docker log collector RUN ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
指令的通常格式爲INSTRUCTION arguments,指令包括FROM、MAINTAINER、RUN等,參見表8-1。
1.FROM
指定所建立鏡像的基礎鏡像,若是本地不存在,則默認會去Docker Hub下載指定鏡像。
格式爲FROM,或FROM
:,或FROM
@。
任何Dockerfile中的第一條指令必須爲FROM指令。而且若是在同一個Dockerfile中建立多個鏡像,可使用多個FROM指令(每一個鏡像一次)。
2.MAINTAINER
指定維護者信息,格式爲MAINTAINER。例如:
MAINTAINER image_creator@docker.com
該信息會寫入生成鏡像的Author屬性域中。
3.RUN
運行指定命令。格式爲RUN或RUN["executable","param1","param2"]。
注意,後一個指令會被解析爲Json數組,所以必須用雙引號。前者默認將在shell終端中運行命令,即/bin/sh-c;後者則使用exec執行,不會啓動shell環境。
指定使用其餘終端類型能夠經過第二種方式實現,例如RUN["/bin/bash","-c","echo hello"]。
每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可使用\來換行。例如:
4.CMD
CMD指令用來指定啓動容器時默認執行的命令。它支持三種格式:
每一個Dockerfile只能有一條CMD命令。若是指定了多條命令,只有最後一條會被執行。
若是用戶啓動容器時手動指定了運行的命令(做爲run的參數),則會覆蓋掉CMD指定的命令。
5.LABEL
LABEL指令用來指定生成鏡像的元數據標籤信息。格式爲LABEL = = =...。
例如:
LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."
6.EXPOSE
聲明鏡像內服務所監聽的端口。
格式爲EXPOSE[...]。
例如:EXPOSE 22 80 8443
注意,該指令只是起到聲明做用,並不會自動完成端口映射。
在啓動容器時須要使用-P,Docker主機會自動分配一個宿主機的臨時端口轉發到指定的端口;使用-p,則能夠具體指定哪一個宿主機的本地端口會映射過來。
7.ENV
指定環境變量,在鏡像生成過程當中會被後續RUN指令使用,在鏡像啓動的容器中也會存在。
格式爲ENV或ENV=...。
指令指定的環境變量在運行時能夠被覆蓋掉,如docker run --env=built_image。
8.ADD
該命令將複製指定的路徑下的內容到容器中的路徑下。格式爲ADD。
其中能夠是Dockerfile所在目錄的一個相對路徑(文件或目錄),也能夠是一個URL,還能夠是一個tar文件(若是爲tar文件,會自動解壓到路徑下)。能夠是鏡像內的絕對路徑,或者相對於工做目錄(WORKDIR)的相對路徑。路徑支持正則格式,例如:ADD *.c /code/
9.COPY
複製本地主機的(爲Dockerfile所在目錄的相對路徑、文件或目錄)下的內容到鏡像中的下。目標路徑不存在時,會自動建立。格式爲COPY。
路徑一樣支持正則格式。當使用本地目錄爲源目錄時,推薦使用COPY。
10.ENTRYPOINT
指定鏡像的默認入口命令,該入口命令會在啓動容器時做爲根命令執行,全部傳入值做爲該命令的參數。
支持兩種格式:
ENTRYPOINT ["executable", "param1", "param2"] ( exec 調用執行); ENTRYPOINT command param1 param2 ( shell 中執行);
此時,CMD指令指定值將做爲根命令的參數。
每一個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最後一個有效。
在運行時,能夠被--entrypoint參數覆蓋掉,如docker run--entrypoint。
11.VOLUME
建立一個數據卷掛載點。格式爲VOLUME["/data"]。
能夠從本地主機或其餘容器掛載數據卷,通常用來存放數據庫和須要保存的數據等。
12.USER
指定運行容器時的用戶名或UID,後續的RUN等指令也會使用指定的用戶身份。格式爲USER daemon。
當服務不須要管理員權限時,能夠經過該命令指定運行用戶,而且能夠在以前建立所須要的用戶。
例如:RUN groupadd -r postgres && useradd -r -g postgres postgres
要臨時獲取管理員權限可使用gosu或sudo。
13.WORKDIR
爲後續的RUN、CMD和ENTRYPOINT指令配置工做目錄。格式爲WORKDIR /path/to/workdir。
可使用多個WORKDIR指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路徑。
例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑爲/a/b/c。
14.ARG
指定一些鏡像內使用的參數(例如版本號信息等),這些參數在執行docker build命令時才以--build-arg=格式傳入。格式爲ARG[=]。
則能夠用docker build --build-arg=.來指定參數值。
15.ONBUILD
配置當所建立的鏡像做爲其餘鏡像的基礎鏡像時,所執行的建立操做指令。格式爲ONBUILD [INSTRUCTION]。
例如,Dockerfile使用以下的內容建立了鏡像image-A:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
若是基於image-A建立新的鏡像時,新的Dockerfile中使用FROM image-A指定基礎鏡像,會自動執行ONBUILD指令的內容,等價於在後面添加了兩條指令:
FROM image-A #Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的鏡像,推薦在標籤中註明,例如ruby:1.9-onbuild。
16.STOPSIGNAL
指定所建立鏡像啓動的容器接收退出的信號值。例如:STOPSIGNAL signal
17.HEALTHCHECK
配置所啓動容器如何進行健康檢查(如何判斷健康與否),自Docker 1.12開始支持。
格式有兩種:
HEALTHCHECK [OPTIONS] CMD command:根據所執行命令返回值是否爲0來判斷;
HEALTHCHECK NONE:禁止基礎鏡像中的健康檢查。
OPTION支持:
18.SHELL
指定其餘命令使用shell時的默認shell類型。默認值爲["/bin/sh","-c"]。
對於Windows系統,建議在Dockerfile開頭添加#escape=`來指定轉義信息。
編寫完成Dockerfile以後,能夠經過docker build命令來建立鏡像。
基本的格式爲docker build [選項] 內容路徑,該命令將讀取指定路徑下(包括子目錄)的Dockerfile,並將該路徑下的全部內容發送給Docker服務端,由服務端來建立鏡像。所以除非生成鏡像須要,不然通常建議放置Dockerfile的目錄爲空目錄。
有兩點經驗:
例如,指定Dockerfile所在路徑爲/tmp/docker_builder/,而且但願生成鏡像標籤爲build_repo/first_image,
使用下面的命令:$ docker build -t build_repo/first_image /tmp/docker_builder/
使用.dockerignore文件
能夠經過.dockerignore文件(每一行添加一條匹配模式)來讓Docker忽略匹配模式路徑下的目錄和文件。例如:
# comment 相似.gitignore */temp* */*/temp* tmp? ~*
所謂最佳實踐,其實是從需求出發,來定製適合本身、高效方便的鏡像。
首先,要儘可能吃透每一個指令的含義和執行效果,本身多編寫一些簡單的例子進行測試,弄清楚了再撰寫正式的Dockerfile。此外,Docker Hub官方倉庫中提供了大量的優秀鏡像和對應的Dockefile,能夠經過閱讀它們來學習如何撰寫高效的Dockerfile。
建議在生成鏡像過程當中,嘗試從以下角度進行思考,完善所生成的鏡像。