Docker開發實踐筆記二

鏡像是容器運行基礎,容器是鏡像運行後的形態,兩者緊密相連又有不一樣。html

一、鏡像的概念java

鏡像是一個包含程序運行必要依賴環境和代碼的只讀文件,它採用分層的文件系統,將每一次改變以讀寫層的形式增長到原來的只讀文件上。nginx

1.1鏡像與容器web

若是將容器理解爲一套程序運行的虛擬環境,那麼鏡像就是用來構建這個環境的模板。經過同一鏡像,咱們能夠構造出不少相互獨立但運行環境同樣的容器。redis

鏡像的最底層必須是一個稱爲啓動文件(bootfs)的鏡像,用戶不會與這一層直接打交道。bootfs的上層鏡像叫做根鏡像(rootfs),它在一般狀況下是一個操做系統,如Ubuntu、Debina和CentOS等。docker

(素材來源與網絡)shell

二、本地鏡像的管理ubuntu

2.1查看centos

docker images
docker images ub* //使用通配符

查看結果相似下表
REPOSITORY TAG IMAGE_ID CREATED VIRTUAL SIZE
centos laster 10009deww3 45 hours ago 199MB

REPOSITORY是倉庫名稱,通常用來存放同一類型的鏡像,其名稱由建立者指定。安全

命令規則:

一、[namespace\ubuntu]:由命名空間和實際的倉庫名組成,中間用」\「隔開,若是要提交到DOcker Hub 非官方的倉庫名必需要遵照此規則。

二、[ubuntu]:只有倉庫名,它屬於頂級命名空間,該空間只能用於官方的鏡像。本地也能夠這種命名,可是沒法分發到DOcker Hub上進行分享。

三、【dl.dockerpool.com:5000\ubuntu:12.04]:指定URL路徑的方式。通常是用於本身搭建的Hub或者第三方Hub上,dl.dockerpool.com:5000是第三方Hub的主機名及端口。

TAG用於區分同一倉庫中的不一樣鏡像。若是未指定,默認爲laster

IMAGE_ID每一個鏡像都有一個字符串類型、長爲64位的HashID,同容器ID同樣,用來惟一標識一個鏡像。通常取前面一部分只要在本機惟一標識一個鏡像便可,和Git的CommitID規則相似。

CREATED鏡像建立時間。

VIRTUAL SIZE鏡像所佔用的虛擬大小,該大小包含了全部共享文件的大小。

 

2.2下載

docker run命令運行一個鏡像時,首先會在本地查找鏡像,若是本地不存在會繼續去Docker Hub上面搜索符合條件的鏡像並將其下載下來運行。

docker pull ubuntu:13.10
13.10: Pulling from library/ubuntu //本地已經有了
6599cadaf950: Pull complete 
23eda618d451: Pull complete 
f0be3084efe9: Pull complete 
52de432f084b: Pull complete 
a3ed95caeb02: Pull complete 
Digest: sha256:15b79a6654811c8d992ebacdfbd5152fcf3d165e374e264076aa435214a947a3
Status: Downloaded newer image for ubuntu:13.10
docker search wordpress //Docker Hub搜索符合條件的鏡像

搜索結果會顯示
鏡像的名稱(NAME)、描述(DESCRIPTION)、
鏡像評分(STARS)(越高代表質量越好)、
是否爲官方鏡像(OFFICIAL)、是否使用了自動構建(AUTOMATED)

有時運行的鏡像本地沒有,會從Docker Hub上獲取,能夠經過docker pull 命令預先下載到本地,再使用docker run命令。

docker pull ubuntu

2.3刪除

刪除的鏡像若是被容器所依賴,即使容器已中止了,也仍然須要依賴鏡像,這裏不能直接刪除,若是必定要強制刪除可使用-f參數。可是爲了安全起見建議先中止容器,刪除容器後再刪除鏡像。

docker rmi 鏡像ID或名稱 //比刪除容器命令多了一個i 
docker rmi -f  鏡像ID或名稱 //強制刪除鏡像

 

三、建立本地鏡像

建立本地鏡像有三種方式:

一、經過鏡像導出成tar文件的方式,而後導入鏡像建立一個新鏡像。(這種方式在 Docker開發實踐筆記一 容器的導入和導出已說明)

二、使用commit命令保存對基礎鏡像的修改建立出新的鏡像

運行鏡像容器後,對容器進行修改,而後使用commit提交建立。

docker run -i -t ubuntu
修改容器,好比安裝軟件、修改配置等。

docker commit -m="Message" --author="LIU" 運行的容器ID myDOcker/redis:v1

若是須要對上面的鏡像再修改,進入容器內更新後再使用上面的命令提交一個新版本鏡像便可。

docker commit -m="Message" --author="LIU" 運行的容器ID myDOcker/redis:v2

三、使用Dockerfile文件建立鏡像(推薦方式)

Dockerfile用來建立一個自定義的image,包含了用戶指定的軟件依賴等。

下面是一個DOckerfile文件實例,本例只是介紹語法無任何實際意義。

#version: 1.00

#指定待擴展的父級鏡像。除註釋外文件開頭必須是一個FROM指令
FROM ubuntu:latest 

#做者信息
MAINtAINER jiuwu "jiuwu@qq.com" 

#設置root用戶爲後續命令的執行者
USET root 

#執行操做
RUN apt-age update
RUN apt-get install -y nginx

#使用&&拼接命令
RUN touch test.txt && echo "abc" >> abc.txt

#對外暴露端口
EXPOSE 80 8080 1038

#添加文件 第一個是源文件,第二個是要添到的容器中的目標路徑
ADD abc.txt /opt/

#添加文件件
ADD /webapp /opt/webapp

#添加網絡文件
ADD https://www.baidu.com/logo.jpg /opt/

#設置環境變量
ENV WEBAPP_PORT=9000

#設置工做目錄
WORKDIR /opt/

#設置啓動命令,只能出現一次,後面的會覆蓋前面的
ENTRYPOINT ["ls"]

#設置啓動參數,只能出現一次,後面的會覆蓋前面的
CMD ["-a","-l"]

#設置卷
VOLUME ["/data","/var/www"]

#設置子鏡像的觸發操做(當有鏡像以此鏡像爲父鏡像時,會執行下面的操做)
ONBUILD ADD ./app/src
ONBUILD RUN echo "on build excuted " >> onbuild.txt

下面是對上述指令的詳細說明:

指令不區分大小寫。可是,命名約定爲所有大寫。
全部Dockerfile都必須以FROM命令開始。 FROM命令會指定鏡像基於哪一個基礎鏡像建立,接下來的命令也會基於這個基礎鏡像(譯者注:CentOS和Ubuntu有些命令但是不同的)。FROM命令能夠屢次使用,表示會建立多個鏡像。具體語法以下:

FROM <image name>

1. MAINTAINER:設置該鏡像的做者。語法以下:

MAINTAINER <author name>

2. RUN:在shell或者exec的環境下執行的命令。RUN指令會在新建立的鏡像上添加新的層面,接下來提交的結果用在Dockerfile的下一條指令中。語法以下:

RUN 《command》
RUN apt-get update //這種形式使用/bin/sh環境中執行的命令
RUN ["apt-get","update"] //直接使用系統調用exec來執行

多個命令能夠用&&鏈接執行
RUN apt-get update && apt-get install nginx

這裏須要注意一下,由於一次RUN會增長一個新層,全部最佳實踐是減小RUN次數,儘可能將多個操做合併到RUN中一次執行。

3. ADD:複製文件指令。它有兩個參數<source>和<destination>。destination是容器內的路徑。source能夠是URL或者是啓動配置上下文中的一個文件。語法以下:

ADD 《src》 《destination》

若是源文件是主機上的zip或tar形式的壓縮文件,Docker會先解壓縮,而後將文件添加到鏡像指定的位置,若是是URL指定的網絡壓縮文件則不解壓。

4. CMD:提供了容器啓動時默認執行的命令。 Dockerfile只容許使用一次CMD指令。 使用多個CMD會抵消以前全部的指令,只有最後一個指令生效。 CMD有三種形式:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

5. EXPOSE:指定容器在運行時監聽的端口。語法以下:

EXPOSE <port>; //多個端口使用空格隔開

EXPOSE 80 8080 9000

