Docker基礎-使用Dockerfile建立鏡像

一、基本結構

  Dockerfile由一行行命令語句組成,並支持以#開頭的註釋行。例如:python

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command ] ..

# Base image to use, this nust 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指令,用來指定運行容器時的操做命令。linux

  Docker Hub上兩個熱門Dockerfile:nginx

  1.在debian:jessie基礎鏡像上安裝nginx環境,從而建立一個新的nginx鏡像:golang

FROM debian:jessie

MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"

ENV NGINX_VERSION 1.10.1-1~jessie

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 && \
echo "deb http://nginx.org/package/debian/ jessie nginx" >> /etc/apt/source.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/err.log

EXPOSE 80 443

CMD ["nginx","-g","daemon off;"]

  2.基於buildpack-deps:jessie-scm基礎鏡像,安裝golang相關環境,製做一個GO語言的運行環境。正則表達式

FROM buildpack-deps:jessie-scm

# gcc fo cgo
RUN apt-get update && apt-get install -y --no-install-recommends g++ gcc libc6-dev make && rm -rf /var/lib/apt/lists*

ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && \
echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz

ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH

COPY go-wrapper /usr/local/bin

二、指令說明

  指令的通常格式爲INSTRUNCTION arguments,指令包括FROM、MAINTAINER、RUN等。具體指令及說明以下:docker

指令 說明
FROM 指定所建立鏡像的基礎鏡像
MAINTAINER 指定維護者信息
RUN 運行命令
CMD 指定啓動容器時默認執行的命令
LABEL 指定生成鏡像的元數據標籤信息
EXPOSE 聲明鏡像內服務所監聽的端口
ENV 指定環境變量
ADD 賦值指定的<src>路徑下的內容到容器中的<dest>路徑下,<src>能夠爲URL;若是爲tar文件,會自動解壓到<dest>路徑下
COPY 賦值本地主機的<scr>路徑下的內容到容器中的<dest>路徑下;通常狀況下推薦使用COPY而不是ADD
ENTRYPOINT 指定鏡像的默認入口
VOLUME 建立數據掛載點
USER 指定運行容器時的用戶名或UID
WORKDIR 配置工做目錄
ARG 指定鏡像內使用的參數(例如版本號信息等)
ONBUILD 配置當前所建立的鏡像做爲其餘鏡像的基礎鏡像時,所執行的建立操做的命令
STOPSIGNAL 容器退出的信號
HEALTHCHECK 如何進行健康檢查
SHELL 指定使用SHELL時的默認SHELL類型

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.FROM

  指定所建立的鏡像的基礎鏡像,若是本地不存在,則默認會去Docker Hub下載指定鏡像。
  格式爲:FROM<image>,或FROM<image>:<tag>,或FROM<image>@<digest>。
  任何Dockerfile中的第一條指令必須爲FROM指令。而且,若是在同一個Dockerfile文件中建立多個鏡像,可使用多個FROM指令(每一個鏡像一次)。shell

2.MAINTAINER

  指定維護者信息,格式爲MAINTAINER<name>。例如:數據庫

MAINTAINER image_creator@docker.com

  該信息將會寫入生成鏡像的Author屬性域中。json

3.RUN

  運行指定命令。
  格式爲:RUN<command>或RUN ["executable","param1","param2"]。
注意:
    後一個指令會被解析爲json數組,因此必須使用雙引號。
前者默認將在shell終端中運行命令,即/bin/sh -c;後者則使用exec執行,不會啓動shell環境。
指定使用其餘終端類型能夠經過第二種方式實現,例如:
    RUN ["/bin/bash","-c","echo hello"]
每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可使用\換行。例如:ubuntu

RUN apt-get update \
        && apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
        && rm -rf /var/cache/apt

4.CMD

  CMD指令用來指定啓動容器時默認執行的命令。它支持三種格式:

1.CMD ["executable","param1","param2"] 使用exec執行,是推薦使用的方式;
2.CMD param1 param2 在/bin/sh中執行,提供給須要交互的應用;
3.CMD ["param1","param2"] 提供給ENTRYPOINT的默認參數。

  每一個Dockerfile只能有一條CMD命令。若是指定了多條命令,只有最後一條會被執行。入股用戶啓動容器時指定了運行的命令(做爲run的參數),則會覆蓋掉CMD指定的命令。

5.LABEL

  LABEL指令用來生成用於生成鏡像的元數據的標籤信息。
  格式爲:LABEL <key>=<value> <key>=<value> <key>=<value> ...。
  例如:

LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."

6.EXPOSE

  聲明鏡像內服務所監聽的端口。
  格式爲:EXPOSE <port> [<port>...]
  例如:

EXPOSE 22 80 443 3306

注意:

  該命令只是起到聲明租用,並不會自動完成端口映射。
       在容器啓動時須要使用-P(大寫P),Docker主機會自動分配一個宿主機未被使用的臨時端口轉發到指定的端口;使用-p(小寫p),則能夠具體指定哪一個宿主機的本地端口映射過來。

7.ENV

  指定環境變量,在鏡像生成過程當中會被後續RUN指令使用,在鏡像啓動的容器中也會存在。
  格式爲:ENV <key><value>或ENV<key>=<value>...。
  例如:

ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz

ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"

  指令指定的環境變量在運行時能夠被覆蓋掉,如docker run --env <key>=<value> built_image。

