一.簡介html
Docker是一個使用Go語言開發的開源的應用容器引擎,讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的機器上。Docker的發展速度和火爆程度着實使人驚歎,一發不可收拾,造成了席捲整個IT界的新浪潮。學完本課程你將瞭解到什麼是docker,docker的思想以及諸如鏡像,倉庫,容器等核心概念。你將學會怎樣運行一個容器,如何搭建私有倉庫,怎麼寫dockerfile以及怎樣把本身的應用放到容器中運行。mysql
Docker爲何這麼火?它確實解決了大部分企業的痛點,好比快速的持續集成、服務的彈性伸縮、部署簡單、解放運維,更重要的是爲企業節省了機器資源。目前有很是多的公司在生產環境中大規模的使用Docker,京東618在2015年的618大促中,大膽啓用了基於Docker的容器技術來承載大促的關鍵業務,在2016年11月份,阿里超大規模Docker化之路,在2015年的3月份,騰訊萬臺規模的Docker應用實踐。Docker已成爲IT從業人員的必備技能,無論你是從事開發、測試、運維,在從此的工做中,都會接觸到Docker。nginx
二.什麼是Dockergit
1.Docker歷史github
2010 dotCloud PAASweb
2013年docker開源spring
2014年6月,Docker1.0sql
2014年7月,C輪$4000萬docker
2015年4月,D輪$9500萬數據庫
至今Docker1.13
2.什麼是Docker?
Docker是一個用來裝應用的容器,就像杯子能夠裝水,筆筒能夠放筆,書包能夠放書同樣,你能夠把Hello World放到Docker裏,你能夠把網站放到Docker裏,你能夠把任何你想獲得的程序放到Docker裏。
Docker is the world's leading software containerization platform,Docker是世界領先的軟件容器化平臺。
Docker公司開發的,開源,託管在github。
跨平臺,支持Windows、Macos、Linux。
三.理解Docker
1.Docker思想
a.集裝箱:把運行程序放到新的機器上去,Docker集裝箱保證咱們程序無論放在哪均可以正常運行。
b.標準化:
運輸方式標準化(Docker運輸程序它有一個超級碼頭,任何一個地方須要貨物的時候,都由鯨魚送到超級碼頭,而後再由鯨魚把貨物送到目的地去。對應技術來講,假如你要把你的臺式機上的應用部署到你的筆記本上,用Docker就標準化了這個過程,只需在臺式機上執行一個命令,把鯨魚派過來,把程序送到超級碼頭去,再在你的筆記本上執行一個Docker命令,由鯨魚把程序從超級碼頭送到筆記本上去)
存儲方式標準化(把程序拷貝到筆記本上的時候,得給它指定一個目錄,還得記住這個命令,由於下次有改動一些東西的時候,可能還須要繼續往這傳,有了Docker以後就不用了,由於存儲方式標準化,不須要關心應用存儲在什麼地方,要運行它或中止它的時候,只需執行一個命令就能夠了)
API接口標準化(Docker提供了一系列的resful API接口,包含了對Docker應用的控制(啓動、中止、查看、刪除等),如當你要啓動你的程序的時候,你可能須要執行tomcat startup命令,中止的時候執行shutdown命令,若是不是tomcat命令,須要用別的命令來控制它。有了Docker接口標準化後,只須要執行一樣的命令就能控制全部的應用。
c.隔離
在用虛擬機時,有自已可用內存、CPU、硬盤,徹底感受不到外面主機的存在,Docker差很少,不過它的技術更加的輕量,能夠實現快速的建立和銷燬。好比你建立一個虛擬機可能要等個幾分鐘,而建立Docker只須要1秒。最底層的技術實際上就是Linux的一種內核的限制機制,叫作LXC(LXC是一種輕量級的容器虛擬化技術,它最大效率的隔離了進程和資源,經過CGoup、NameSpace的限制,隔離進程組所使用的物理資源,好比CPU、Memory、IO等),其實這個機制早在七、8年前就加到了Linux內核了,直到2013年Docker出世時它才火起來。雲計算、敏捷開發、高頻率的彈性伸縮需求、IT行業這些年的長足發展造就了Docker的火爆。
2.Docker解決了什麼問題?
a.Docker解決了運行環境不一致帶來的問題。
若是一個應用要能運行起來,須要最底層的操做系統,操做系統上它依賴JDK、Tomcat、代碼、配置文件。
1).操做系統變了可能致使程序運行失敗,好比個人程序調用了系統的某些命令,換了個系統調不起來了。
2).JDK版本也可能致使程序運行失敗,好比Class文件是JDK1.7編譯的,機器上裝了一個1.6的JDK,就會出現Class版本識別不了。
3).Tomcat版本也可能致使失敗,好比舊版本的配置在新版本中再也不支持了。
4).代碼更是有可能了,好比你的代碼依賴了磁盤D盤的一個文件,或者用了系統的環境編碼等等。
5).配置也是同樣,要不是你的配置是和系統相關的,換了個環境就跑不起來
Docker把操做系統、JDK、Tomcat、代碼、配置都一個個的給放到集裝箱裏,再打包放到鯨魚上,由鯨魚給咱們送到服務器上,在你的機器上怎麼運行,在服務器上也將怎麼運行,不會有任何的問題。
b.系統好卡,哪一個哥們又寫死循環了?!
若是有和別人共用服務器呢,可能會有這樣的體會,莫名其妙的發現程序掛了,一查緣由,要不是內存不夠,要不是硬盤滿了,或者忽然發現某一個服務變慢了,甚至終端都比較卡,Linux自己是一個多租戶的操做系統,能夠供多我的使用,怎麼辦呢?用Docker,Dockder的隔離性就徹底解決了這個問題。它是怎麼解決的呢?若是把你們的程序都放到Docker裏運行,就算別人的程序仍是死循環,瘋狂吃CPU,或者是瘋狂的打日誌把磁盤佔滿,或者是佔用大量的內存,內存泄露,都不會致使別人的程序運行錯誤,只會致使自已的程序錯誤,由於Docker在啓動的時候就給它限定好了最大使用的CPU、內存、硬盤,若是它超過了,就殺掉。
c.雙十一來了,服務器撐不住啦!
你們知道,業務系統的業務量不必定是平均的,特別是電商系統,每一年老是有那麼幾天,業務量會比平時多幾倍,甚至幾十倍,若是按平時的量去準備服務器,到雙十一確定撐不住,但要是按雙十一的規模去準備服務器,平時就是極大的浪費,因此就只能在節日前臨時擴展機器,過完節再把多餘的節點下線,這就給運維帶來很是大的工做量,一到這種節日就須要在各類機器上部署各類各樣的服務,你們知道,我啓動一個程序,我要裝操做系統、JDK、Tomcat等好多好多東西,還有可能啓不來,還要調試,這是一個很是繁重的工做。Docker讓這一切變得很是美好了,只須要點一下鼠標,就能夠立馬從10臺服務器變成100臺,甚至1000、1000臺,都是分分鐘的事,由於Docker無論在哪臺機器上,無論要運行什麼服務,都是用標準的方式把咱們的程序運過來,再用標準的方式把它運行起來,這樣就能夠作到,我只要在每臺機器上執行一兩條命令就可讓程序跑起來,而且不用擔憂會不會有問題。
Docker的標準化讓快速擴展、彈性伸縮變得簡單。
四.走進Docker
1.Docker裏有三個核心詞彙:Build、Ship、Run
鏡像就是集裝箱,倉庫就是超級碼頭,容器就是運行程序的地方,用Docker運行一個程序的過程就是去倉庫把鏡像拉到本地,而後用一條命令把鏡像運行起來,變成容器。
Build:構建,就是構建鏡像。
Ship:運輸,運輸鏡像,從倉庫、主機上運輸。
Run:運行的鏡像,就是一個容器。
2.Docker鏡像
鏡像的英文名是image,前面咱們講到了集裝箱,想像一下,鯨魚馱着的全部集裝箱都是一個鏡像,那麼從本質上來講,鏡像究竟是什麼呢?
其實鏡像就是一系列的文件,它能夠包括咱們運行程序的文件,也能夠包括咱們應用運行環境的文件,既然都是文件,Docker把它保存到本地了嗎?答案是確定的。可是它以什麼格式保存的呢?說到鏡像的存儲格式,就要提到Linux的存儲技術,叫作聯合文件系統Union File System(UFS),它是一種分層的文件系統,它能夠將不一樣的目錄掛到同一個虛擬文件系統下。
好比test1目錄下有三個文件夾,test2目錄下有一個文件README、兩個文件夾,聯合文件系統就是能夠在同一個文件夾下看到這裏的五個文件夾和一個文件README,也就是這兩個文件夾的集合。
經過這樣一種方式呢,聯合文件系統就能夠實現文件的分層,好比test1能夠看作第一層,test2能夠看作第二層,每一層有每一層的文件,Docker就是利用了這種分層的概念來實現了鏡像存儲,下面就是鏡像的存儲格式圖。
很明顯地能夠看到這張圖是分層的,下面有一層,上面也是一層一層的,一個個集裝箱挪在一塊兒,這就是鏡像最直觀的存儲形式,這個例子它的最底層是操做系統的引導,上面是具體的Linux操做系統,再上面是相關的軟件(若是是咱們的程序,那可能就是JDK、Tomcat),最上面一層先忽略不看,是下面講容器時要看到的一種。
Docker鏡像每一層文件系統都是隻讀的,把每一層加載完成以後呢,這些文件都會被看做是同一個目錄,至關只有一個文件系統,Docker的這種文件系統被稱做爲鏡像。
3.Docker容器
容器的本質就是一個進程,爲了便於理解,能夠想像成一個虛擬機,每一個虛擬機都有自已的文件系統,能夠把整個這一部分看做是容器的文件系統,至關於虛擬機裏面全部的文件系統,它和虛擬機的區別是它這裏的文件系統是一層一層的,而且這下面的N層都是隻讀的,只有上面一層是可寫的。爲何要有可寫的這一層呢?想想若是你們的程序運行起來,勢必會要寫一些日誌,寫一些文件,或者對系統的某一些文件作一些修改,這是大部分程序都有的需求,因此容器在最上面一層建立了一個可讀可寫的文件系統。
若是程序在運行過程當中要寫一個鏡像裏面的一個文件,這種狀況將發生什麼呢?由於鏡像的每一層都是隻讀的,因此它在寫這個文件以前會把這個文件這一層拷到文件的最上一層,而後再對它進行修改,修改了以後,當咱們的應用讀一個文件的時候會從頂層開始查找,若是沒有才會找下一層,由於咱們這個文件已被拷到最上一層了,因此會在最上一層找到它最新的內容。因爲容器的最上一層是能夠修改的,而鏡像是不能夠修改的,這樣就能夠保證同一個鏡像能夠生成多個容器獨立運行,而它們之間沒有任何的干擾。
4.Docker倉庫
構建鏡像的目的就是爲了在其它的機器或環境運行個人程序,那我就須要把個人鏡像傳到目的地去,我該如何完成傳輸過程?這就用到了Docker倉庫,我須要先把個人鏡像傳到Docker倉庫裏去,目的地再從倉庫把個人鏡像拉過去,這就完成了這樣的一個傳輸過程。誰提供Dockder倉庫呢?確定有一箇中央服務器提供給我地址去訪問它,是誰提供了這樣的服務呢?Docker自已就提供了,提供服務的地址就是:hub.docker.com。但這這個網站在開始的時候在國內訪問不了,如今雖然能夠訪問了,可是下載鏡像的速度很是的慢。爲了解決這個問題,國內不少的公司作自已的倉庫,比較知名的倉庫有163yun.com/product/repo(網易蜂巢的一個鏡像中心),這裏有一些咱們經常使用的鏡像,這些倉庫都是其它公司給咱們提供好的中心,咱們能夠把鏡像傳過去,若是個人鏡像比較私密,不想讓別人看到,只是內部的人使用的話,Docker也支持咱們自已搭建一個鏡像中心,好比咱們是一個內網的環境,能夠把咱們的鏡像中心在內網搭建起來,最後咱們在鏡像的傳輸過程放到內網的Docker倉庫裏就好了。
五.Docker安裝
1.Windows安裝
Docker對Win10作了原生的支持。
附:boot2docker.iso下載地址:http://pan.baidu.com/s/1qYyc0ag
運行docker version,輸出Client和Server信息,則說明已安裝OK,以下所示:
2.MacOS安裝
3.Linux安裝
Redhat&CentOS的安裝詳見《》。
Docker是在Ubuntu上開發的,對Ubuntu支持是最好的,下面以Ubuntu爲例演示安裝過程。
a.檢查內核版本,檢查其值是否大於3.10
切入到root用戶,將apt-get更新到最新版本。
b.apt-get install -y docker.io安裝Docker
這種安裝方式是用系統自帶的安裝包,可能不是Docker的最新版本,如要安裝Docker最新版本,可使用curl -s https://get.docker.com|sh
這句話的意思就是把get.docker.com網頁的內容拿過來,執行sh,這是Docker提供的一種安裝方式。
c.service docker start啓動Docker
d.執行docker version查看docker是否安裝OK
六.Docker初體驗
1.第一個Docker鏡像
docker pull [OPTIONS] NAME[:TAG]:從Docker遠程倉庫拉取鏡像到本地。NAME是要拉取的鏡像的名稱,後面的TAG是可選的,若是不加默認是:laster,表示鏡像的最新版本,用TAG就會下載TAG指定的版本。OPTIONS是拉取的一些參數。
docker images [OPTIONS] [REPOSITORY[:TAG]]:查看本機有哪些鏡像,也能夠驗證pull是否成功,其中,REPOSITORY表示鏡像的名稱。
實例:pull hello-world鏡像
在此設置使用docker國內鏡像DaoCloud,右鍵點擊桌面右下角的docker圖標,選擇Settings。
在Daemon標籤下的Registry mirrors列表中加入下面的鏡像地址:http://141e5461.m.daocloud.io,點擊 Apply,Docker服務將會自動重啓生效。
這塊相關資料能夠參考《在windows系統下如何查找域名對應IP地址?》、《Docker獲取鏡像報錯 docker: Error response from daemon》。
而後,再pull hello-world鏡像。
REPOSITORY:鏡像的名字
TAG:latest,最新版
IMAGE_ID:是一個64位的字符串,它能夠惟一的標識咱們的鏡像,這裏只顯示16位,後面在顯示時自動被截掉了
CREATED:建立時間,說明這個hello-world在五週之前被修改過
SIZE:大小,只有1.84k
若是是Linux系統,則按以下操做設置國內鏡像:
1.修改或建立daemon.json文件:vi /etc/docker/daemon.json
將如下配置寫入到文件中,保存並退出:
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
2.重啓docker:systemctl restart docker.service
2.第一個Docker容器
docker run [OPTIONS] IMAGE[:TAG][COMMAND][ARG...]:IMAGE表示鏡像的名字,COMMAND表示這個鏡像在運行起來的時候要執行什麼命令,ARG表示這條命令所依賴的參數。
代表運行成功。
最左邊Client是咱們在本機的Docker Client,就是咱們執行命令的時候Docker Client的部分,中間這部分DOCKER_HOST也是在咱們本機的Docker服務(Docker Daemon),最右邊是Docker的遠程倉庫。
Docker Client輸入docker pull,將會向Docker Daemon發起pull命令,告訴Docker Daemon要拉取某一個鏡像,Docker Daemon會先在本機Images去檢查鏡像是否存在,若是存在且版本就是你所要拉取的版本,就不會作任何的操做,若是不存在將會去Docker倉庫找咱們須要拉取的鏡像名字,若是找到了就會從Docker倉庫傳到咱們本地,把咱們要的鏡像拉到本地來。
Docker Client輸入docker run,第一步也是把咱們的命令發到本地的Docker Daemon,Docker Daemon會檢查這個鏡像是否在本機已經存在,若是不存在,將會執行一個至關於Docker pull的過程去遠端Docker倉庫把鏡像下載回來,而後經過必定的方式把這個鏡像運行起來,變成Docker容器。
七.Docker運行Nginx
1.運行nginx鏡像
Nginx是一個Web服務器,是一個持久運行的容器,上面咱們的hello-world是前臺運行的(由於咱們能看到它打印出的運行結果),運行Nginx能夠選擇前臺運行,也能夠選擇後臺運行,若是一個前臺運行的鏡像,能夠用Ctrl+C結束進程,進程結束了,鏡像也就結束了,因此說Nginx最好的運行方式是後臺運行。成功運行Nginx後,能夠進入容器內部看看Nginx容器究竟是什麼樣的。
docker run -d library/nginx命令的返回字符串表明容器的ID,docker ps看到的CONTAINER ID是同樣的。
-d表示後臺運行,若是想了解更到docker run參數,能夠運行docker run --help查看。
docker exec --help能夠看到命令的詳細解釋,這就是在一個運行的容器中運行一個命令。
docker exec -it 30d bash
2.docker網絡
a.網絡類型
bridge模式
docker的隔離性,網絡也是隔離性的一部分,Linux用了namespace來進行資源的隔離,好比PIDNameSpace就是用來隔離進程的,Mount NameSpace用來隔離文件系統的,Network NameSpace是用來隔離網絡的,每個Network NameSpace都提供了一份獨立的網絡環境,包括網卡、路由、iptable規則等等,都是與其它的Network NameSpace隔離的,Docker容器在默認狀況下都是分配一個獨立的Network NameSpace,也就是網絡類型中的bridge模式。
Host模式
若是啓動容器的時候,指定使用Host模式,那麼這個容器將不會得到一個獨立的Network NameSpace,而是和主機共同使用一個,這個時候,容器將不會虛擬出自已的網卡,配置自已的IP等等,而是會使用宿主機上的IP和端口,也就是在Docker裏使用網絡的時候和在主機上使用網絡是同樣的。
None模式
Docker將不會和外界的任何東西進行通訊。
b.端口映射
在使用bridge模式的時候,就涉及到了一個問題,既然它使用了網絡有獨立的NameSpace,這就須要一種技術使容器內的端口能夠在主機上訪問到,這種技術就是端口映射。Docker能夠指定你想把容器內的某一個端口能夠在容器所在主機上的某一個端口作一個映射,當你在訪問主機上的這個端口的時候,其實就是訪問容器裏面的那個端口。
docker run --help能夠看到,-p會開放一個容器的端口到主機上,默認是空的,-P是開放全部的端口到一個隨機的端口。
如上先把原來的nginx容器停掉,再指定映射端口啓動,並檢查8080端口確實已被佔用,這時經過瀏覽器輸入localhost:8080便可正常訪問到nginx,以下所示:
咱們再用-P方式來運行一下。
用docker ps能夠看到端口映射的狀況,在我本機上開了一個32768的隨機端口映射到容器裏的80端口,用netstat -ano|findstr "32768"檢查一下實際端口也是啓動了。
此時用localhost:8080就不能夠訪問了,用localhost:32768能夠正常訪問。
八.Docker化Java web應用
1.製做自已的鏡像
Dockerfile:告訴Docker,我要怎麼樣來製做個人鏡像,我要製做鏡像每一步操做是什麼。
docker build:用來執行Dockerfile裏面所描述的每一件事情,最終會把Docker鏡像構建出來。
Jpress:http://jpress.io/,開源的博客平臺,我這裏用我自已的工程SpringMVC,下載地址:https://bijian1013.iteye.com/blog/2307353
2.將下載下來的SpringMVC配置到Eclipse中,將其Export成war包
將生成的SpringMVC.war包拷貝到E:\develop目錄下
3.下載基礎library/tomcat鏡像
docker pull library/tomcat
4.以上面tomcat基礎鏡像爲起點,製做鏡像
編寫Dockerfile
from library/tomcat MAINTAINER bijian xxx@126.com COPY SpringMVC.war /usr/local/tomcat/webapps
構建鏡像,命令:docker build E:\develop
若是不知道命令參數時,能夠用docker build --help命令查看參數。
5.運行自已的鏡像
命令:docker run -d -p 8888:8080 springmvc
此時,在瀏覽器上輸入http://localhost:8888/,能正常打開tomcat主頁,代表Tomcat啓動成功。
輸入http://localhost:8888/SpringMVC/greet,頁面輸出內容以下:
運行正常,在這裏咱們的SpringMVC項目不依賴數據庫,假如咱們的項目還依賴mysql,那麼能夠經過pull library/mysql下載library/mysql鏡像。
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=000000 -e MYSQL_DATABASE=springmvc library/mysql命令運行mysql鏡像,docker restart 7532592dac95重啓tomcat應用springmvc。
九.小結
1.集裝箱,標準化,隔離
2.鏡像、容器、倉庫(BUID、SHIP、RUN)
構建鏡像,運行容器,鏡像經過倉庫來傳輸,Docker集裝箱的思想就體如今鏡像上,咱們的鏡像是分層的,一層一層的,每一層的東西都是固定的,一個鏡像打好後,就好像一個大大的集裝箱,它裏面的東西是固定的文件,不會發生變化。
Docker標準化思想在咱們使用各類Docker命令時應該也會體會到,無論是在啓動一個鏡像的方式,仍是在下載和運行一個鏡像的時候,都會發現咱們所作的操做是基本差很少的。
Docker的隔離思想,網絡隔離、進程隔離、磁盤隔離,容器運行起來,就有自已的進程空間、磁盤、網絡。
3.docker命令pull,build,run,stop,restart,exec...
docker pull:下拉鏡像
docker build:構建鏡像
docker run:運行一個容器
docker stop:中止容器
docker restart:重啓一個容器
docker exec:進行容器的內部