看到這標(biāo)題你可能會(huì)想,網(wǎng)上不是已經(jīng)有很多Docker的入門介紹了么?同一個(gè)主題被講過很多次,還有沒有必要必要再講?可是,我體內(nèi)這混雜的的高傲與固執(zhí)雖然讓人厭惡,但卻讓我廣受大家的歡迎,這也讓我覺得我應(yīng)該來一發(fā)(篇),哈哈。
舉一個(gè)我遇到的場(chǎng)景,ELK三劍客,即Elasticsearch、Logstash和Kibana。我可以選擇把它們直接安裝在我的MacBook上,這是我主力開發(fā)機(jī),但是在上面已經(jīng)裝好一個(gè)Elasticsearch了。我不想破壞現(xiàn)在已有的環(huán)境。要解決這個(gè)問題,用2015年時(shí)下最熱門的解決方案就是Docker了。如果過去一年關(guān)于Docker的各種熱鬧你都錯(cuò)過了,那么請(qǐng)繼續(xù)往下看。
Docker做的事情就是將的軟件隔離起來,讓它們即使出了問題也不會(huì)互相影響。這并不是什么橫空出世的新思想。你很可能會(huì)說內(nèi)核控制的進(jìn)程不就這樣玩么?每一個(gè)進(jìn)程都有自己的內(nèi)存空間,并且在一個(gè)進(jìn)程自身看來,內(nèi)存空間與所處在的計(jì)算機(jī)的內(nèi)存空間是一樣的。然而內(nèi)核欺騙了進(jìn)程,在背后將內(nèi)存地址重新映射到了真實(shí)的內(nèi)存空間中。想想今天高速運(yùn)轉(zhuǎn)處理器,任何地方見到的系統(tǒng)都能同時(shí)運(yùn)行多個(gè)進(jìn)程。今天的文明社會(huì)比人類歷史任何一個(gè)時(shí)間點(diǎn)制造的謊言數(shù)量級(jí)都要很多的量級(jí)。
扯遠(yuǎn)了,Docker將進(jìn)程的隔離模型的進(jìn)行了擴(kuò)展,讓隔離性變得更強(qiáng)。Docker是在Linux內(nèi)核的基礎(chǔ)上打造的一系列工具。整個(gè)文件系統(tǒng)被抽象了,網(wǎng)絡(luò)被虛擬化了,其它進(jìn)程被隱藏了,并且從理論上,不可能逃脫容器去對(duì)在一個(gè)機(jī)器上的其他進(jìn)程搞破壞。實(shí)際中,每個(gè)人對(duì)于怎么才能逃脫容器,至少去收集一點(diǎn)運(yùn)行容器的機(jī)器的相關(guān)信息,持開放的態(tài)度。跟虛擬機(jī)比較起來,容器的隔離性還是較弱。
上面箭頭:提升單機(jī)性能;下面箭頭:提升隔離性
但換個(gè)角度看,進(jìn)程比容器性能更好,容器性能比虛擬機(jī)性能更佳。原因很簡(jiǎn)單,隔離性更高,在每一個(gè)上下文中就需要運(yùn)行更多的東西,從而拖慢速度。選擇一個(gè)隔離性的過程,實(shí)際就是決定你對(duì)要運(yùn)行進(jìn)程的信任有多少的過程 - 它會(huì)不會(huì)去干擾其他的進(jìn)程?如運(yùn)行的進(jìn)程都是自己的親兒子,那你對(duì)他們會(huì)有一個(gè)很高的信任度,對(duì)他們用最少的隔離,運(yùn)行在一個(gè)進(jìn)程中就行了。如果是SAP,那么你很可能需要盡可能高的隔離性:將電腦裝在封存在箱子里,綁在火箭上發(fā)射到月球。
Docker另一個(gè)很好的特性是,容器可以作為一個(gè)整體交付。他們不會(huì)像虛擬機(jī)那么臃腫。這大大的提高了部署的簡(jiǎn)易度。在這個(gè)微服務(wù)流行的世界里,你可以很容易將你的服務(wù)捆在一起,用鏡像來發(fā)布。你甚至可以將build的結(jié)果指定成一個(gè)Docker鏡像。
Docker將會(huì)怎樣改變軟件開發(fā)和部署的過程仍然有待觀察。盡管我覺得Docker是一種帶有破壞性的技術(shù),但影響還在幾年之后才會(huì)到來。雖然我會(huì)認(rèn)為Docker會(huì)讓很多系統(tǒng)管理員丟掉工作,但是實(shí)際上Docker卻會(huì)改變他們的工作。每個(gè)人現(xiàn)在都需要一點(diǎn)變革,趕上時(shí)代的腳步。
又扯遠(yuǎn)了,說說OSX上的Docker。
細(xì)心的你可能注意到,我之前說Docker是運(yùn)行在Linux內(nèi)核之上的。然而OSX沒有Linux內(nèi)核,那怎么運(yùn)行Docker呢。為了解決這個(gè)問題,我們需要用虛擬機(jī)來運(yùn)行Docker。我們可以用一個(gè)叫boot2docker的工具來做這件事情,但是最近被docker-machine取代了。
我的機(jī)上有一個(gè)比較老的Docker,但是我覺得想試試Docker Compose,因?yàn)槲疫\(yùn)行著很多的服務(wù)。Docker Compose能讓很多的容器協(xié)作起來運(yùn)行一個(gè)整體的環(huán)境。為了遵循保證隔離服務(wù)的宗旨,每一個(gè)服務(wù)都運(yùn)行在單獨(dú)的容器中。因而,一個(gè)典型的web應(yīng)用中,可以把web服務(wù)器運(yùn)行在一個(gè)容器里面,數(shù)據(jù)庫運(yùn)行在另外一個(gè)容器里面,然后這些容器可以放在同一個(gè)機(jī)器上。
我從Docker官網(wǎng)上下載了安裝包,并且跟著安裝指南
http://docs.docker.com/mac/step_one/安裝。裝好Docker后,我讓docker-machine在Virtual Box上創(chuàng)建了新的虛擬機(jī)。
一起看起來很順利,然后啟動(dòng)隨處可見的hello-world鏡像。
很驚訝這個(gè)鏡像的并不完全,完全沒有發(fā)現(xiàn)任何一個(gè)地方有“hello world”的輸出。然而好在,不是每一個(gè)Docker鏡像都實(shí)現(xiàn)地這般草率。這個(gè)hello world的例子比較無聊,看看能不能找到更加有意思的。我們想從容器中服務(wù)一個(gè)頁面,我打算使用Nginx,已經(jīng)有一個(gè)現(xiàn)成的Nginx的容器了,因此我創(chuàng)建了個(gè)新的Dockerfile。Dockerfile包含了一系列如何指導(dǎo)Docker從一系列鏡像中創(chuàng)建出一個(gè)容器的指令。這里提到的容器包含以下內(nèi)容:
- FROM nginx
- COPY *.html /usr/share/nginx/html/
第一行設(shè)置了我們?nèi)萜鞯幕A(chǔ)鏡像。第二行將本地的帶有html后綴的文件拷貝到Nginx容器中WEB服務(wù)器的目錄里。為了使用這個(gè)Dockerfile文件,我們需要?jiǎng)?chuàng)建一個(gè)Docker的鏡像:
- /tmp/nginx$ docker build -t nginx_test .
- Sending build context to Docker daemon 3.072 kB
- Step 0 : FROM nginx
- latest: Pulling from library/nginx
- 843e2bded498: Pull complete
- 8c00acfb0175: Pull complete
- 426ac73b867e: Pull complete
- d6c6bbd63f57: Pull complete
- 4ac684e3f295: Pull complete
- 91391bd3c4d3: Pull complete
- b4587525ed53: Pull complete
- 0240288f5187: Pull complete
- 28c109ec1572: Pull complete
- 063d51552dac: Pull complete
- d8a70839d961: Pull complete
- ceab60537ad2: Pull complete
- Digest: sha256:9d0768452fe8f43c23292d24ec0fbd0ce06c98f776a084623d62ee12c4b7d58c
- Status: Downloaded newer image for nginx:latest
- ---> ceab60537ad2
- Step 1 : COPY *.html /usr/share/nginx/html/
- ---> ce25a968717f
- Removing intermediate container c45b9eb73bc7
- Successfully built ce25a968717f
Docker build命令開始將拉取已經(jīng)構(gòu)建好的Nginx容器。然后將我們的文件拷貝到容器里面,并且顯示容器的hash值,這讓它們很容易辨認(rèn)。要運(yùn)行這個(gè)容器我們可以運(yùn)行:
- /tmp/nginx$ docker run --name simple_html -d -p 3001:80 -p 3002:443 nginx_test
這條命令讓Docker運(yùn)行nginxtest的容器,并且取名為simple_html。-d選項(xiàng)是為了讓Docker在后臺(tái)運(yùn)行這條命令,并且最終-p選項(xiàng)是為了轉(zhuǎn)發(fā)端口,這里需要將本地的3001端口映射到容器的80端口 - 即正常的web服務(wù)器端口?,F(xiàn)在我們可以連接到web服務(wù)上了。如果我們打開chrome,訪問localhost:3001就會(huì)看到:
居然不行,問題在于Docker沒有意識(shí)到自己運(yùn)行在虛擬機(jī)的環(huán)境里面,因此我們需要將vm的端口映射到我們本地機(jī)器上:
- Docker container:80 -> vm host:3001 -> OSX:3001
這個(gè)從虛擬機(jī)管理器里面可以輕松的搞定:
現(xiàn)在我們可以看到頁面了:
這就是我們放在容器中的文件。好極了!現(xiàn)在我準(zhǔn)備好嘗試更復(fù)雜一點(diǎn)的容器了。
小貼士: 我注意到在虛擬機(jī)里面同時(shí)并行的運(yùn)行Docker會(huì)整個(gè)讓系統(tǒng)hang住。我懷疑同時(shí)跑兩個(gè)虛擬工具可能讓某個(gè)地方卡住產(chǎn)生了沖突的結(jié)果。我相信docker-machine的并行的支持正在在積極的解決中,0.5版本可能會(huì)看到。直到這之前,你可以參考:
http://kb.parallels.com/en/123356并且看看:
https://github.com/Parallels/docker-machine中對(duì)docker-machine的fork版本。
原文鏈接:Yet another intro to docker (翻譯:鐘最龍 校對(duì):宋喻) 譯文來自:DockOne.io