Docker學習筆記 - 第二篇:鏡像及DockerFile編寫

1.Docker鏡像

1.1 是什麼

鏡像是一種輕量級、可執行的獨立軟件包,它包含運行某個軟件所需的全部內容,包括代碼、運行時、庫、環境變量和配置文件。
Docker鏡像是由一系列文件系統疊加而成:java

  • 1:最底端是一個引導文件系統,也就是bootfs,當一個容器運行時,它將會裝載到內存中,而引導文件系統將會被卸載
  • 2:第二層是root文件系統,即rootfs,它位於引導文件系統之上,rootfs一般是一種或多種操做系統,如Ubuntu文件系統

(1)在linux引導過程當中,root文件系統起初會只讀裝載,當引導結束並完成了完整性檢查後,會被切換成讀寫模式
(2)在Docker裏面,root文件系統始終都是隻讀模式,而且利用聯合加載技術,在root文件系統層上加載更多的只讀文件系統
聯合加載:指的是一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含全部底層的文件和目錄
Docker將這樣的文件系統稱爲鏡像linux

1.2 關於Docker鏡像

  • 1:Docker的鏡像都是隻讀的
  • 2:鏡像是分層的,一個鏡像能夠放到另外一個鏡像頂端,下層的鏡像稱爲父鏡像,最底部的鏡像稱爲基礎鏡像。鏡像不能超過127層,以從總體上優化鏡像的大小。
  • 3:從一個鏡像啓動容器時,Docker會在該鏡像頂層加載一個讀寫文件系統,咱們在docker中運行的程序就是在這層執行的。
  • 4:當一個docker容器啓動的時候,讀寫層初始是空的,當文件系統發生變化時,這些變化都會應用到這一層。

好比:想要修改一個文件,這個文件會從下面的只讀層複製到該讀寫層,該文件的只讀版本仍然存在,可是被該文件在讀寫層中的可讀寫副本所隱藏。
這種機制也就是寫時複製,這是Docker如此強大的技術之一。nginx

  • 5: Docker鏡像的表示格式:
    Image Hub/namespace/image name :tag
    Image Hub:存放image的倉庫地址,若是沒有這個部分,表示缺省docker官方hub
    Namespace:命名空間,是一個用戶或組織中全部鏡像命名的集合
    image name:鏡像的名稱
    tag:區分同一鏡像的不一樣版本,不寫標籤默認就是latest
    layer:鏡像由一系列層組成,每層都用64位的十六進制數表示web

    Image ID:鏡像最上層的layer ID就是該鏡像的ID
  • 6:本地存放:

本地鏡像和容器都保存在docker宿主機的/var/lib/docker目錄下,保存在docker 所採用的存儲驅動裏面,多是aufs或者devicemapper。
(1) aufs的全稱是advanced multi-layered unification filesystem,主要功能是把多個文件夾的內容合併到一塊兒,提供一個統一的視圖,使用的操做系統如Ubuntu、Debian等
(2) Device Mapper是Linux系統中基於內核的高級卷管理技術框架,而devicemapper是Docker基於Device Mapper提供的一種存儲驅動,使用的操做系統如RHEL、Centos等
Docker鏡像操做補充docker

docker commit:提交容器副本,如:
docker commit -m=「提交的描述信息」  -a=「指定鏡像做者」  容器ID  要建立的目標鏡像名
docker build:根據Dockerfile來建立一個新的鏡像,如:
docker build -t 要建立的鏡像名稱 .  ,最後一個點表示Dockerfile 文件所在目錄,能夠指定Dockerfile 的絕對路徑
docker tag:爲鏡像添加一個新的標籤,如:
    docker tag 源鏡像 新鏡像名

2 Dockerfile

2.1 是什麼

Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。數據庫

2.2 基礎知識

  • 1:每條指令都必須爲大寫字母,且後面要跟隨至少一個參數
  • 2:指令按照從上到下,順序執行apache

    • 3:#表示註釋
    • 4:每條指令都會建立一個新的鏡像層,並對鏡像進行提交
  • 5:Docker執行Dockerfile的大體流程

(1)docker從基礎鏡像運行一個容器
(2)執行一條指令,對容器做出修改
(3)執行相似docker commit的操做,提交一個新的鏡像層
(4)docker再基於剛提交的鏡像運行一個新容器
(5)執行dockerfile中的下一條指令,直到全部指令都執行完成ubuntu

  • 6:Docker會將構建鏡像的過程緩存起來,若是不須要緩存,能夠在docker build的時候指定--no-cache

2.3 Dockerfile基本指令

2.3.1 FROM

指定一個已經存在的鏡像,也是構建的基礎鏡像,Dockerfile的第一條必須是FROMcentos

2.3.2 MAINTAINER

設置做者,聯繫郵件數組

2.3.3 RUN

指定要運行的命令,建議使用數組的格式,也是exec的格式,如:

RUN[「apt-get」,」install」,」-y」,」nginx」]

2.3.4 EXPOSE

向容器外部公開容器內的端口

2.3.5 WORKDIR

指定在建立容器的時候,在容器內部設置一個工做目錄,entroypoint和CMD指定的程序會在這個目錄執行

能夠在docker run中使用-w來覆蓋工做目錄

2.3.6 USER

指定該鏡像以什麼樣的用戶去執行,能夠單獨指定用戶,也能夠指定用戶和組,格式:USER uid:gid,能夠在docker run中經過-u來覆蓋,若是都不指定,默認是root

2.3.7 CMD

指定一個容器啓動時要運行的命令,若是指定了多條CMD,只有最後一條會執行

例如:CMD[「/bin/bash」,」-l」]
若是在docker run 後面跟上要執行的命令,會覆蓋Dockerfile裏面的cmd指定的命令

2.3.8 ENTROYPOINT

也用來指定一個容器啓動時要運行命令

  • 1:可是它不會被docker run後面的命令覆蓋,而是把docker run指定的任何參數看成參數傳遞給entroypoint
  • 2:能夠和CMD一塊兒用,好比:
    ENTROYPOINT[「/usr/sbin/nginx」]
    CMD[「-h」]
    這樣若是docker run的時候不覆蓋CMD,那麼就是按照

    /usr/sbin/nginx –h來運行

    若是運行的時候:docker run –it 容器id –g「daemon off;」
    那麼實際運行就是:

    /usr/sbin/nginx –g 「daemon off;」了
  • 3:若是非要覆蓋entrypoint,能夠在docker run的時候,設置--entroypoint 標誌

2.3.9 ENV

用來在構建鏡像過程當中設置環境變量,例如:

ENV MY_PATH /usr/my
這個環境變量能夠在後續的任何RUN指令中使用,這就如同在命令前面指定了環境變量前綴同樣;也能夠在其它指令中直接使用這些環境變量,好比:
    WORKDIR $MY_PATH

能夠在docker run 命令中使用 –e來指定環境變量,這些變量只在運行時有效
小技巧:
能夠在不須要構建緩存的前面,添加一個ENV語句,這樣,要後面更新的時候,就修改一下這個ENV的值

2.3.10 ADD

用來將構建環境下的文件或目錄複製到鏡像中。

  • 1:只能操做構建環境相對的文件或目錄,文件源也可使用URL格式
  • 2:若是將一個歸檔文件指定爲源文件,docker會自動解壓
  • 3:若是目的位置不存在的話,Docker會自動建立全路徑

注意:ADD會使得構建緩存無效,ADD後續指令都不能使用以前的構建緩存了

2.3.11 COPY

相似於ADD,COPY只作構建上下文中複製文件,而不會去作文件提取和解壓的工做
若是源文件是目錄,那麼這整個目錄會被複制到容器中

2.3.12 VOLUME

用來向鏡像建立的容器添加捲,一個卷是能夠存在於一個或者多個容器內的特定目錄,這個目錄能夠繞過聯合文件系統,並提供以下共享數據或者對數據進行持久化:

  • 1:卷能夠在容器間共享和重用

    • 2:對卷的修改是當即生效的
    • 3:對卷的修改不影響鏡像

