在計算機技術發展的早期,幾乎全部的程序都是在開發後部署到一臺或是少數幾臺服務器上的。那時的程序也幾乎都是集全部模塊和運行時環境爲一身的「全棧應用」,雖然這些程序能夠基於一套良好、完善的協議棧 ( 譬如一套完整的 MVC 架構 ) 進行開發,但再好的架構也沒法讓應用服務在這種體系下快速發展。html
隨着互聯網的極速發展,應用程序的功能愈來愈豐富,而須要迭代的速度要求也愈來愈高,爲了實現這些目標,應用的開發逐漸趨向服務化甚至微服務化。每一個應用程序都有其對應依賴的操做系統或者其餘程序,而在將應用程序細分爲不一樣的微服務或者是其餘形式的微小應用模塊後,解決這種依賴問題會愈發顯得棘手。有的應用運行環境特別複雜,搭建過程也極易出錯,這都是讓開發、測試、運維人員焦頭爛額的地方。更多時候,開發者們確定更願意將他們寶貴的時間用在實際的開發中,而不是糾纏着應用運行環境的問題上。git
同時,因爲物理硬件的更新迭代速度已經難以追趕互聯網的腳步,應用的部署逐漸轉向集羣化。應用模塊的數量乘上每一個應用所部署的機器的數量,會是一個很是龐大的數字。相信全部的開發或者運維都不會願意把時間浪費在逐一搭建服務器環境這種重複的勞動上。docker
這些變化都對應用的開發、部署帶來了不小的挑戰。編程
我想不少讀者已經想到了應對這些挑戰的辦法了,沒錯,那就是虛擬化技術。經過虛擬化技術可讓環境的搭建變得更加的容易,對咱們快速部署分佈式應用服務體系提供了極大的便利。安全
進而言之,若是咱們把管理環境的複雜度,更輕量級的虛擬化實現等更加實際的問題考慮進去,容器技術天然成了虛擬化技術中最佳的選擇項。bash
若是說在分佈式部署中應用容器技術是一個方向,那麼 Docker 就是在這個方向上跑得最快也最完美的運動員了。Docker 不論從實現容器技術的完整性上來講,仍是從上手易用性來講,都是可圈可點的。服務器
好了,這裏我要穿插一下推薦 Docker 的緣由了。咱們使用 Docker 的目的其實很簡單,就是利用它的全面性和易用性來提高咱們的工做效率。瞭解了這個目的,我想你們會更容易理解不少場合 Docker 能派上用場的緣由。固然,經過這個道理,你也就明白了爲何我會說 Docker 是一門新時代開發者必須掌握的技術了。畢竟全部的老闆都但願找到會得多、幹活快的優秀開發者 ( 亦或者說,會的多、幹活快是優秀開發者所必備的品質 )。網絡
再怎麼從理論上說快也是很難服衆的,是騾子是馬拉出來「跑個分」就知道了。Docker 官方對 Docker 在工做上帶來的提高作了調查研究,分別從工做效率的提高和技術設計投入的減小等方面數據化了 Docker 所作出的突出貢獻。架構
讓咱們先來從一張 Docker 官方提供的架構圖來看看 Docker 對容器結構的設計。 運維
與其餘虛擬化實現甚至其餘容器引擎不一樣的是,Docker 推崇一種輕量級容器的結構,即一個應用一個容器。舉個具體的例子,在常見的虛擬機實現中,咱們要搭建一套 LAMP 結構的服務,咱們一般會創建一個虛擬機,在虛擬機中安裝上 Linux 系統,以後分別安裝 Apache、MySQL 和 PHP。而在 Docker 裏,最佳的實踐是分別基於 Apache、MySQL 和 PHP 的鏡像創建三個容器,分別運行 Apache、MySQL 和 PHP ,而它們所在的虛擬操做系統也直接共享於宿主機的操做系統。 若是咱們將 Docker 的輕量級容器實現和虛擬機的一些參數進行對比,更容易獲得結果。
屬性 | Docker | 虛擬機 |
---|---|---|
啓動速度 | 秒級 | 分鐘級 |
硬盤使用 | MB 級 | GB級 |
性能 | 接近原生 | 較低 |
普通機器支撐量 | 數百個 | 幾個 |
雖然這裏只列出了一些 Docker的優點項,但這些優點都是對咱們開發中環境搭建和使用極其有幫助的內容。就拿啓動速度來講,咱們在開發中顯然不肯意調整環境或更新代碼後要等待幾分鐘來讓其生效,Docker 秒級的啓動速度幾乎讓咱們感知不到咱們對環境作了什麼改動。而像虛擬機佔用大量操做系統資源,致使咱們本地開發使用電腦過慢 ( 有時候不得不將環境搭建在另外的機器上,但這顯然在代碼編寫到運行自測的過程當中增長不少工做量 ) 等問題,也容易獲得解決。
從理論上咱們已經知道 Docker 可以爲咱們的工做帶來巨大的便利,那麼將其放於實踐中,咱們應該如何正確的使用它呢?這裏我摘錄整理了一段來自 Docker 官方文檔的指導意見,但願可以對你們的實踐提供參考。
使用 Docker 後,開發者可以在本地容器中獲得一套標準的應用或服務的運行環境,由此能夠簡化開發的生命週期 ( 減小在不一樣環境間進行適配、調整所形成的額外消耗 )。對於整個應用迭代來講,加入 Docker 的工做流程將更加適合持續集成 ( Continuous Integration ) 和持續交付 ( Continuous Delivery )。
舉個具體的例子:
基於容器技術的 Docker 擁有很高的跨平臺性,Docker 的容器可以很輕鬆的運行在開發者本地的電腦,數據中心的物理機或虛擬機,雲服務商提供的雲服務器,甚至是混合環境中。
同時,Docker 的輕量性和高可移植性可以很好的幫助咱們完成應用的動態伸縮,咱們能夠經過一些手段近實時的對基於 Docker 運行的應用進行彈性伸縮,這可以大幅提升應用的健壯性。
Docker 的高效和輕量等特徵,爲替代基於 Hypervisor 的虛擬機提供了一個經濟、高效、可行的方案。在 Docker 下,你能節約出更多的資源投入到業務中去,讓應用程序產生更高的效益。同時,如此低的資源消耗也說明了 Docker 很是適合在高密度的中小型部署場景中使用。
在 Docker 體系裏,有四個對象 ( Object ) 是咱們不得不進行介紹的,由於幾乎全部 Docker 以及周邊生態的功能,都是圍繞着它們所展開的。它們分別是:鏡像 ( Image )、容器 ( Container )、網絡 ( Network )、數據卷 ( Volume )。
鏡像 ( Image ) 這個概念相信你們不會陌生,由於它是其餘虛擬化技術 ( 特別是虛擬機 ) 中經常被使用的一個概念。所謂鏡像,能夠理解爲一個只讀的文件包,其中包含了虛擬環境運行最原始文件系統的內容。
固然,Docker 的鏡像與虛擬機中的鏡像仍是有必定區別的。首先,以前咱們談到了 Docker 中的一個創新是利用了 AUFS(參考文檔:www.cnblogs.com/sammyliu/p/… 做爲底層文件系統實現,經過這種方式,Docker 實現了一種增量式的鏡像結構。
每次對鏡像內容的修改,Docker 都會將這些修改鑄形成一個鏡像層,而一個鏡像其實就是由其下層全部的鏡像層所組成的。固然,每個鏡像層單獨拿出來,與它之下的鏡像層均可以組成一個鏡像。另外,因爲這種結構,Docker 的鏡像實質上是沒法被修改的,由於全部對鏡像的修改只會產生新的鏡像,而不是更新原有的鏡像。
容器 ( Container ) 就更好理解了,在容器技術中,容器就是用來隔離虛擬環境的基礎設施,而在 Docker 裏,它也被引伸爲隔離出來的虛擬環境。
若是把鏡像理解爲編程中的類,那麼容器就能夠理解爲類的實例。鏡像內存放的是不可變化的東西,當以它們爲基礎的容器啓動後,容器內也就成爲了一個「活」的空間。
用更官方的定義,Docker 的容器應該有三項內容組成:
對於大部分程序來講,它們的運行都不會是孤立的,而是要與外界或者更準確的說是與其餘程序進行交互的,這裏的交互絕大多數狀況下指的就是數據信息的交換。網絡通信是目前最經常使用的一種程序間的數據交換方式了。
因爲計算機網絡領域擁有相對統一且獨立的協議等約定,其跨平臺性很是優秀,全部的應用均可以經過網絡在不一樣的硬件平臺或操做系統平臺上進行數據交互。特別是在分佈式雲計算的時代,應用或服務間的通信更是充分依賴於網絡傳輸,因此天然擁有一套完善的網絡體系支撐,是承載應用運行所必須的基礎設施。
在 Docker 中,實現了強大的網絡功能,咱們不但可以十分輕鬆的對每一個容器的網絡進行配置,還能在容器間創建虛擬網絡,將數個容器包裹其中,同時與其餘網絡環境隔離。
另外,利用一些技術,Docker 可以在容器中營造獨立的域名解析環境,這使得咱們能夠在不修改代碼和配置的前提下直接遷移容器,Docker 會爲咱們完成新環境的網絡適配。對於這個功能,咱們甚至可以在不一樣的物理服務器間實現,讓處在兩臺物理機上的兩個 Docker 所提供的容器,加入到同一個虛擬網絡中,造成徹底屏蔽硬件的效果。
正是由於擁有強大的網絡功能,才能讓咱們製造健壯的 Docker 應用體系。
除了網絡以外,文件也是重要的進行數據交互的資源。在以往的虛擬機中,咱們一般直接採用虛擬機的文件系統做爲應用數據等文件的存儲位置。然而這種方式其實並不是徹底安全的,當虛擬機或者容器出現問題致使文件系統沒法使用時,雖然咱們能夠很快的經過鏡像重置文件系統使得應用快速恢復運行,可是以前存放的數據也就消失了。
爲了保證數據的獨立性,咱們一般會單獨掛載一個文件系統來存放數據。這種操做在虛擬機中是繁瑣的,由於咱們不但要搞定掛載在不一樣宿主機中實現的方法,還要考慮掛載文件系統兼容性,虛擬操做系統配置等問題。值得慶幸的是,這些在 Docker 裏都已經爲咱們輕鬆的實現了,咱們只須要簡單的一兩個命令或參數,就能完成文件系統目錄的掛載。
可以這麼簡單的實現掛載,主要仍是得益於 Docker 底層的 Union File System 技術。在 UnionFS 的加持下,除了可以從宿主操做系統中掛載目錄外,還可以創建獨立的目錄持久存放數據,或者在容器間共享。
在 Docker 中,經過這幾種方式進行數據共享或持久化的文件或目錄,咱們都稱爲數據卷 ( Volume )。
時至今日,Docker 生態已經遠比它誕生之初要龐大許多,雖然咱們仍然習慣使用 Docker 這個名字去指代實現容器技術支持的軟件,但顯然更加容易與其餘的概念產生混淆。這裏咱們頗有必要對這個 Docker 中最核心的軟件進行介紹,不只由於它在 Docker 生態中扮演着中心的地位,也由於它是咱們在開發中實實在在接觸最多的東西。
目前這款實現容器化的工具是由 Docker 官方進行維護的,Docker 官方將其命名爲 Docker Engine,同時定義其爲工業級的容器引擎 ( Industry-standard Container Engine )。在 Docker Engine 中,實現了 Docker 技術中最核心的部分,也就是容器引擎這一部分。
docker daemon 和 docker CLI 雖然咱們說 Docker Engine 是一款軟件,但實實在在去深究的話,它其實算是由多個獨立軟件所組成的軟件包。在這些程序中,最核心的就是 docker daemon 和 docker CLI 這倆了。
全部咱們一般認爲的 Docker 所能提供的容器管理、應用編排、鏡像分發等功能,都集中在了 docker daemon 中,而咱們以前所提到的鏡像模塊、容器模塊、數據卷模塊和網絡模塊也都實如今其中。在操做系統裏,docker daemon 一般以服務的形式運行以便靜默的提供這些功能,因此咱們也一般稱之爲 Docker 服務。
在 docker daemon 管理容器等相關資源的同時,它也向外暴露了一套 RESTful API,咱們可以經過這套接口對 docker daemon 進行操做。或者更確切的說,是經過這套 RESTful API 對 docker daemon 中運行的容器和其餘資源進行管理。一般來講,咱們是採用在控制檯或者命令行輸入命令來控制 docker daemon 的,由於這樣很酷也更容易適應那些有或者沒有圖形界面的操做系統。
那麼問題來了,若是咱們在控制檯中編寫一個 HTTP 請求以藉助 docker daemon 提供的 RESTful API 來操控它,那顯然是個費腦、費手又費時間的活兒。因此在 Docker Engine 裏還直接附帶了 docker CLI 這個控制檯程序。
熟悉程序結構的朋友們比較容易看出來,docker daemon 和 docker CLI 所組成的,正是一個標準 C/S ( Client-Server ) 結構的應用程序。銜接這二者的,正是 docker daemon 所提供的這套 RESTful API。整體上來講,咱們能夠將 Dockerfile 理解爲一個由上往下執行指令的腳本文件。當咱們調用構建命令讓 Docker 經過咱們給出的 Dockerfile 構建鏡像時,Docker 會逐一按順序解析 Dockerfile 中的指令,並根據它們不一樣的含義執行不一樣的操做。
若是進行細分,咱們能夠將 Dockerfile 的指令簡單分爲五大類。
docker pull gitlab/gitlab-ce
複製代碼
sudo docker run --detach \
--hostname fhero.me \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume ~/gitlab/config:/etc/gitlab \
--volume ~/gitlab/logs:/var/log/gitlab \
--volume ~/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
複製代碼
由於部署在本地,又指定了fhero.me做爲域名,因此在/etc/hosts配置下,這樣能夠經過域名訪問gitlab。
docker run \
-u root \
--rm \
-d \
-p 8081:8080 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkinsci/blueocean
複製代碼
Jenkins新建項目中源碼管理使用Git時遇到以下問題: Failed to connect to repository : Error performing command: git ls-remote -h …. 須要查看服務器上是否已經安裝git.
從起啓動Jenkins時輸入以前的用戶名和密碼,居然提示我無效的用戶名或密碼,最後只能用強攻了,將用戶名和密碼去掉,直接進入到Jenkins。
二、修改$JENKINS_HOME下的config.xml ①將true元素中的true改成false ②將和元素的內容刪掉 三、從新啓動Jenkins(docker restart 12bda098be23) 就能夠直接訪問Jenkins了,不用在登陸了,比較暴力,不推薦。swam建立集羣:mp.weixin.qq.com/s/cKRAs-H8p…?