運行容器時經過參數-P(大寫)便可將EXPOSE裏所指定的端口映射到主機上另外的隨機端口,其它容器或主機就能夠經過映射後的端口與此容器通訊。同時,咱們也能夠經過-p(小寫)參數將DOckerfile中EXPOSE中沒有列出的端口設置成公開的。

6. ENTRYPOINT:配置給容器一個可執行的命令,這意味着在每次使用鏡像建立容器時一個特定的應用程序能夠被設置爲默認程序。同時也意味着該鏡像每次被調用時僅能運行指定的應用。相似於CMDDocker只容許一個ENTRYPOINT,多個ENTRYPOINT會抵消以前全部的指令,只執行最後的ENTRYPOINT指令。語法以下:

ENTRYPOINT ["executable", "param1","param2"]
ENTRYPOINT command param1 param2

7. WORKDIR:指定RUNCMDENTRYPOINT命令的工做目錄。語法以下:

WORKDIR /path/to/workdir

8. ENV:設置環境變量。它們使用鍵值對,增長運行程序的靈活性。語法以下:

ENV <key> <value>

在運行容器的時候能夠經過-e參數來設置或修改環境變量:

docker run -e WEBAPP_PORT=8000 -e WEBAPP_HOST=www.test.com ....

9. USER:鏡像正在運行時設置一個UID。語法以下:

USER <uid> //好比:USER root

10. VOLUME:受權訪問從容器內到主機上的目錄。語法以下:

VOLUME ["/data"]

此掛載通常是在運行容器的時候指定,由於要關聯到宿主機上,這樣分享Dockerfile就不方便了。多個容器能夠經過同一個掛載點共享數據,即使其中一個容器已經中止,掛載點也仍然能夠訪問,只有當掛載點的容器引用所有消失時,掛載點纔會自動刪除。

11. ONBUILD: 指定的命令在構建鏡像時並不執行,而是在它的子鏡像中執行。

ONBUILD中的命令會在當前鏡像的子鏡像構建時執行。能夠把ONBUILD命令當成父鏡像的Dockerfile傳遞給子鏡像的Dockerfile的指令。

在子鏡像的構建過程當中,Docker 會在執行Dockerfile中的任何指令以前,先執行父鏡像經過ONBUILD傳遞的指令。

當從給定鏡像構建新鏡像時,ONBUILD指令頗有用。例如,你可能會在一個語言棧鏡像中使用ONBUILD,語言棧鏡像用於在Dockerfile中構建用戶使用相應語言編寫的任意軟件,正如 Ruby 的ONBUILD變體

使用ONBUILD構建的鏡像應用一個單獨的標籤,例如:ruby:1.9-onbuild或ruby:2.0-onbuild。

在ONBUILD中使用ADD或COPY時要格外當心。若是新的構建上下文中缺乏對應的資源,「onbuild」鏡像會災難性地失敗。添加一個單獨的標籤,容許Dockerfile的做者作出選擇,將有助於緩解這種狀況。

 

最後再重點說明一下CMD和ENTRYPOINT命令:

兩個命令都是用來指定容器啓動時默認運行的命令。

假如,咱們指定的ENTRYPOINT是這樣的:

ENTRYPOINT ["ls","-l"]

並構建出名爲 jiuwu/newImage的鏡像,那麼 docker run jiuwu/newImage的運行結果與docker run ubuntu ls -l是同樣,而docker run jiuwu/newImage -a 的運行結果與docker run ubuntu ls -l -a 同樣。

否則發現,ENTRYPOINT與CMD的區別在於運行容器時添加在鏡像名以後的參數,對ENTRYPOINT 是拼接,而對CMD則是覆蓋。咱們能夠在運行容器的時候使用--entrypoint來覆蓋Dockerfile中的指定:

docker run --entrypoint echo jiuwu/newImage "hello docker"

輸出爲:hello docker

一般狀況下風們會將ENTRYPOINT 和CMD搭配起來使用。ENTRYPOINT 用於指定須要運行的命令,CMD用於指定運行命令所須要的參數(這是個知識點,記住)。示例以下:

ENTRYPOINT  ["ls"]
CMD ["-a","-l"]

 

Dockerfile 最佳實踐

相關文章
相關標籤/搜索