Docker 提供輕量的虛擬化,你能夠從Docker獲得一個額外抽象層,你能夠在單台機器上運行多個Docker微容器,
而每個微容器里都有一個微服務或獨立應用,例如你可以將Tomcat運行在一個Docker,而MySQL運行在另外一個Docker,
兩者可以運行在同一個服務器,或多個服務器上。未來可能每個應用都要Docker化。
容器的啟動和關系是非常快速的。Docker目前能夠有以下八種用途:
簡化配置
這是Docker初始目的,虛擬機VM最大的好處是基於你的應用配置能夠無縫運行在任何平台上。Docker提供同樣類似VM的能力,
但是沒有任何副作用,它能讓你將環境和配置放入代碼然后部署,同樣的Docker配置能夠在各種環境中使用,這實際是將應用
環境和底層環境實現了解耦。
代碼管道化管理
能夠對代碼以流式pipeline管道化進行管理,從開發者的機器到生產環境機器這個流程中都能有效管理。因為在這個流程中會
有各種不同的環境,每個都可能有微小的區別,Docker提供了跨越這些異構環境以一致性的微環境,從開發到部署實現流暢發布。
開發人員的生產化
在一個開發環境,我們希望我們的開發環境能更加接近於生產環境,我們會讓每個服務運行在自己的VM中,這樣能模擬生產環境,
比如有時我們並不總是需要跨越網絡連接,這樣我們可以將多個Docker裝載一系列服務運行在單機上最大程度模擬生產分布式部署的環境。
應用隔離
有很多理由你需要在一台機器上運行多個應用,這就需要將原來鐵板一塊monolithic的應用切分為很多微服務。實現應用之間的解耦,
將多個應用服務部署在多個Docker中能輕松達到這個目的。
服務合並
使用Docker也能合並多個服務以降低費用,不多的操作系統內存占用,跨實例共享多個空閑的內存,這些技術Docker能以更加緊密資源
提供更有效的服務合並。
多租戶
Docker能夠作為雲計算的多租戶容器,使用Docker能容易為每個租戶創建運行應該多個實例,這得益其靈活的快速環境以及有效diff命令。
快速部署
Docker通過創建進程的容器,不必重新啟動操作系統,幾秒內能關閉,你可以在數據中心創建或銷毀資源,不用擔心額外消耗。
典型的數據中心利用率是30%,通過更積極的資源分配,以低成本方式對一個新的實例實現一個更聚合的資源分配,
我們很容易超過這個利用率,大大提高數據中心的利用效率。
我們都知道,操作系統分為內核和用戶空間。對於 Linux 而言,內核啟動后,會掛載 root 文件系統為其提供用戶空間支持。
而 Docker 鏡像( Image) ,就相當於是一個 root 文件系統。比如官方鏡像 ubuntu:14.04 就包含了完整的一套Ubuntu 14.04
最小系統的 root 文件系統。
Docker 鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,
還包含了一些為運行時准備的一些配置參數( 如匿名卷、環境變量、用戶等) 。鏡像不包含任何動態數據,
其內容在構建之后也不會被改變。
分層存儲
因為鏡像包含操作系統完整的 root 文件系統,其體積往往是龐大的,因此在Docker 設計時,就充分利用 Union FS 的技術,
將其設計為分層存儲的架構。所以嚴格來說,鏡像並非是像一個 ISO 那樣的打包文件,鏡像只是一個虛擬的概念,其實際體現
並非由一個文件組成,而是由一組文件系統組成,或者說,由多層文件系統聯合組成。
鏡像構建時,會一層層構建,前一層是后一層的基礎。每一層構建完就不會再發生改變,后一層上的任何改變只發生在自己這一層。
比如,刪除前一層文件的操作,實際不是真的刪除前一層的文件,而是僅在當前層標記為該文件已刪除。在最終容器運行的時候,
雖然不會看到這個文件,但是實際上該文件會一直跟隨鏡像。因此,在構建鏡像的時候,需要額外小心,每一層盡量只包含該層
需要添加的東西,任何額外的東西應該在該層構建結束前清理掉。
分層存儲的特征還使得鏡像的復用、定制變的更為容易。甚至可以用之前構建好的鏡像作為基礎層,然后進一步添加新的層,
以定制自己所需的內容,構建新的鏡像。
Docker 容器
鏡像( Image) 和容器( Container) 的關系,就像是面向對象程序設計中的 類 和 實例一樣,鏡像是靜態的定義,
容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等。
容器的實質是進程,但與直接在宿主執行的進程不同,容器進程運行於屬於自己的獨立的 命名空間。
因此容器可以擁有自己的 root 文件系統、自己的網絡配置、自己的進程空間,甚至自己的用戶 ID 空間。
容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立於宿主的系統下操作一樣。
這種特性使得容器封裝的應用比直接在宿主運行更加安全。也因為這種隔離的特性,很多人初學Docker 時常常會把容器和虛擬機搞混。
前面講過鏡像使用的是分層存儲,容器也是如此。每一個容器運行時,是以鏡像為基礎層,在其上創建一個當前容器的存儲層,
我們可以稱這個為容器運行時讀寫而准備的存儲層為容器存儲層。
容器存儲層的生存周期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,任何保存於容器存儲層的信息都會隨容器刪除而丟失。
按照 Docker 最佳實踐的要求,容器不應該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。所有的文件寫入操作,
都應該使用 數據卷( Volume) 、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,
其性能和穩定性更高。
數據卷的生存周期獨立於容器,容器消亡,數據卷不會消亡。因此,使用數據卷后,容器可以隨意刪除、重新 run ,數據卻不會丟失。
docker Registry
鏡像構建完成后,可以很容易的在當前宿主上運行,但是,如果需要在其它服務器上使用這個鏡像,我們就需要一個集中的存儲、
分發鏡像的服務,Docker Registry就是這樣的服務。
一個 Docker Registry 中可以包含多個倉庫( Repository) ;每個倉庫可以包含多個標簽( Tag) ;每個標簽對應一個鏡像。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用於對應該軟件的各個版本。我們可以通過 <倉庫名>:<標簽>
的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 latest 作為默認標簽。
以 Ubuntu 鏡像 為例, ubuntu 是倉庫的名字,其內包含有不同的版本標簽,如, 14.04 , 16.04 。
我們可以通過 ubuntu:14.04 ,或者 ubuntu:16.04來具體指定所需哪個版本的鏡像。如果忽略了標簽,
比如 ubuntu ,那將視為ubuntu:latest 。
倉庫名經常以 兩段式路徑 形式出現,比如 jwilder/nginx-proxy ,前者往往意味着 Docker Registry多用戶環境下的用戶名,
后者則往往是對應的軟件名。但這並非絕對,取決於所使用的具體 Docker Registry 的軟件或服務。
Docker Registry 公開服務
Docker Registry 公開服務是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。一般這類公開服務允許用戶免費上傳、
下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。
最常使用的 Registry 公開服務是官方的 Docker Hub,這也是默認的 Registry,並擁有大量的高質量的官方鏡像。
除此以外,還有 CoreOS 的 Quay.io,CoreOS 相關的鏡像存儲在這里;Google 的 Google Container Registry,
Kubernetes 的鏡像使用的就是這個服務。
由於某些原因,在國內訪問這些服務可能會比較慢。國內的一些雲服務商提供了針對 Docker Hub 的鏡像服務( Registry Mirror) ,
這些鏡像服務被稱為加速器。常見的有 阿里雲加速器、DaoCloud 加速器、靈雀雲加速器等。使用加速器會直接從國內的地址下載
Docker Hub 的鏡像,比直接從官方網站下載速度會提高很多。在后面的章節中會有進一步如何配置加速器的講解。
國內也有一些雲服務商提供類似於 Docker Hub 的公開服務。比如 時速雲鏡像倉庫、網易雲鏡像服務、DaoCloud 鏡像市場、
阿里雲鏡像庫等。
私有 Docker Registry
除了使用公開服務外,用戶還可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,
可以直接使用做為私有 Registry 服務。在后續的相關章節中,會有進一步的搭建私有 Registry 服務的講解。
開源的 Docker Registry 鏡像只提供了 Docker Registry API 的服務端實現,足以支持 docker 命令,不影響使用。
但不包含圖形界面,以及鏡像維護、用戶管理、訪問控制等高級功能。在官方的商業化版本 Docker Trusted Registry
中,提供了這些高級功能。
除了官方的 Docker Registry 外,還有第三方軟件實現了 Docker Registry API,甚至提供了用戶界面以及一些高級功能
。比如,VMWare Harbor 和 SonatypeNexus。