卷可讓咱們把數據、數據庫或其它內容添加到鏡像中,而不是將這些內容提交到鏡像中,而且容許咱們在多個容器間共享這些內容。
注意:若是刪除了最後一個使用卷的容器,內部卷就不見了。
可在docker run的時候,使用-v來把宿主機的目錄映射到容器,這樣數據就能一直保存了

2.3.13 ONBUILD

指定當鏡像作爲其它鏡像的基礎鏡像時,該鏡像觸發執行的功能。

ONBUILD在子鏡像build的時候,在FROM以後就先執行,而且只能被執行一次,不會被孫鏡像繼承

2.3.14 Dockerfile編寫最佳實踐

  • 1:容器應該是短暫的
  • 2:避免安裝沒必要要的包
  • 3:每一個容器應該只有一個關注點
  • 4:最小化層的數量
  • 5:對多行參數進行排序
  • 6:緩存中間構建的鏡像

3 製做本身的鏡像示例

3.1 簡介

以製做一個tomcat9的鏡像爲例。

3.2 準備工做

下載好要使用的jdk和tomcat,這裏下載的是:
jdk-8u144-linux-x64.tar.gz
apache-tomcat-9.0.1.tar.gz

3.3 編寫Dockerfile

FROM         ubuntu
MAINTAINER    cc
#把java與tomcat添加到容器中
ADD jdk-8u144-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.1 /usr/local/apache-tomcat-9.0.1
#配置java與tomcat環境變量
ENV JAVA_HOME /usr/local/jdk1.8.0_144
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.1
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.1
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器運行時監聽的端口
EXPOSE  8080
#啓動時運行tomcat
# CMD ["/usr/local/apache-tomcat-9.0.1/bin/catalina.sh","run"]
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.1/bin/startup.sh" ]
CMD /usr/local/apache-tomcat-9.0.1/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.1/bin/logs/catalina.out

444.png

555.png

  • 使用Dockerfile來製做鏡像
docker build -t cctomcat9 . ,注意後面有個 . ,表示在當前路徑找Dockerfile
  • 當前路徑還有:
apache-tomcat-9.0.1
apache-tomcat-9.0.1.tar.gz
Dockerfile
jdk-8u144-linux-x64.tar.gz
  • 啓動容器
docker run -i -t -d -p 9080:8080 --name myt9 -v /ccdockermake/tomcat9/test:/usr/local/apache-tomcat-9.0.1/webapps/test -v /tomcat9logs/:/usr/local/apache-tomcat-9.0.1/logs --privileged=true cctomcat9

4.錯誤解決

centos 7 Docker 啓動一個web服務 可是啓動時 報WARNING: IPv4 forwarding is disabled. Networking will not work.

4.1:解決辦法

編輯 /usr/lib/sysctl.d/00-system.conf

添加以下代碼:net.ipv4.ip_forward=1
重啓network服務:systemctl restart network
查看是否修改爲功:sysctl net.ipv4.ip_forward
若是返回爲「net.ipv4.ip_forward = 1」則表示成功了

關於web應用放的位置
靜態引入:能夠把web應用直接copy到容器中,分發方便
動態引入:就是如上這樣把宿主機上的目錄掛載到容器,方便調試

4.2 使用docker commit來製做鏡像

1:先把tomcat9鏡像運行起來
2:進入運行中的容器:docker exec -it 容器id /bin/bash,固然,先經過docker ps獲取容器號
3:進入運行起來的tomcat容器,刪除掉webapps裏面的東西,

而後再把本身的server.xml從宿主機拷貝到容器中,如:

docker cp ./server.xml 容器id:/usr/local/apache-tomcat-9.0.1/conf/server.xml
4:製做鏡像

docker commit -m=「remove default webapps」 -a=「cc」 容器id cctomcat:9.0
相關文章
相關標籤/搜索