docker學習筆記二

 

什麼是docker鏡像?

Docker鏡像是由文件系統疊加而成。最底端是一個引導文件系統,即bootfs,這很像典型的Linux/Unix的引導文件系統。Docker用戶幾乎永遠不會和引導文件系統有什麼交互。實際上,當一個容器啓動後,它將會被移到內存中,而引導文件系統則會被卸載(unmount),以留出更多的內存供initrd磁盤鏡像使用。

實際上,Docker鏡像的第二層是root文件系統rootfs,它位於引導文件系統之上。rootfs可以是一種或多種操作系統(如Debian或者Ubuntu文件系統)

在傳統的Linux引導過程中,root文件系統會最先以只讀的方式加載,當引導結束並完成了完整性檢查之後,它纔會被切換爲讀寫模式。但是在Docker裏,root文件系統永遠只能是隻讀狀態,並且Docker利用聯合加載[1](union mount)技術又會在root文件系統層上加載更多的只讀文件系統。聯合加載指的是一次同時加載多個文件系統,但是在外面看起來只能看到一個文件系統。聯合加載會將各層文件系統疊加到一起,這樣最終的文件系統會包含所有底層的文件和目錄。

  Docker將這樣的文件系統稱爲鏡像。一個鏡像可以放到另一個鏡像的頂部。位於下面的鏡像稱爲父鏡像(parent image),可以依次類推,直到鏡像棧的最底部,最底部的鏡像稱爲基礎鏡像(base image)。最後,當從一個鏡像啓動容器時,Docker會在該鏡像的最頂層加載一個讀寫文件系統。我們想在Docker中運行的程序就是在這個讀寫層中執行的。

當Docker第一次啓動一個容器時,初始的讀寫層是空的。當文件系統發生變化時,這些變化都會應用到這一層上。比如,如果想修改一個文件,這個文件首先會從該讀寫層下面的只讀層複製到該讀寫層。該文件的只讀版本依然存在,但是已經被讀寫層中的該文件副本所隱藏。

 

         通常這種機制被稱爲寫時複製(copy on write),這也是使Docker如此強大的技術之一。每個只讀鏡像層都是隻讀的,並且以後永遠不會變化。當創建一個新容器時,Docker會構建出一個鏡像棧,並在棧的最頂端添加一個讀寫層。這個讀寫層再加上其下面的鏡像層以及一些配置數據,就構成了一個容器。在上一章我們已經知道,容器是可以修改的,它們都有自己的狀態,並且是可以啓動和停止的。容器的這種特點加上鏡像分層框架(image-layering framework),使我們可以快速構建鏡像並運行包含我們自己的應用程序和服務的容器

列出鏡像

$docker images

鏡像從倉庫下載下來。鏡像保存在倉庫中,而倉庫存在於Registry中。默認的Registry是由Docker公司運營的公共Registry服務,即Docker Hub

Docker Hub(或者用戶自己運營的Registry)中,鏡像是保存在倉庫中的。可以將鏡像倉庫想象爲類似Git倉庫的東西。它包括鏡像、層以及關於鏡像的元數據(metadata

拉取的鏡像並不是一個完整的操作系統,只是一個裁剪版,只包含最低限度的支持系統運行的組件。

$ sudo docker run -t -i --name new_container ubuntu:12.04 /bin/bash 

這個例子會從鏡像ubuntu:12.04啓動一個容器,而這個鏡像的操作系統則是Ubuntu 12.04

在構建容器時指定倉庫的標籤也是一個很好的習慣。這樣便可以準確地指定容器來源於哪裏

Docker Hub中有兩種類型的倉庫:用戶倉庫(user repository)和頂層倉庫(top-level repository。用戶倉庫的鏡像都是由Docker用戶創建的,而頂層倉庫則是由Docker內部的人來管理的。

  用戶倉庫的命名由用戶名和倉庫名兩部分組成,如myhub/zjib

    用戶名:myhub

倉庫名:zjib

頂層倉庫只包含倉庫名部分,如ubuntu倉庫。頂層倉庫由Docker公司和由選定的能提供優質基礎鏡像的廠商(如Fedora團隊提供了fedora鏡像)管理,用戶可以基於這些基礎鏡像構建自己的鏡像。同時頂層倉庫也代表了各廠商和Docker公司的一種承諾,即頂層倉庫中的鏡像是架構良好、安全且最新的

拉取鏡像

docker run命令從鏡像啓動一個容器時,如果該鏡像不在本地,Docker會先從Docker Hub下載該鏡像。如果沒有指定具體的鏡像標籤,那麼Docker會自動下載latest標籤的鏡像

其實也可以通過docker pull命令先發制人地將該鏡像拉取到本地。使用docker pull命令可以節省從一個新鏡像啓動一個容器所需的時間

$docker pull ……

 

查找鏡像

通過docker search命令來查找所有Docker Hub上公共的可用鏡像

這條命令會完成鏡像查找工作,並返回如下信息:

    倉庫名;

    鏡像描述;

    用戶評價(Stars反應出一個鏡像的受歡迎程度;

    是否官方(Official由上游開發者管理的鏡像(如fedora鏡像由Fedora團隊管理);

    自動構建(Automated表示這個鏡像是由Docker Hub的自動構建(Automated Build)流程創建的。

構建鏡像

前面我們已經看到了如何拉取已經構建好的帶有定製內容的Docker鏡像,那麼我們如何修改自己的鏡像,並且更新和管理這些鏡像呢?構建Docker鏡像有以下兩種方法。

    使用docker commit命令。

    使用docker build命令和Dockerfile文件

首次學習的時候那本書上說並不推薦使用docker commit命令,而應該使用更靈活、更強大的Dockerfile來構建Docker鏡像

創建Docker Hub賬號

官網註冊,在linux上使用

$docker login        進行登錄

Dockercommit命令創建鏡像

創建Docker鏡像的第一種方法是使用docker commit命令。可以將此想象爲我們是在往版本控制系統裏提交變更。我們先創建一個容器,並在容器裏做出修改,就像修改代碼一樣,最後再將修改提交爲一個新鏡像

$docker commit

我們啓動了一個容器,並在裏面安裝了nginx。我們會將這個容器作爲一個Web服務器來運行,所以我們想把它的當前狀態保存下來。這樣就不必每次都創建一個新容器並再次在裏面安裝nginx了。爲了完成此項工作,需要先使用exit命令從容器裏退出,之後再運行docker commit命令

在這條命令裏,我們指定了更多的信息選項。首先-m選項用來指定新創建的鏡像的提交信息。同時還指定了--a選項,用來列出該鏡像的作者信息。接着指定了想要提交的容器的ID。最後的myhub/nginx指定了鏡像的用戶名和倉庫名,: 併爲該鏡像增加了一個webserver標籤

可以用docker inspect命令來查看新創建的鏡像的詳細信息

如果想從剛創建的新鏡像運行一個容器,可以使用docker run命令

⑳ 刪除image

 docker images

 容器在運行中的話是沒辦法刪除鏡像的,所以刪除鏡像之前要先讓容器停止運行

docker stop

docker  rmi  id/name   刪除鏡像

docker  rm  id/name  刪除容器

 

2、用Dockerfile構建鏡像

並不推薦使用docker commit的方法來構建鏡像。相反,推薦使用被稱爲Dockerfile的定義文件和docker build命令來構建鏡像。Dockerfile使用基本的基於DSL(Domain Specific Language))語法的指令來構建一個Docker鏡像,我們推薦使用Dockerfile方法來代替docker commit,因爲通過前者來構建鏡像更具備可重複性、透明性以及冪等性

 

wo創建了一個名爲static_web的目錄用來保存Dockerfile,這個目錄就是我們的構建環境(build environment),Docker則稱此環境爲上下文(context)或者構建上下文(build context)。Docker會在構建鏡像時將構建上下文和該上下文中的文件和目錄上傳到Docker守護進程。這樣Docker守護進程就能直接訪問用戶想在鏡像中存儲的任何代碼、文件或者其他數據

 

該Dockerfile由一系列指令和參數組成。每條指令,如FROM,都必須爲大寫字母,且後面要跟隨一個參數:FROM centos。Dockerfile中的指令會按順序從上到下執行,所以應該根據需要合理安排指令的順序。

  每條指令都會創建一個新的鏡像層並對鏡像進行提交。Docker大體上按照如下流程執行Dockerfile中的指令

  •    Docker從基礎鏡像運行一個容器。
  • 執行一條指令,對容器做出修改。
  • 執行類似docker commit的操作,提交一個新的鏡像層。
  • Docker再基於剛提交的鏡像運行一個新容器。
  • 執行Dockerfile中的下一條指令,直到所有指令都執行完畢。

每個Dockerfile的第一條指令必須是FROM。FROM指令指定一個已經存在的鏡像,後續指令都將基於該鏡像進行,這個鏡像被稱爲基礎鏡像(base iamge)

在前面的Dockerfile示例裏,我們指定了centos作爲新鏡像的基礎鏡像。基於這個Dockerfile構建的新鏡像將以centos操作系統爲基礎。在運行一個容器時,必須要指明是基於哪個基礎鏡像在進行構建。

  接着指定了MAINTAINER指令,這條指令會告訴Docker該鏡像的作者是誰,以及作者的電子郵件地址。這有助於標識鏡像的所有者和聯繫方式

  RUN指令會在當前鏡像中運行指定的命令。在這個例子裏,我們通過RUN指令更新了已經安裝的APT倉庫,安裝了nginx包,之後創建了/usr/share/nginx/html/index.html文件,該文件有一些簡單的示例文本。像前面說的那樣,每條RUN指令都會創建一個新的鏡像層,如果該指令執行成功,就會將此鏡像層提交,之後繼續執行Dockerfile中的下一條指令

默認情況下,RUN指令會在shell裏使用命令包裝器/bin/sh -c來執行。如果是在一個不支持shell的平臺上運行或者不希望在shell中運行(比如避免shell字符串篡改),也可以使用exec格式的RUN指令

在這種方式中,我們使用一個數組來指定要運行的命令和傳遞給該命令的每個參數

EXPOSE指令,這條指令告訴Docker該容器內的應用程序將會使用容器的指定端口。這並不意味着可以自動訪問任意容器運行中服務的端口(這裏是80)。出於安全的原因,Docker並不會自動打開該端口,而是需要用戶在使用docker run運行容器時來指定需要打開哪些端口。一會兒我們將會看到如何從這一鏡像創建一個新容器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章