Docker簡介與入門

pchou發表於2014-08-25

  Docker是個新生的事物,概念類似虛擬化。網上關於Docker入門的東西已經很多了。不過本文探討了Docker的特點、特性、原理,還介紹了具有中國特色的安裝測試過程,另外還談到了Docker的社群生態和Dockerfile,並使用Dockerfile構建一個nginx環境。

 緣起

  Docker是個新生的事物,概念類似虛擬化。網上關於Docker入門的東西已經很多了。不過本文探討了Docker的特點、特性、原理,還介紹了具有中國特色的安裝測試過程,另外還談到了Docker的社群生態和Dockerfile,並使用Dockerfile構建一個nginx環境。在幾個月前聽說Docker,但是一直沒有時間去研究,前一段時間趁著azure免費試用,趕緊實驗一下,但是卡在了ubuntu基礎映象的下載上(由於國內網路的特殊原因),所以也就擱淺了。在逛Segmentfault的時候,看到上面有個Docker子站問答,逛了逛果然有乾貨,於是重新試了一下,這裡把經驗和體會分享一下。

 Docker簡介

  我覺得簡單來說,Docker就是一個應用程式執行容器,類似虛擬機器的概念。但是與虛擬化技術的不同點在於下面幾點:

  1. 虛擬化技術依賴物理CPU和記憶體,是硬體級別的;而docker構建在作業系統上,利用作業系統的containerization技術,所以docker甚至可以在虛擬機器上執行。
  2. 虛擬化系統一般都是指作業系統映象,比較複雜,稱為“系統”;而docker開源而且輕量,稱為“容器”,單個容器適合部署少量應用,比如部署一個redis、一個memcached。
  3. 傳統的虛擬化技術使用快照來儲存狀態;而docker在儲存狀態上不僅更為輕便和低成本,而且引入了類似原始碼管理機制,將容器的快照歷史版本一一記錄,切換成本很低。
  4. 傳統的虛擬化技術在構建系統的時候較為複雜,需要大量的人力;而docker可以通過Dockfile來構建整個容器,重啟和構建速度很快。更重要的是Dockfile可以手動編寫,這樣應用程式開發人員可以通過釋出Dockfile來指導系統環境和依賴,這樣對於持續交付十分有利。
  5. Dockerfile可以基於已經構建好的容器映象,建立新容器。Dockerfile可以通過社群分享和下載,有利於該技術的推廣。

  Docker的主要特性如下(摘自Docker:具備一致性的自動化軟體部署):

  1. 檔案系統隔離:每個程式容器執行在完全獨立的根檔案系統裡。
  2. 資源隔離:可以使用cgroup為每個程式容器分配不同的系統資源,例如CPU和記憶體。
  3. 網路隔離:每個程式容器執行在自己的網路名稱空間裡,擁有自己的虛擬介面和IP地址。
  4. 寫時複製:採用寫時複製方式建立根檔案系統,這讓部署變得極其快捷,並且節省記憶體和硬碟空間。
  5. 日誌記錄:Docker將會收集和記錄每個程式容器的標準流(stdout/stderr/stdin),用於實時檢索或批量檢索。
  6. 變更管理:容器檔案系統的變更可以提交到新的映像中,並可重複使用以建立更多的容器。無需使用模板或手動配置。
  7. 互動式Shell:Docker可以分配一個虛擬終端並關聯到任何容器的標準輸入上,例如執行一個一次性互動shell。

  目前Docker正處在開發階段,官方不建議用於生產環境。另外,Docker是基於Ubuntu開發的,所以官方推薦將其安裝在Ubuntu的作業系統上,目前只能安裝在linux系統上。

 Docker的使用入門

  Docker官方的安裝指導挺詳細的。但是由於國內的特殊情況,我這裡基於這個安裝指導,給出適用於國內開發者的入門過程。基於Ubuntu Precise 12.04 (LTS) (64-bit),推薦這個版本,其他版本參考官方安裝手冊。

  Docker的安裝

  首先,Docker官方聲稱最好是執行在Linux核心3.8以上,所以要先進行核心升級

# 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:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9

  新增映象,這裡直接用俄羅斯的Yandex

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/

  經過筆者測試,上面這個代理也不是很穩定,可能用的人比較多吧。

  可用的代理地址(持續關注中)

http://192.241.209.203:8384

  然後,你就可以執行下面的命令,測試執行了,由於代理不是很穩定,可能需要多嘗試幾次(淡定):

sudo docker run -i -t ubuntu /bin/bash

  下面這個截圖是我成功pull完成,並測試hello world成功(大概嘗試了3-4次):

docker-introduction-1

 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的核心技術如下:

  • 名稱空間
  • 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

  Under the Hood系列

  LXC (Linux 虛擬環境)簡單介紹

  docker原理簡介

 參考資料

  Docker官方

  Docker:具備一致性的自動化軟體部署

  Dockerfile的教程

  一些Docker的社群資源:

  SegmentfaultDocker子站問答

  Docker中文社群

  Docker中文文件

相關文章