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