8.ADD

  該指令將複製指定的<src>路徑下的內容到容器中的<dest>路徑下。
  格式爲:ADD<src> <dest>
  其中<src>可使Dockerfile所在目錄的一個相對路徑(文件或目錄),也能夠是一個URL,還能夠是一個tar文件(若是是tar文件,會自動解壓到<dest>路徑下)。<dest>可使鏡像內的絕對路徑,或者至關於工做目錄(WORKDIR)的相對路徑。路徑支持正則表達式,例如:

ADD *.c /code/

9.COPY

  複製本地主機的<src>(爲Dockerfile所在目錄的一個相對路徑、文件或目錄)下的內容到鏡像中的<dest>下。目標路徑不存在時,會自動建立。路徑一樣支持正則。
  格式爲:COPY <src> <dest>
  當使用本地目錄爲源目錄時,推薦使用COPY。

10.ENTRYPOINT

  指定鏡像的默認入口命令,該入口命令會在啓動容器時做爲根命令執行,全部傳入值做爲該命令的參數。
  支持兩種格式:

1.ENTRYPOINT ["executable","param1","param2"] (exec調用執行);
2.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 nginx && useradd -r -g nginx nginx

  要臨時獲取管理員權限能夠用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<varname>=<value>格式傳入。
  格式爲:ARG<name>[=<default value>]。
  則能夠用docker build --build-arg<name>=<value>來指定參數值。

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
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

  使用ONBUILD指令的鏡像,推薦在標籤中註明,例如:ruby:1.9-onbuild。

16.STOPSIGNAL

  指定所建立鏡像啓動的容器接收退出的信號值。例如:

STOPSIGNAL singnal

17.HEALTHCHECK

  配置所啓動容器如何進行健康檢查(如何判斷是否健康),自Docker 1.12開始支持。
  格式有兩種:

1.HEALTHCHECK [OPTIONS] CMD command    :根據所執行命令返回值是否爲0判斷;
2.HEALTHCHECK NONE              :禁止基礎鏡像中的健康檢查。

  [OPTION]支持:

1.--inerval=DURATION  (默認爲:30s):多久檢查一次;
2.--timeout=DURATION  (默認爲:30s):每次檢查等待結果的超時時間;
3.--retries=N        (默認爲:3):若是失敗了,重試幾回才最終肯定失敗。

18.SHELL

  指定其餘命令使用shell時的默認shell類型。
  格式爲: SHELL ["executable","parameters"]
  默認值爲 ["bin/sh","-c"]。
  注意:
    對於Windows系統,建議在Dockerfile開頭添加# escape=`來指定轉移信息。

 

三、建立鏡像

  編寫玩Dockerfile以後,能夠經過docker build命令來建立鏡像。
  基本的docker build [選項] 內容路徑,該命令將讀取指定路徑下(包括子目錄)的Dockerfile,並將該路徑下的全部內容發送給Docker服務端,由服務端來建立鏡像。所以除非生成鏡像須要,不然通常建議放置Dockerfile的目錄爲空目錄。

1.若是使用非內容路徑下的Dockerfile,能夠經過-f選項來指定其路徑;
2.要指定生成鏡像的標籤信息,可使用-t選項。

  例如:指定Dockerfile所在路徑爲 /tmp/docker_builder/,而且但願生成鏡像標籤爲build_repo/first_image,可使用下面的命令:

docker build -t build_repo/first_image /tmp/docker_builder

四、使用 .dockerignore文件

  能夠經過 .dockeringore文件(每一行添加一條匹配模式)來讓Docker忽略匹配模式路徑下的目錄和文件。例如:

# comment
    */tmp*
    */*/tmp*
    tmp?
    ~*

五、Dockerfile編寫小結

  從需求出發,定製適合本身需求、高效方便的鏡像,能夠參考他人優秀的Dockerfile文件,在構建中慢慢優化Dockerfile文件:

1.精簡鏡像用途:                 儘可能讓每一個鏡像的用途都比較集中、單一,避免構造大而複雜、多功能的鏡像;
2.選用合適的基礎鏡像:            過大的基礎鏡像會形成構建出臃腫的鏡像,通常推薦比較小巧的鏡像做爲基礎鏡像;
3.提供詳細的註釋和維護者信息:     Dockerfile也是一種代碼,須要考慮方便後續擴展和他人使用;
4.正確使用版本號:               使用明確的具體數字信息的版本號信息,而非latest,能夠避免沒法確認具體版本號,統一環境;
5.減小鏡像層數:                減小鏡像層數建議儘可能合併RUN指令,能夠將多條RUN指令的內容經過&&鏈接;
6.及時刪除臨時和緩存文件:        這樣能夠避免構造的鏡像過於臃腫,而且這些緩存文件並無實際用途;
7.提升生產速度:                合理使用緩存、減小目錄下的使用文件,使用.dockeringore文件等;
8.調整合理的指令順序:           在開啓緩存的狀況下,內容不變的指令儘可能放在前面,這樣能夠提升指令的複用性;
9.減小外部源的干擾:             若是確實要從外部引入數據,須要制定持久的地址,並帶有版本信息,讓他人能夠重複使用而不出錯。
相關文章
相關標籤/搜索