Docker是個新生的事物,概念相似虛擬化。網上關於Docker入門的東西已經不少了。不過本文探討了Docker的特色、特性、原理,還介紹了具備中國特點的安裝測試過程,另外還談到了Docker的社區生態和Dockerfile,並使用Dockerfile構建一個nginx環境。原文:Docker簡介與入門linux
緣起
在幾個月前據說Docker,可是一直沒有時間去研究,前一段時間趁着azure免費試用,趕忙實驗一下,可是卡在了ubuntu基礎鏡像的下載上(因爲國內網絡的特殊緣由),因此也就擱淺了。在逛Segmentfault的時候,看到上面有個Docker子站問答,逛了逛果真有乾貨,因而從新試了一下,這裏把經驗和體會分享一下。nginx
Docker簡介
我以爲簡單來講,Docker就是一個應用程序執行容器,相似虛擬機的概念。可是與虛擬化技術的不一樣點在於下面幾點:git
- 虛擬化技術依賴物理CPU和內存,是硬件級別的;而docker構建在操做系統上,利用操做系統的containerization技術,因此docker甚至能夠在虛擬機上運行。
- 虛擬化系統通常都是指操做系統鏡像,比較複雜,稱爲「系統」;而docker開源並且輕量,稱爲「容器」,單個容器適合部署少許應用,好比部署一個redis、一個memcached。
- 傳統的虛擬化技術使用快照來保存狀態;而docker在保存狀態上不只更爲輕便和低成本,並且引入了相似源代碼管理機制,將容器的快照歷史版本一一記錄,切換成本很低。
- 傳統的虛擬化技術在構建系統的時候較爲複雜,須要大量的人力;而docker能夠經過Dockfile來構建整個容器,重啓和構建速度很快。更重要的是Dockfile能夠手動編寫,這樣應用程序開發人員能夠經過發佈Dockfile來指導系統環境和依賴,這樣對於持續交付十分有利。
- Dockerfile能夠基於已經構建好的容器鏡像,建立新容器。Dockerfile能夠經過社區分享和下載,有利於該技術的推廣。
Docker的主要特性以下(摘自Docker:具有一致性的自動化軟件部署):github
- 文件系統隔離:每一個進程容器運行在徹底獨立的根文件系統裏。
- 資源隔離:可使用cgroup爲每一個進程容器分配不一樣的系統資源,例如CPU和內存。
- 網絡隔離:每一個進程容器運行在本身的網絡命名空間裏,擁有本身的虛擬接口和IP地址。
- 寫時複製:採用寫時複製方式建立根文件系統,這讓部署變得極其快捷,而且節省內存和硬盤空間。
- 日誌記錄:Docker將會收集和記錄每一個進程容器的標準流(stdout/stderr/stdin),用於實時檢索或批量檢索。
- 變動管理:容器文件系統的變動能夠提交到新的映像中,並可重複使用以建立更多的容器。無需使用模板或手動配置。
- 交互式Shell:Docker能夠分配一個虛擬終端並關聯到任何容器的標準輸入上,例如運行一個一次性交互shell。
目前Docker正處在開發階段,官方不建議用於生產環境。另外,Docker是基於Ubuntu開發的,因此官方推薦將其安裝在Ubuntu的操做系統上,目前只能安裝在linux系統上。golang
Docker的使用入門
Docker官方的安裝指導挺詳細的。可是因爲國內的特殊狀況,我這裏基於這個安裝指導,給出適用於國內開發者的入門過程。基於Ubuntu Precise 12.04 (LTS) (64-bit)
,推薦這個版本,其餘版本參考官方安裝手冊。web
Docker的安裝
首先,Docker官方聲稱最好是運行在Linux內核3.8以上,因此要先進行內核升級redis
# install the backported kernel sudo apt-get update sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring # reboot sudo reboot
添加Docker倉庫的key:docker
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
添加鏡像,這裏直接用俄羅斯的Yandexshell
sudo sh -c "echo deb http://mirror.yandex.ru/mirrors/docker/ docker main > /etc/apt/sources.list.d/docker.list" sudo apt-get update
安裝Docker
sudo apt-get install lxc-docker
通常上面的步驟不會有任何問題。
Docker鏡像下載
Docker運行至少須要一個ubuntu的基礎鏡像,這個鏡像會在你初次嘗試執行時自動下載,不過從國內直接用基本上就別想了,須要使用代理。這裏用Docker中文社區提供的代理。出處1,出處2。
修改/etc/default/docker
文件,取消註釋http_proxy
的部分:
# If you need Docker to use an HTTP proxy, it can also be specified here. export http_proxy=http://192.241.209.203:8384/
通過筆者測試,上面這個代理也不是很穩定,可能用的人比較多吧。
可用的代理地址(持續關注中)
而後,你就能夠執行下面的命令,測試執行了,因爲代理不是很穩定,可能須要多嘗試幾回(淡定):
sudo docker run -i -t ubuntu /bin/bash
下面這個截圖是我成功pull完成,並測試hello world成功(大概嘗試了3-4次):
Docker的社區和生態
倉庫和鏡像
評估一項開源技術很大程度上須要關注它的社區和生態。Docker的生態是經過推送和拉取特定的「鏡像(image)包」來展開的。你能夠從docker index上搜索須要的鏡像。也能夠經過下面的命令搜索:
sudo docker search
鏡像能夠看做是包含有某些軟件的容器系統,好比ubuntu就是一個官方的基礎鏡像,不少鏡像都是基於這個鏡像「衍生」,該鏡像包含基本的ubuntu系統。再好比,hipache是一個官方的鏡像容器,運行後能夠支持http和websocket的代理服務,而這個鏡像自己又基於ubuntu。
經過pull
來拉取鏡像,將鏡像下載到本地,好比
sudo docker pull hipache
經過images
查看如今有哪些鏡像:
sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 13.10 9f676bd305a4 6 weeks ago 178 MB ubuntu saucy 9f676bd305a4 6 weeks ago 178 MB ubuntu 13.04 eb601b8965b8 6 weeks ago 166.5 MB ubuntu raring eb601b8965b8 6 weeks ago 166.5 MB ubuntu 12.10 5ac751e8d623 6 weeks ago 161 MB ubuntu quantal 5ac751e8d623 6 weeks ago 161 MB ubuntu 10.04 9cc9ea5ea540 6 weeks ago 180.8 MB ubuntu lucid 9cc9ea5ea540 6 weeks ago 180.8 MB ubuntu 12.04 9cd978db300e 6 weeks ago 204.4 MB ubuntu latest 9cd978db300e 6 weeks ago 204.4 MB ubuntu precise 9cd978db300e 6 weeks ago 204.4 MB
上面的都是鏡像,都從屬於ubuntu倉庫(通常倉庫名應該是username/repository
格式,若是是直接以repository
做爲倉庫名的,是指官方發佈的倉庫)。咱們拉取ubuntu的時候,其實是把倉庫裏的鏡像都拉下來了。每一個鏡像都有一個惟一的IMAGE ID
,和一個易於記憶的TAG
,能夠經過IMAGE ID
的前幾位或者repository:TAG
來標識一個鏡像。
Dockerfile和經過Dockerfile來構建Nginx容器
除了pull,鏡像也能夠經過"編譯"獲得,這裏的"編譯"是指一種構建行爲,經過手動編寫或者從github獲取Dockerfile來構建一個鏡像。能夠把Dockerfile當作是一個腳本,這個腳本會在容器每次啓動時執行。通常在Dockerfile裏面須要編寫基礎軟件的安裝腳本和配置腳本。下面這個Dockerfile是個例子:
# # Ubuntu Dockerfile # # https://github.com/dockerfile/ubuntu # # Pull base image. FROM ubuntu:12.10 # Update OS. RUN echo "deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse" > /etc/apt/sources.list RUN apt-get update RUN apt-get upgrade -y # Install basic packages. RUN apt-get install -y software-properties-common RUN apt-get install -y curl git htop unzip vim wget # Add files. ADD root/.bashrc /root/.bashrc ADD root/.gitconfig /root/.gitconfig ADD root/scripts /root/scripts # Set working directory. ENV HOME /root WORKDIR /root
FROM
指令表示此次構建須要基於ubuntu倉庫的12.10這個TAG的鏡像,若是本地不存在這個鏡像的話,會自動下載鏡像。鏡像實際上就是編譯好的結果。向上面這個Dockerfile,在原始ubuntu的基礎上安裝了不少經常使用的軟件。
docker官方有Dockerfile的教程
實踐
首先確保你已經完成上面的安裝步驟,並拉取到基礎鏡像ubuntu:12.10。
如今咱們用上面的Dockerfile來構建這個倉庫(上面的Dockerfile其實是github dockerfile項目的基本倉庫dockerfile/ubuntu,所下面的命令直接從github下載Dockerfile來構建)
sudo docker build -t="dockerfile/ubuntu" github.com/dockerfile/ubuntu
下面是最後構建成功時的輸出:
...
Processing triggers for ureadahead ...
---> 0a4392cf8e2d Step 6 : ADD root/.bashrc /root/.bashrc ---> b0e86f348c09 Step 7 : ADD root/.gitconfig /root/.gitconfig ---> e2a9c001d457 Step 8 : ADD root/scripts /root/scripts ---> 678febabdbdc Step 9 : ENV HOME /root ---> Running in c4afef311cf1 ---> eaa3ae3277a8 Step 10 : WORKDIR /root ---> Running in d50c273c75b8 ---> c9ecf5bc3227 Successfully built c9ecf5bc3227 Removing intermediate container 1a3d1f794c49 Removing intermediate container 9f72df8abb63 Removing intermediate container 5694d1e3e77e Removing intermediate container 6a184821f89c Removing intermediate container 8195bd05fc36 Removing intermediate container d50c273c75b8 Removing intermediate container 70de07353ecf Removing intermediate container 73e3f6204613 Removing intermediate container 5dd948415981 Removing intermediate container c4afef311cf1
此時會多出一個倉庫:
sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE dockerfile/ubuntu latest c9ecf5bc3227 About a minute ago 294.2 MB ...
如今咱們能夠來構建dockerfile/nginx了(固然,從一開始你就能夠直接pull
這個鏡像)
sudo docker build -t="dockerfile/nginx" github.com/dockerfile/nginx
完成後,會看到編譯好的鏡像:
sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
dockerfile/nginx latest 68508350c656 About a minute ago 308.3 MB dockerfile/ubuntu latest c9ecf5bc3227 16 minutes ago 294.2 MB ...
如今是時候看到真正的效果了!用下面這個命令運行容器:
sudo docker run -d -p 80:80 dockerfile/nginx
這個命令會以daemon的方式運行容器,經過下面命令查看正在運行的容器:
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
98c474a7dd6a dockerfile/nginx:latest nginx 6 seconds ago Up 6 seconds 0.0.0.0:80->80/tcp trusting_hawking
訪問你主機的80端口,能夠看到nginx的歡迎頁面了!這時,咱們來看看本機的進程sudo ps -ef
:
root 1428 952 0 15:19 ? 00:00:00 nginx: master process nginx root 1429 417 0 15:19 ? 00:00:00 /sbin/udevd --daemon www-data 1441 1428 0 15:19 ? 00:00:00 nginx: worker process www-data 1442 1428 0 15:19 ? 00:00:00 nginx: worker process www-data 1443 1428 0 15:19 ? 00:00:00 nginx: worker process www-data 1444 1428 0 15:19 ? 00:00:00 nginx: worker process
彷佛有些接近事物的本質了!nginx的進程其實是在本機上的,這意味着,容器中程序的執行仍然是使用本機操做系統的,容器並不本身構建操做系統,而是以某種隔離的方式依賴本機操做系統工做。這就是Docker和虛擬機的本質區別。
你能夠像下面這樣,將本機的目錄映射給這個"nginx容器"。<sites-enabled-dir>
目錄下應該有nginx的配置文件片斷
docker run -d -p 80:80 -v <sites-enabled-dir>:/etc/nginx/sites-enabled -v <log-dir>:/var/log/nginx dockerfile/nginx
PS:這步筆者沒有成功,日誌路徑是能夠map的,可是sites-enable-dir中的配置始終不行。繼續診斷中。
鏡像的共享與Dockfile的分發
能夠共享你的鏡像和用來構建的Dockfile分享給社區:
- Docker index是官方的鏡像目錄,能夠從裏面獲得大量的預編譯好的鏡像
- Dockerfile Project一個託管Dockerfile的倉庫集合
原理
總的來講Docker的核心技術以下:
- 命名空間
- AUFS(advanced multi layered unification filesystem)
- cgroup
因爲本人才疏學淺,下面給出一些參考資料,有興趣的朋友能夠擴展閱讀一下,必定會對Docker有更深入的認識的:
PaaS under the hood, episode 1: kernel namespaces
PaaS Under the Hood, Episode 2: cgroups
PAAS Under the Hood, Episode 3: AUFS
PaaS Under the Hood, Episode 4: GRSEC
PaaS under the hood, episode 5: Distributed routing with Hipache
參考資料
一些Docker的社區資源: