【Docker技術入門與實踐(第2版)】Docker容器入門(IT必備)-學習筆記

第一章

1 Docker入門須知

1.1 Docker基本知識

       Docker是基於Go語言實現的開源容器項目,誕生於2013年年初,最初發 起者是dotCloud公司。Docker自開源後受到廣泛的關注和討論,目前已有多個相關項目(包括Docker三劍客、Kubernetes等),逐漸形成了圍繞Docker容器的生態體系。現在主流的Linux操作系統都已經支持Docker。例如,紅帽公司的RHEL 6.5/CentOS 6.5往上的操作系統、Ubuntu14.04往上的操作系統,都已經在軟件 源中默認帶有Docker軟件包。

       Docker的構想是要實現“Build,Ship and Run Any App,Anywhere”, 即通過對應用的封裝(Packaging)、分發(Distribution)、部署 (Deployment)、運行(Runtime)生命週期進行管理,達到應用組件“一次封裝,到處運行”的目的。這裏的應用組件,既可以是一個 Web應用、一個編譯環境,也可以是一套數據庫平臺服務,甚至是一個操作系統或集羣。

                    

1.2  Docker VS 虛擬化

       虛擬化是一種資源管理技術,是將計算機的各種實體資源,如服務 器、網絡、內存及存儲等,予以抽象、轉換後呈現出來,打破實體結構間的 不可切割的障礙,使用戶可以比原本的組態更好的方式來應用這些資源。

       虛擬化的核心是對資源的抽象,目標往往是爲了在同一個主機上同時運行多個系統或應用,從而提高系統資源的利用率,並且帶來降低成本、方便管理和容錯容災等好處。 從大類上分,虛擬化技術可分爲基於硬件的虛擬化和基於軟件的虛擬化:

       真正意義上,基於硬件的虛擬化技術不多見,少數如網卡中的單根多IO虛擬化(Single Root I/O Virtualization and Sharing Specification,SR-IOV)等技術。  

       基於軟件的虛擬化從對象所在的層次,又可以分爲應用虛擬化和平臺虛擬化(通常說的虛擬機技術即屬於這個範疇)。其中,前者一般指的是一些 模擬設備或諸如Wine這樣的軟件。平臺虛擬化又可以細分爲如下幾個子類:

       傳統方式是在硬件層面實現虛擬化,需要有額外的虛擬機管理應用和虛擬機操作系統層。

       Docker容器是在操作系統(OS)層面上實現虛擬化直接複用本地主機的操作系統,因此更加輕量級。

 

2. 核心概念和安裝配置

  2.1 核心概念

   1.Docker鏡像(Image)

       Docker鏡像類似於虛擬機鏡像,可以將它理解爲一個只讀的模板。例如,一個鏡像可以包含一個基本的操作系統環境,裏面僅安裝了Apache應用程序(或用戶需要的其他軟件)。可以把它稱爲一個Apache鏡像

       鏡像是創建Docker容器的基礎。通過版本管理和增量的文件系統,Docker提供了一套十分簡單的機制來創建和更新現有的鏡像,用戶甚至可以從網上下載一個已經做好的應用鏡像,並直接使用。

   2.Docker容器(Container)

       Docker容器類似於一個輕量級的沙箱,Docker利用容器來運行和隔離應用。容器是從鏡像創建的應用運行實例。可以將其啓動、開始、停止、刪除,而這些容器都是彼此相互隔離的、互不可見的。可以把容器看做是一個簡易版的Linux系統環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)以及運行在其中的應用程序打包而成的盒子。

       鏡像自身是隻讀的。容器從鏡像啓動的時候,會在鏡像的最上層創建一個可寫層。

  3.Docker倉庫(Repository)

      Docker倉庫類似於代碼倉庫,它是Docker集中存放鏡像文件的場所有時候會看到有資料將Docker倉庫和倉庫註冊服務器(Registry)混爲 一談,並不嚴格區分。實際上,倉庫註冊服務器是存放倉庫的地方,其上往往存放着多個倉庫。每個倉庫集中存放某一類鏡像,往往包括多個鏡像文件,通過不同的標籤(tag)來進行區分。例如存放 Ubuntu操作系統鏡像的倉 庫稱爲Ubuntu倉庫,其中可能包括14.04、12.04等不同版本的鏡像。

       根據所存儲的鏡像公開分享與否,Docker倉庫可以分爲公開倉庫 (Public)和私有倉庫(Private)兩種形式。目前,最大的公開倉庫是官方提供的Docker Hub,其中存放了數量龐大的鏡像供用戶下載。國內不少雲服務提供商(如時速雲、阿里雲等)也提供了倉庫的本地源,可以提供穩定的國內訪問。

       當然,用戶如果不希望公開分享自己的鏡像文件,Docker也支持用戶在本地網絡內創建一個只能自己訪問的私有倉庫。當用戶創建了自己的鏡像之後就可以使用push命令將它上傳到指定的公有或者私有倉庫。這樣用戶下次在另外一臺機器上使用該鏡像時,只需要將其從倉庫上pull下來就可以了。Docker利用倉庫管理鏡像的設計理念與Git非常相似,實際上 在理念設計上借鑑了Git的很多優秀思想。

  2.2 Docker安裝

   MacOS :https://docs.docker.com/docker-for-mac/install/

   Windows : https://docs.docker.com/docker-for-windows/

  ·Docker Platform : 支持在桌面系統或雲平臺安裝Docker;

  ·Docker Hub : 官方提供的雲託管服務,可以提供公有或私有的鏡像倉庫;

  ·Docker Cloud : 官方提供的容器雲服務,可以完成容器的部署與管理, 可以完整地支持容器化項目,還有CI、CD功能;

  ·Docker DataCenter : 提供企業級的簡單安全彈性的容器集羣編排和管理。

   Docker目前只能運行在64位平臺上且要求內核版本不低於3.10,實際上內核越新越好,過低的內核版本容易造成功能不穩定。Docker目前支持的最低Ubuntu版本爲12.04 LTS,但實際上從穩定性上考 慮,推薦至少使用14.04 LTS版本。CentOS系統的要求與Ubuntu情況下類似:64位操作系統,內核版本至少爲3.10。Docker目前支持CentOS 6.5及以後的版本,推薦使用CentOS 7系統。

  本人電腦安裝簡略步驟:

http://localhost/ 打開,看到如下頁面,表示正確install nginx webserver.

命令行下輸入: docker run --help  可查詢docker run 命令所有的參數,其他命令也如此。

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

3. 使用Docker鏡像

       Docker運行容器前需要本地存在對應的鏡像,如果鏡像沒保存在本地,Docker會嘗試先從默認鏡像倉庫下載(默認使用Docker Hub公共註冊服務器中的倉庫),用戶也可以通過配置,使用自定義的鏡像倉庫。鏡像是運行容器的前提,官方的Docker Hub網站已經提供了數十萬個鏡像供大家開放下載。

   docker  pull  [OPTIONS]  NAME[:TAG|@DIGEST]  -------> Pull an image or a repository from a registry,如果不顯式指定TAG,則默認會選擇 latest 標籤,就會下載倉庫中最新版本的鏡像。

       一般來說,鏡像的latest標籤意味着該鏡像的內容會跟蹤最新的非穩定版本而發佈,內容是不穩定的。從穩定性上考慮,不要在生產環境中忽略鏡像的標籤信息或使用默認的 latest 標記的鏡像。如下:

    docker  pull  nodejs:10.11.0  <=====>  docker  pull  registry.hub.docker.com/nodejs:10.11.0

如果從非官方的倉庫下載,則需要在倉庫名稱前指定完整的倉庫地址。docker  pull  hub.c.163.com/public/nodejs:10.11.0

3.1  docker images(獲取鏡像文件)

·Tag: 比如14.04、latest用來標註不同的版本信息。只是標記,並不能標識鏡像內容;

·IMAGE ID(唯一標識鏡像):  如果ID一樣表示它們目前實際上指向同一個鏡像; 它唯一標識了鏡像。在使用鏡像ID的時 候,一般可以使用該ID的前若干個字符組成的可區分串來替代完整的ID。

·created : 說明鏡像最後的更新時間;

·size : 優秀的鏡像往往體積都較小。鏡像大小信息只是表示該鏡像的邏輯體積大小,實際上由於相同的鏡像層本地只會存儲一份,物理上佔用的存儲空間會小於各鏡像的邏輯體積之和。

3.2  docker tag (取別名)

     爲了方便在後續工作中使用特定鏡像,還可以使用docker tag命令來爲本地鏡像任意添加新的標籤。這些myubuntu:latest鏡像的ID跟ubuntu:latest 完全一致。它們實際上指向同一個鏡像文件,只是別名不同而已。docker tag 命令添加的標籤實際上起到了類似鏈接的作用。docker  tag  ubuntu:latest   myubuntu:latest 

 3.3  docker inspect (獲取鏡像的詳細信息)  

     使用 docker inspect  nginx(docker inspect e81eb098537d)命令可以獲取該鏡像的詳細信息,包括製作者、適應架構、各層的數字摘要等。返回的是一個JSON格式的消息,如果我們只要其中一項內容時,可以使用參數 -f 來指定,例如,

     獲取鏡像的Architecture : docker inspect nginx( or e81eb098537d)  -f  {{".Architecture"}}

 3.4  docker history (獲取鏡像的歷史信息)  

     使用history子命令,該命令將列出各層的創建信息。docker history nginx

      

3.5  docker rmi (刪除鏡像)

     使用docker rmi命令可以刪除鏡像,命令格式爲docker rmi  IMAGE [IMAGE...],其中IMAGE可以爲標籤或ID。當同一個鏡像擁有多個標籤的時候,docker rmi命令只是刪除該鏡像多個標籤中的指定標籤而已,並不影響鏡像文件。刪除標籤爲hello-world:latest的鏡像,由於該鏡像沒有額外的標籤指向它,執行docker rmi命令,可以看出它會刪除這個鏡像文件的所有層.

     要想強行刪除鏡像,可以使用 -f 參數。通常並不推薦使用-f參數來強制刪除一個存在容器依賴的鏡像。 正確的做法是,先刪除依賴該鏡像的所有容器,再來刪除鏡像。

       

3.6  創建鏡像:創建鏡像的方法主要有三種:基於已有鏡像的容器創建、基於本地模板導入、基於Dockerfile創建(後續詳解)。

3.6.1 基於已有鏡像的容器創建

該方法主要是使用docker commit命令。命令格式爲docker   commit[OPTIONS]CONTAINER[REPOSITORY[:TAG]],主要選項包括:

       ·-a,--author="":作者信息;

       ·-c,--change=[]:提交的時候執行 Dockerfile指令,包括CMD| ENTRYPOINT|ENV|EXPOSE|LABEL|ONBUILD|USER|

VOLUME| WORKDIR 等;

        ·-m,--message="":提交消息;

        ·-p,--pause=true:提交時暫停容器運行。

Tip : 創建鏡像 和 docker tag 打標籤的別混淆

3.6.2   基於本地模板導入

        docker  import命令。命令格式爲 docker  import [OPTIONS]  file|URL|- [ REPOSITORY [:TAG] ]。要直接導入一個鏡像,可以使用OpenVZ提供的模板來創建,或者用其他 已導出的鏡像模板來創建。例如:

   cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04

3.7  存出、載入、上傳鏡像

     如果要導出鏡像到本地文件,可以使用docker save命令    docker save -o nginx.tar nginx : latest

     可以使用docker load將導出的tar文件再導入到本地鏡像庫     docker load < nginx.tar <==> docker load --input nginx.tar

     可以使用docker push命令上傳鏡像到倉庫,默認上傳到Docker Hub官方倉庫(需要登錄)。命令格式:

docker push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]

4.  操作docker 容器

        容器是鏡像的一個運行實例。所不同的是,鏡像是靜態的只讀文件,而容器帶有運行時需要的可寫文件層。如果認爲虛擬機是模擬運行的一整套操作系統(包括內核、應用運行 態環境和其他系統環境)和跑在上面的應用,那麼Docker容器就是獨立運行 的一個(或一組)應用,以及它們必需的運行環境。

4.1  創建容器

4.1.1  可以使用docker create命令新建一個容器

       使用docker create命令新建的容器處於停止狀態,可以使用docker start命令來啓動它。create命令run命令支持的選項都十分複雜,主要包括如下幾大類:與容器運行模式相關、與容器和環境配置相關、與容器資源限制和安全保護相關。

        除了創建容器後通過start命令來啓動,也可以直接新建並啓動容器。新建並啓動容器: 所需要的命令主要爲docker run,等價於先執行docker create命令,再執行docker start命令。利用docker run來創建並啓動容器時,Docker在後臺運行的標準操作包括:

  • 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載;
  • 利用鏡像創建一個容器,並啓動該容器;
  • 分配一個文件系統給容器,並在只讀的鏡像層外面掛載一層可讀寫層;
  • 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中;
  • 從網橋的地址池配置一個IP地址給容器;
  • 執行用戶指定的應用程序;
  • 執行完畢後容器被自動終止。 
docker run -it ubuntu:14.04 /bin/bash 

-t : 讓Docker分配一個僞終端(pseudo-tty)並綁定到容器的標準輸入上。     - i : 讓容器的標準輸入保持打開。

某些時候,執行docker run會出錯,因爲命令無法正常執行容器會直接退 出,此時可以查看退出的錯誤代碼。 默認情況下,常見錯誤代碼包括:

·125: Docker daemon執行出錯,例如指定了不支持的Docker命令參 數;

·126:所指定命令無法執行,例如權限出錯;

·127:容器內命令無法找到。 命令執行後出錯,會默認返回錯誤碼。

4.1.2  終止容器

     更多的時候,需要讓Docker容器在後臺以守護態(Daemonized)形式運行。此時,可以通過添加 -d 參數來實現。可以用docker ps -qa命令看到所有容器的ID。

     可以使用docker stop來終止一個運行中的容器。該命令的格式爲docker stop[-t|--time[=10]][CONTAINER...]。首先向容器發送SIGTERM信號,等待一段超時時間(默認爲10秒)後, 再發送SIGKILL信號來終止容器。

  docker stop containerID

     docker kill 命令會直接發送SIGKILL信號來強行終止容器。當Docker容器中指定的應用終結時,容器也會自動終止。例如對 於上一節中只啓動了一個終端的容器,用戶通過exit命令或Ctrl+d來退出終端時,所創建的容器立刻終止,處於stopped狀態

     docker restart 命令會將一個運行態的容器先終止,然後再重新啓動。

4.2  進入容器

     進入容器進行操作有多種方法,包括使用官方的 attach 或 exec命令,以及第三方的nsenter工具等。

4.2.1 attach方法

       

  • --detach-keys[=[]]:指定退出attach模式的快捷鍵序列,默認是CTRL-p  CTRL-q;
  • --no-stdin=true|false:是否關閉標準輸入,默認是保持打開;
  • --sig-proxy=true|false:是否代理收到的系統信號給應用進程,默認爲 true。

      但是使用attach命令有時候並不方便。當多個窗口同時用attach命令連到同一個容器的時候,所有窗口都會同步顯示。當某個窗口因命令阻塞時,其他窗口也無法執行操作了。

4.2.2  exec命令

通過指定 -it 參數來保持標準輸入打開,並且分配一個僞終端。通過exec 命令對容器執行操作是最爲推薦的方式。

  • -i,--interactive=true|false:打開標準輸入接受用戶輸入命令,默認爲false;
  • --privileged=true|false:是否給執行命令以高權限,默認爲false;
  • -t,--tty=true|false:分配僞終端,默認爲false; ·-u,--user="":執行命令的用戶名或ID。

4.2.3 nsenter工具

4.3 刪除容器

默認情況下,docker rm命令只能刪除處於終止或退出狀態的容器,並不能刪除還處於運行狀態的容器。如果要直接刪除一個運行中的容器,可以添加 -f 參數。Docker會先發送 SIGKILL信號給容器,終止其中的應用then強行刪除。docker rm -f containerID

4.4 導入導出容器

       某些時候,需要將容器從一個系統遷移到另外一個系統,此時可以使用 Docker的導入和導出功能。這也是Docker自身提供的一個重要特性。

       1.導出容器是指導出一個已經創建的容器到一個文件,不管此時這個容器 是否處於運行狀態,可以使用docker export命令,該命令的格式爲 docker export [-o|--output[=""]] CONTAINER。其中,可以通過-o選項來指定導出的tar 文件名,也可以直接通過重定向來實現。可將導出的tar文件傳輸到其他機器上,然後再通過導入命令導入到系統中,從而實現容器的遷移

   $ docker export -o test_for_run.tar ce5
   $ ls
   test_for_run.tar
   $ docker export e81 >test_for_stop.tar
   $ ls
   test_for_run.tar test_for_stop.tar

     2.導出的文件又可以使用docker import命令導入變成鏡像,該命令格式爲

      docker import  [OPTIONS]  file|URL|-  [REPOSITORY[:TAG]]

   $ docker import test_for_run.tar - test/ubuntu:v1.0
   $ docker images
   REPOSITORY        TAG      IMAGE ID       CREATED             VIRTUAL SIZE
   test/ubuntu       v1.0     9d37a6082e97   About a minute ago     171.3 MB

       既可以使用docker load命令來導入鏡像存儲文件到本地鏡像庫, 也可以使用docker import命令來導入一個容器快照到本地鏡像庫。 這兩者的區別在於:

5. 訪問Docker Hub庫

5.1 初識Docker Hub

      根據是否爲官方提供,可將這些鏡像資源分爲兩類

       一種是類似centos這樣的基礎鏡像,稱爲基礎或根鏡像。這些鏡像是由Docker公司創建、驗證、 支持、提供。這樣的鏡像往往使用單個單詞作爲名字。

      另一種類型,比如ansible/centos7-ansible鏡像,它是由Docker用戶ansible創建並維護的,帶有用戶名稱爲前綴,表明是某用戶下的某倉庫。可 以通過用戶名稱前綴user_name/鏡像名來指定使用某個用戶提供的鏡像。

另外,在查找的時候通過- s N參數可以指定僅顯示評價爲N星以上的鏡像。

    1. docker search  命令來查找官方倉庫中的鏡像

    2. docker pull  命令來將它下載到本地

    3. docker push 命令來將本地鏡像推送到Docker Hub。

     自動創建允許用戶通過Docker Hub指定跟蹤一個目標網站(目前支持 GitHub或BitBucket)上的項目,一旦項目發生新的提交,則自動執行創建。要配置自動創建,包括如下的步驟:

  •  容器快照文件將丟棄所有的歷史記錄和元數據信息 (即僅保存容器當時的快照狀態),
  • 鏡像存儲文件將保存完整記錄,體積也更大。此外,從容器快照文件導入時可以重新指定標籤等元數據信息。
  •  1) 創建並登錄Docker Hub,以及目標網站;*在目標網站中連接帳戶到Docker Hub;
  • 2) 在Docker Hub中配置一個“自動創建”;
  • 3) 選取一個目標網站中的項目(需要含Dockerfile)和分支;
  • 4) 指定Dockerfile的位置,並提交創建。
  • 5) 可以在Docker Hub的“自動創建”頁面中跟蹤每次創建的狀態。

  5.2 搭建本地私有倉庫

       在本地將啓動一個私有倉庫服務,監聽端口爲5000。使用registry鏡像創建私有倉庫   docker run -d -p 5000:5000 registry  。默認情況下,會將倉庫創建在容器的/ tmp/registry目錄下。可以通過- v參數來將鏡像文件存放在本地的指定路徑。 例如下面的例子將上傳的鏡像放到/ opt/data/registry目錄:

        docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry

       比較新的Docker版本對安全性要求較高,會要求倉庫支持SSL/TLS證書。 對於內部使用的私有倉庫,可以自行配置證書或關閉對倉庫的安全性檢查。修改Docker daemon的啓動參數,添加如下參數,表示信任這個私 有倉庫,不進行安全證書檢查:

   DOCKER_OPTS="--insecure-registry 10.0.2.2:5000"

      如果要使用安全證書,用戶也可以從較知名的CA服務商(如verisign) 申請公開的SSL/TLS證書,或者使用openssl等軟件來自行生成。

6. Docker數據管理

       生產環境中使用Docker的過程中,往往需要對數據進行持久化,或者需要在多個容器之間進行數據共享,這必然涉及容器的數據管理操作。 容器中管理數據主要有兩種方式:

  • 數據卷(Data Volumes): 容器內數據直接映射到本地主機環境;
  • 數據卷容器(Data Volume Containers): 使用特定容器維護數據卷。

6.1 數據卷

        在生產環境中,筆者推薦在使用數據卷或數據卷容器之外,定期將主機 的本地數據進行備份,或者使用支持容錯的存儲系統,包括RAID或分佈式文件系統如Ceph、GPFS、HDFS等。數據卷是一個可供容器使用的特殊目錄,它將主機操作系統目錄直接映射進容器,類似於Linux中的mount操作。

  • 數據卷可以在容器之間􏰀享和重用,容器間傳遞數據將變得高效方便;
  • 對數據卷內數據的修改會立馬生效,無論是容器內操作還是本地操作;
  • 對數據卷的更新不會影響鏡像,解耦了應用和數據;
  • 卷會一直存在,直到沒有容器使用,可以安全地卸載它。

1.在容器內創建一個數據卷

     在用docker run命令的時候,使用- v標記可以在容器內創建一個數據卷。 多次重複使用-v標記可以創建多個數據卷。下面使用training/webapp鏡像創建一個web容器,並創建一個數據卷掛載 到容器的/webapp目錄:

   $ docker run -d -P --name web -v /webapp training/webapp python app.py

       注意: -P是將容器服務暴露的端口,是自動映射到本地主機的臨時端口。

2.掛載一個主機目錄作爲數據卷

        使用-v標記也可以指定掛載一個本地的已有目錄到容器中去作爲數據卷 (推薦方式)。

   $ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

       上面的命令加載主機的/ src/webapp目錄到容器的/ opt/webapp目錄。這個功能在進行測試的時候十分方便,比如用戶可以將一些程序或數據放到本地目錄中,然後在容器內運行和使用。另外,本地目錄的路徑必須是 絕對路徑,如果目錄不存在Docker,會自動創建。

        Docker掛載數據卷的默認權限是讀寫(rw),用戶也可以通過 ro指定爲只讀:

   $ docker run -d -P --name web -v /src/webapp:/opt/webapp:ro  training/webapp python app.py

       加了:ro 之後,容器內對所掛載數據卷內的數據就無法修改了。

3.掛載一個本地主機文件作爲數據卷

         -v標記也可以從主機掛載單個文件到容器中作爲數據卷(不推薦)。

   $ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash  這樣就可以記錄在容器輸入過的命令歷史。
   注意如果直接掛載一個文件到容器,使用文件編輯工具,包括vi或者sed--in- place的時候,可能會造成文件inode的改變,從Docker 1.1.0起,這會導致報錯 誤信息。所以推薦的方式是直接掛載文件所在的目錄。

6.2 數據卷容器

       如果用戶需要在多個容器之間共享一些持續更新的數據最簡單的方式是使用數據卷容器。數據卷容器也是一個容器,但是它的目的是專門用來提供數據卷供其他容器掛載。

       創建一個數據卷容器dbdata,並在其中創建一個數據卷掛載到 /dbdata:

   $ docker run -it -v /dbdata --name dbdata ubuntu
   root@3ed94f279b6f:/# ls
   bin  boot  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run sbin  srv  sys  tmp  usr    
   var

       在其他容器中使用--volumes-from來掛載dbdata容器中的數據卷,例如創建db1和db2兩個容器,並從dbdata容器掛載數據卷:

   $ docker run -it --volumes-from dbdata --name db1 ubuntu
   $ docker run -it --volumes-from dbdata --name db2 ubuntu

      容器db1和db2都掛載同一個數據捲到相同的 /dbdata 目錄。三個容器任何一方在該目錄下的寫入,其他容器都可以看到。       

      可以多次使用--volumes-from參數來從多個容器掛載多個數據卷。還可以從其他已經掛載了容器卷的容器來掛載數據卷。使用--volumes-from參數所掛載數據卷的容器自身並不需要保持在運行狀態。如果刪除了掛載的容器(包括dbdata、db1和db2),數據卷並不會被自動刪除。如果要刪除一個數據卷,必須在刪除最後一個還掛載着它的容器時 顯式使用 docker rm-v 命令來指定同時刪除關聯的容器。

6.3 利用數據卷容器來遷移數據

1.備份

       使用下面的命令來備份dbdata數據卷容器內的數據卷:

   $ docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata

       這個命令稍微有點複雜,具體分析一下。首先利用ubuntu鏡像創建了一個容器worker。使用--volumes-from dbdata參數來讓worker容器掛載dbdata容器的數據卷(即dbdata數據卷); 

     使用-v $(pwd):/backup參數 來掛載本地的當前目錄到worker容器的/backup目錄。

      worker容器啓動後,使用了tar cvf/backup/backup.tar/dbdata命令來將/ dbdata下內容備份爲容器內的/ backup/backup.tar,即宿主主機當前目錄下的backup.tar。

2.恢復

       如果要將數據恢復到一個容器,可以按照下面的步驟操作。首先創建一個帶有數據卷的容器dbdata2:

   $ docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

       然後創建另一個新的容器,掛載dbdata2的容器,並使用untar解壓備份文件到所掛載的容器卷中:

   $ docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf  /backup/backup.tar

7. 端口映射與容器互聯 *****

       多個容器之間有能夠互相訪問到對方的服務。除了通過網絡訪問外,Docker還提供了兩個很方便的功能來滿足服務訪問的基本需求:一個是允許映射容器內應用的服務端口到本地宿主主機; 另 一個是互聯機制實現多個容器間通過容器名來快速訪問。 

 7.1 端口映射實現訪問容器

      1.從外部訪問容器應用

       在啓動容器的時候,如果不指定對應的參數,在容器外部是無法通過網絡來訪問容器內的網絡應用和服務的。 當容器中運行一些網絡應用,要讓外部訪問這些應用時,可以通過 -P 或 -p參數來指定端口映射。當使用-P(大寫的)標記時,Docker會隨機映射一個 49000~49900的端口到內部容器開放的網絡端口:

   $ docker run -d -P training/webapp python app.py
   $ docker ps -l
   CONTAINER ID  IMAGE         COMMAND       CREATED        STATUS        PORTS                   NAMES
   bc533791f3f5  py_dem:latest python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp py_demo 

       此時,可以使用docker ps看到,本地主機的49155被映射到了容器的5000端口。訪問宿主主機的49155端口即可訪問容器內Web應用提供的界面。同樣,可以通過docker logs命令來查看應用的信息:

   $ docker logs -f nostalgic_morse
   * Running on http://0.0.0.0:5000/
   10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
   10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -

        -p(小寫的)可以指定要映射的端口,並且在一個指定端口上只可以綁定一個容器。支持的格式有

        IP:HostPort: ContainerPort  | IP : : ContainerPort | HostPort:ContainerPort。

      2.映射所有接口地址

      使用HostPort:ContainerPort格式將本地的5000端口映射到容器的5000端口,可以執行:

   $ docker run -d -p 5000:5000 training/webapp python app.py

     此時默認會綁定本地所有接口上的所有地址。多次使用 -p標記可以綁定多個端口。例如:

   $ docker run -d -p 5000:5000  -p 3000:80 training/webapp python app.py

     3.映射到指定地址的指定端口

     可以使用IP:HostPort:ContainerPort格式指定映射使用一個特定地址,比如localhost地址127.0.0.1:

     $ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

     4.映射到指定地址的任意端口

    使用IP::ContainerPort綁定localhost的任意端口到容器的5000端口,本地主機會自動分配一個端口:

   $ docker run -d -p 127.0.0.1::5000 training/webapp python app.py

     還可以使用udp標記來指定udp端口:
      $ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

     5.查看映射端口配置
     使用docker port命令來查看當前映射的端口配置,也可以查看到綁定的地址:

   $ docker port py_demo 5000
   127.0.0.1:49155.

      注意: 容器有自己的內部網絡和IP地址,使用docker inspect+容器ID可以獲取容器的具體信息。

7.2 互聯機制實現便捷互訪

       容器的互聯(linking)是一種讓多個容器中應用進行快速交互的方式。 它會在源和接收容器之間創建連接關係,接收容器可以通過容器名快速訪問到源容器,而不用指定具體的IP地址。

       1.自定義容器命名

       連接系統依據容器的名稱來執行。因此,首先需要定義一個好記的容器名字。 雖然當創建容器的時候,系統默認會分配一個名字,但自定義容器名字有兩個好處:

       使用--name標記可以爲容器自定義命名:

  • 自定義的命名比較好記,比如一個Web應用容器,我們可以給它起名叫 web,一目瞭然;
  • 當要連接其他容器時,即便重啓,也可以使用容器名而不用改變,比如 連接web容器到db容器。
  •  

       $ docker run -d -P --name web test/demo python app.py

       使用docker ps來驗證設定的命名:

   $ docker ps -l
   CONTAINER ID  IMAGE            COMMAND        CREATED       STATUS        PORTS                    NAMES
   aed84ee21bde  test/demo:latest python app.py  12 hours ago  Up 2 seconds  0.0.0.0:49154->5000/tcp  web

      也可以使用docker inspect來查看容器的名字: $ docker inspect -f "{{.Name}}" aed84ee21bde  ----->  /web

       容器的名稱是唯一的。如果已經命名了一個叫web的容器,當你要再次使用web這個名稱的時候,需要先用docker rm來刪除之前創建的同名容器。

       在執行docker run的時候如果添加 --rm 標記,則容器在終止後會立刻刪除。注意,--rm和 -d 參數不能同時使用

       2.容器互聯

      使用--link參數可以讓容器之間安全地進行交互。 下面先創建一個新的數據庫容器:

   $ docker run -d --name db training/db2

       刪除之前創建的web容器: $ docker rm -f web   然後創建一個新的web容器,並將它連接到db容器:
       $ docker run -d -P --name web --link db:db training/webapp python app.py

       此時,db容器和web容器建立互聯關係:  --link參數的格式爲 --link name:alias,其中name是要連接的容器名稱,alias是這個連接的別名。使用docker ps來查看容器的連接,如下所示:

 $ docker ps
CONTAINER ID IMAGE         COMMAND      CREATED      STATUS    PORTS     NAMES
349169744e49 training/db2:latest su postgres -c '/usr    Up About a minute  5432/tcp  db, web/db
aed84ee21bde training/webapp:latest python app.py Up 2 minute  0.0.0.0:49154->5000/tcp 16 hours ago  web

       Docker相當於在兩個互聯的容器之間創建了一個虛機通道,而且不用映射它們的端口到宿主主機上。在啓動db容器的時候並沒有使用 -p 和 -P 標記, 從而避免了暴露數據庫服務端口到外部網絡上。Docker通過兩種方式爲容器公開連接信息:

  • 更新環境變量;
  • 更新/etc/hosts文件。

       Docker容器服務訪問的兩大基本操作--基礎的容器端口映射機制和 容器互聯機制。同時,Docker目前可以成熟地支持Linux系統自帶的網絡服務和功能,這既可以利用現有成熟的技術提供穩定支持,又可以實現快速的高性能轉發。

       在生產環境中,網絡方面的需求更加複雜多變,包括跨主機甚至跨數據中心的通信,這時候往往就需要引入額外的機制,例如SDN(軟件定義網絡) 或NFV(網絡功能虛擬化)的相關技術。

8. 使用Dockerfile創建鏡像 

      Dockerfile是一個文本格式的配置文件,用戶可以使用Dockerfile來快速創建自定義的鏡像。

8.1 基本結構

      Dockerfile由一行行命令語句組成,並且支持以#開頭的註釋行。 一般而言,Dockerfile分爲四部分:基礎鏡像信息、維護者信息、鏡像操作指令和容器啓動時執行指令。例如:

   # This Dockerfile uses the ubuntu image
   # VERSION 2 - EDITION 1
   # Author: docker_user
   # Command format: Instruction [arguments / command] ..
   # Base image to use, this must be set as the first line
   FROM ubuntu
   # Maintainer: docker_user <docker_user at email.com> (@docker_user)
   MAINTAINER docker_user [email protected]
   # Commands to update the image
   RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
   RUN apt-get update && apt-get install -y nginx
   RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
   # Commands when creating a new container
   CMD /usr/sbin/nginx

       其中,一開始必須指明所基於的鏡像名稱,接下來一般是說明維護者信 息。後面則是鏡像操作指令,例如RUN指令,RUN指令將對鏡像執行跟隨的命 令。每運行一條RUN指令,鏡像就添加新的一層,並提交。最後是CMD指令,用來指定運行容器時的操作命令。下面是Docker Hub上兩個熱門鏡像的Dockerfile的例子,可以幫助讀者對 Dockerfile結構有個基本的認識。

       第一個例子是在debian:jessie基礎鏡像基礎上安裝Nginx環境,從而創建 一個新的nginx鏡像:

   FROM debian:jessie
   MAINTAINER NGINX Docker Maintainers "[email protected]"
   ENV NGINX_VERSION 1.10.1-1~jessie
   RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC64107
       9A6ABABF5BD827BD9BF62 \
           && echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list \
           && apt-get update \
           && apt-get install --no-install-recommends --no-install-suggests -y \
           ca-certificates \
           nginx=${NGINX_VERSION} \
           nginx-module-xslt \
           nginx-module-geoip \
           nginx-module-image-filter \
           nginx-module-perl \
           nginx-module-njs \
           gettext-base \
           && rm -rf /var/lib/apt/lists/*
   # forward request and error logs to docker log collector
   RUN ln -sf /dev/stdout /var/log/nginx/access.log \
       && ln -sf /dev/stderr /var/log/nginx/error.log
   EXPOSE 80 443
   CMD ["nginx", "-g", "daemon off;"]

       第二個例子是基於buildpack-deps:jessie-scm基礎鏡像,安裝Golang相關環境,製作一個GO語言的運行環境鏡像:

   FROM buildpack-deps:jessie-scm
   # gcc for cgo
   RUN apt-get update && apt-get install -y --no-install-recommends \
       g++ \
       gcc \
       libc6-dev \
       make \
       && rm -rf /var/lib/apt/lists/*
   ENV GOLANG_VERSION 1.6.3
   ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
   ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd
       7561275a87aeb
   RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
       && echo "$GOLANG_DOWNLOAD_SHA256  golang.tar.gz" | sha256sum -c - \
       && tar -C /usr/local -xzf golang.tar.gz \
       && rm golang.tar.gz
   ENV GOPATH /go
   ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
   RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
   WORKDIR $GOPATH
   COPY go-wrapper /usr/local/bin/

8.2 基本指令

1.FROM

      指定所創建鏡像的基礎鏡像,如果本地不存在,則默認會去Docker Hub 下載指定鏡像。格式爲

      FROM <image>,或FROM <image>:<tag>,或FROM <image>@<digest>

     任何Dockerfile中的第一條指令必須爲FROM指令。並且,如果在同一個Dockerfile中創建多個鏡像,可以使用多個FROM指令(每個鏡像一次)。

2.MAINTAINER

       指定維護者信息,格式爲MAINTAINER<name>。例如:

   MAINTAINER [email protected]

       該信息會寫入生成鏡像的Author屬性域中。

3.RUN

       運行指定命令。 格式爲RUN <command>或 RUN["executable","param1","param2"]

      注意,後一個指令會被解析爲Json數組,因此必須用雙引號。 前者默認將在shell終端中運行命令,即/ bin/sh-c;後者則使用exec執行,不會啓動shell環境。 指定使用其他終端類型可以通過第二種方式實現,例如RUN["/bin/bash","-c","echo hello"]。 每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可以使用 \ 來換行。例如:

   RUN apt-get update \
           && apt-get install -y libsnappy-dev zlib1g-dev libbz2-dev \
           && rm -rf /var/cache/apt

4.CMD

    CMD指令用來指定啓動容器時默認執行的命令。它支持三種格式:

  • ·CMD["executable","param1","param2"]使用 exec執行,是推薦使用的方式;
  • ·CMD command param1 param2在/bin/sh中執行,提供給需要交互的應用;
  • ·CMD["param1","param2"]提供給 ENTRYPOINT的默認參數。

   每個Dockerfile只能有一條CMD命令。如果指定了多條命令,只有最後一 條會被執行。如果用戶啓動容器時手動指定了運行的命令(作爲run的參數),則會覆蓋掉CMD指定的命令。

5.LABEL

        LABEL指令用來指定生成鏡像的元數據標籤信息。 格式爲LABEL<key>=<value><key>=<value><key>=<value>... 

   LABEL version="1.0"
   LABEL description="This text illustrates \ that label-values can span multiple lines."

6.EXPOSE

      聲明鏡像內服務所監聽的端口。 格式爲EXPOSE<port>[<port>...]。 例如:  

   EXPOSE 22 80 8443
   注意,該指令只是起到聲明作用,並不會自動完成端口映射。在啓動容器時需要使用-P,Docker主機會自動分配一個宿主機的臨時端 口轉發到指定的端口;使用-p,則可以具體指定哪個宿主機的本地端口會映射過來。

7.ENV

     指定環境變量,在鏡像生成過程中會被後續RUN指令使用,在鏡像啓動 的容器中也會存在。格式爲ENV <key> <value>或ENV <key>=<value>... 例如:

   ENV PG_MAJOR 9.3
   ENV PG_VERSION 9.3.4
   RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/
       postgress && ...
   ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

      指令指定的環境變量在運行時可以被覆蓋掉,如docker run  --env <key>=<value> built_image。

8.ADD

       該命令將複製指定的<src>路徑下的內容到容器中的<dest>路徑下。 格式爲ADD  <src>  <dest>

       其中<src>可以是Dockerfile所在目錄的一個相對路徑(文件或目錄),也 可以是一個URL,還可以是一個tar文件(如果爲tar文件,會自動解壓到<dest> 路徑下)。<dest>可以是鏡像內的絕對路徑,或者相對於工作目錄 (WORKDIR)的相對路徑。 路徑支持正則格式,例如:

   ADD *.c /code/

9.COPY

      格式爲COPY<src><dest>。 複製本地主機的<src>(爲Dockerfile所在目錄的相對路徑、文件或目錄)下的內容到鏡像中的<dest>下。目標路徑不存在時,會自動創建。路徑同樣支持正則格式。當使用本地目錄爲源目錄時,推薦使用COPY。

10.ENTRYPOINT

      指定鏡像的默認入口命令,該入口命令會在啓動容器時作爲根命令執 行,所有傳入值作爲該命令的參數。  支持兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"](exec調用執行);
  • ENTRYPOINT command param1 param2(shell中執行)。

     此時,CMD指令指定值將作爲根命令的參數。 每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最後一個有效。在運行時,可以被-- entrypoint參數覆蓋掉,如docker run--entrypoint。

11.VOLUME

    創建一個數據卷掛載點。格式爲VOLUME ["/data"]。 可以從本地主機或其他容器掛載數據卷,一般用來存放數據庫和需要保存的數據等。

12.USER

       指定運行容器時的用戶名或UID,後續的RUN等指令也會使用指定的用戶身份。格式爲USER daemon。 當服務不需要管理員權限時,可以通過該命令指定運行用戶,並且可以在之前創建所需要的用戶。例如:

   RUN groupadd -r postgres && useradd -r -g postgres postgres

      要臨時獲取管理員權限可以使用gosu或sudo。

13.WORKDIR

        爲後續的RUN、CMD和 指令配置工作目錄。

        ENTRYPOINT 格式爲WORKDIR/path/to/workdir。可以使用多個WORKDIR指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如:

   WORKDIR /a
   WORKDIR b
   WORKDIR c
   RUN pwd

則最終路徑爲 /a/b/c。

14.ARG

      指定一些鏡像內使用的參數(例如版本號信息等),這些參數在執行 docker build命令時才以-- build-arg<varname>=<value>格式傳入。格式爲ARG<name>[=<default value>]。則可以用docker build--build-arg<name>=<value>.來指定參數值。

15.ONBUILD

       配置當所創建的鏡像作爲其他鏡像的基礎鏡像時,所執行的創建操作指令。格式爲ONBUILD[INSTRUCTION]。 例如,Dockerfile使用如下的內容創建了鏡像 image-A:

   [...]
   ONBUILD ADD . /app/src
   ONBUILD RUN /usr/local/bin/python-build --dir /app/src
   [...]

       如果基於image-A創建新的鏡像時,新的Dockerfile中使用FROM image-A 指定基礎鏡像,會自動執行ONBUILD指令的內容,等價於在後面添加了兩條 指令:

   FROM image-A
   #Automatically run the following
   ADD . /app/src
   RUN /usr/local/bin/python-build --dir /app/src

       使用ONBUILD指令的鏡像,推薦在標籤中註明,例如ruby:1.9- onbuild。

16.STOPSIGNAL

       指定所創建鏡像啓動的容器接收退出的信號值。例如: STOPSIGNAL signal

17.HEALTHCHECK

       配置所啓動容器如何進行健康檢查(如何判斷健康與否),自Docker 1.12開始支持。格式有兩種:

  • HEALTHCHECK[OPTIONS]CMD command:根據所執行命令返回值是否 爲0來判斷;
  • HEALTHCHECK NONE:禁止基礎鏡像中的健康檢查。

     OPTION支持: ·--interval=DURATION(默認爲:30s):過多久檢查一次; ·--timeout=DURATION(默認爲:30s):每次檢查等待結果的超時; ·--retries=N(默認爲:3):如果失敗了,重試幾次才最終確定失敗。

18.SHELL

     指定其他命令使用shell時的默認shell類型。 默認值爲["/bin/sh","-c"]。

注意: 對於Windows系統,建議在Dockerfile開頭添加#escape=`來指定轉義信 息。

 8.3 創建鏡像

       編寫完成Dockerfile之後,可以通過docker build命令來創建鏡像。

       基本的格式爲docker build[選項]內容路徑,該命令將讀取指定路徑下 (包括子目錄)的Dockerfile,並將該路徑下的所有內容發送給 Docker服務端,由服務端來創建鏡像。因此除非生成鏡像需要,否則一般建議放置 Dockerfile的目錄爲空目錄。有兩點經驗:

  • 如果使用非內容路徑下的Dockerfile,可以通過 -f 選項來指定其路徑。
  • 要指定生成鏡像的標籤信息,可以使用 -t 選項。

    例如,指定Dockerfile所在路徑爲/ tmp/docker_builder/,並且希望生成 鏡像標籤爲build_repo/first_image,可以使用下面的命令:

   $ docker build -t build_repo/first_image /tmp/docker_builder/

    使用.dockerignore文件 可以通過.dockerignore文件(每一行添加一條匹配模式)來讓 Docker忽略匹配模式路徑下的目錄和文件。例如:

   # comment
       */temp*
       */*/temp*
       tmp?
       ~*

 建議讀者在生成鏡像過程 中,嘗試從如下角度進行思考,完善所生成的鏡像。

  • 精簡鏡像用途:  儘量讓每個鏡像的用途都比較集中、單一,避免構造大而複雜、多功能的鏡像;
  • 選用合適的基礎鏡像:  過大的基礎鏡像會造成生成臃腫的鏡像,一般推 薦較爲小巧的debian鏡像;
  • 提供足夠清晰的命令註釋和維護者信息:  Dockerfile也是一種代碼,需要 考慮方便後續擴展和他人使用;
  • 正確使用版本號:  使用明確的版本號信息,如1.0,2.0,而非latest, 將避免內容不一致可能引發的慘案;
  • 減少鏡像層數:  如果希望所生成鏡像的層數儘量少,則要儘量合併指 令,例如多個RUN指令可以合併爲一條;
  • 及時刪除臨時文件和緩存文件:  特別是在執行apt-get指令後,/var/cache/ apt下面會緩存一些安裝包;
  • 提高生成􏰀度:  如合理使用緩存,減少內容目錄下的文件,或使 用.dockerignore文件指定等;
  • 調整合理的指令順序:  在開啓緩存的情況下,內容不變的指令儘量放在 前面,這樣可以儘量複用;
  • 減少外部源的干擾:  如果確實要從外部引入數據,需要指定持久的地 址,並帶有版本信息,讓他人可以重複而不出錯。

9. 實戰集錦

第九章只是針對這本書中涉及到的做個簡單的簡介,具體的內容以及想深入瞭解可以自行學習。

9.1 操作系統

       目前常用的Linux發行版主要包括Debian/Ubuntu系列和CentOS/Fedora系列。前者以自帶軟件包版本較新而出名;後者則宣稱運行更穩定一些。選擇哪個操作系統取決於讀者的具體需求。同時,社區還推出了完全基於Docker 的Linux發行版CoreOS。 使用Docker,只需要一個命令就能快速獲取一個Linux發行版鏡像,這是以往包括各種虛擬化技術都難以實現的。這些鏡像一般都很精簡,但是可以支持完整Linux系統的大部分功能。帶有OFFICIAL標記說明是官方鏡像。

         3.2 Ubuntu:是一個以桌面應用爲主的GNU/Linux操作系統,與Debian的不同在於它每6個月會發佈一個新版本,每2年會推

         出一個長期支持(LongTerm Support,LTS)版本,一般支持3年。

  1.  BusyBox是一個集成了一百多個最常用Linux命令和工具(如 cat、echo、grep、mount、telnet等)的精簡工具箱,它只有幾 MB的大小, 很方便進行各種快速驗證,被譽爲“Linux系統的瑞士軍刀”。BusyBox可運 行於多款POSIX環境的操作系統中,如Linux(包括 Android)、Hurd、FreeBSD等。

    $ docker pull busybox:latest
    $ docker run –it busybox
    
  2. Alpine操作系統是一個面向安全的輕型Linux發行版。它不同於通常的 Linux發行版,Alpine採用了musl libc和BusyBox以減小系統的體積和運行時資源消耗,但功能上比BusyBox又完善得多,因此得到開源社區越來越多的青 睞。在保持瘦身的同時,Alpine還提供了自己的包管理工具apk,可以通過https://pkgs.alpinelinux.org/packages查詢包信息,也可以通過apk命令直接查 詢和安裝各種軟件。Alpine Docker鏡像也繼承了Alpine Linux發行版的這些優勢。相比於其他 Docker鏡像,它的容量非常小,僅僅只有5MB左右(Ubuntu系列鏡像接近 200MB),且擁有非常友好的包管理機制。官方鏡像來自docker-alpine項目。

  3. Debian/Ubuntu:Debian和Ubuntu都是目前較爲流行的Debian系的服務器操作系統,十分適合研發場景。Docker Hub上提供了官方鏡像,國內各大容器雲服務也基本 都提供了相應的支持。

    3.1 Debian系統

           Debian是由GPL和其他自由軟件許可協議授權的自由軟件組成的操作系 統,由Debian Project組織維護。Debian計劃是一個獨立、分散的組織,由 3000個志願者組成,接受世界多個非盈利組織的資金支持,Software in the Public Interest提供支持並持有商標作爲保護機構。Debian以其堅守Unix和自 由軟件的精神,以及給予用戶的衆多選擇而聞名。現在Debian包括了超過 25000個軟件包並支持12個計算機系統結構。

          作爲一個大的系統組織框架,Debian下面有多種不同操作系統核心的分 支計劃,主要爲採用Linux核心的Debian GNU/Linux系統,其他還有采用GNU Hurd核心的Debian GNU/Hurd系統、採用FreeBSD核心的Debian GNU/ kFreeBSD系統,以及採用NetBSD核心的Debian GNU/NetBSD系統,甚至還有 利用Debian的系統架構和工具,採用OpenSolaris核心構建而成的Nexenta OS系 統。在這些Debian系統中,以採用Linux核心的Debian GNU/Linux最爲著名。衆多的Linux發行版,例如Ubuntu、Knoppix和Linspire及Xandros等,都基 於Debian GNU/Linux。

  4. CentOS:(Community Enterprise Operating System,社區企業操作系統)是基於Red Hat Enterprise Linux源代碼編譯而成的。由於CentOS與Redhat Linux 源於相同的代碼基礎,所以很多成本敏感且需要高穩定性的公司就使用 CentOS來替代商業版Red Hat Enterprise Linux。CentOS自身不包含閉源軟件。

  5. Fedora :Fedora是由Fedora Project社區開發,紅帽公司贊助的Linux發行版。它的目標是創建一套新穎、多功能並且自由和開源的操作系統。對用戶而言,Fedora是一套功能完備的、可以更新的免費操作系統,而對贊助商Red Hat而言,它是許多新技術的測試平臺,被認爲可用的技術最終會加入到Red Hat Enterprise Linux中。

     $ docker run -it centos[Fedora] bash
    

9.2 爲鏡像添加SSH服務

       比如attach、exec等進入容器的辦法命令, 但這些命令都無法解決遠程管理容器的問題。因此,當讀者需要遠程登錄到容器內進行一些操作的時候,就需要SSH的支持了。 詳情下載PDF查看第10章的內容:

  • 基於commit命令創建
  • 使用Dockerfile創建

9.3 Web服務與應用

  • Apache是一個高穩定性的、商業級別的開源Web服務器。目前Apache已經是世界使用排名第一的Web服務器軟件。由於其良好的跨平臺和安全性,Apache被廣泛應用在多種平臺和操作系統上。作爲Apache軟件基金會支 持的項目,它的開發者社區完善而高效。自1995年發佈至今,一直以高標準 進行維護與開發。Apache名稱源自美國的西南部一個印第安人部落:阿帕奇 族,它支持類UNIX和Windows系統。 

  • Nginx是一款功能強大的開源反向代理服務器,支持 HTTP、HTTPS、SMTP、POP3、IMAP等協議。它也可以作爲負載均衡器、HTTP緩存或Web服務器。Nginx一開始就專注於高併發和高性能的應用場景。它使用類BSD開源協議,支持Linux、BSD、Mac、Solaris、AIX等類Unix系統,同時 也有Windows上的移植版本。

  • Tomcat是由Apache軟件基金會下屬的Jakarta項目開發的一個Servlet容 器,按照Sun Microsystems提供的技術規範,實現了對Servlet和Java Server Page(JSP)的支持。同時,它提供了作爲Web服務器的一些特有功能,如Tomcat管理和控制平臺、安全域管理和Tomcat閥等。由於Tomcat本身也內含 了一個HTTP服務器,也可以當作一個單獨的Web服務器來使用。下面介紹如何定製Tomcat鏡像。

  • Jetty是一個優秀的開源Servlet容器,以其高效、小巧、可嵌入式等優點深得人心,它爲基於Java的Web內容(如JSP和Servlet)提供運行環境。Jetty 基於Java語言編寫,它的API以一組JAR包的形式發佈。開發人員可以將Jetty 容器實例化成一個對象,可以迅速爲一些獨立運行的Java應用提供Web服務。

  • LAMP(Linux-Apache-MySQL-PHP)是目前流行的Web工具棧,其中包 括:Linux操作系統,Apache網絡服務器,MySQL數據庫,Perl、PHP或者 Python編程語言。其組成工具均是成熟的開源軟件,被大量網站所採用。和 Java/J2EE架構相比,LAMP具有Web資源豐富、輕量、快速開發等特點;和微軟的.NET架構相比,LAMP更具有通用、跨平臺、高性能、低價格的優勢。因 LAMP無論是在性能、質量還是價格方面都是企業搭建網站的首選平臺。

  • CMS:內容管理系統(Content Management System,CMS)指的是提供內容編輯服務的平臺程序。CMS可以讓不懂編程的用戶方便又輕鬆地發佈、更改和管理 各類數字內容(主要以文本和圖像爲主)。

       Ghost是一個廣受歡迎的開源博客平臺,使用JavaScript編寫,以MIT協議 發佈。它的設計非常簡約,使用起來體驗優異,非常適合做內容發佈,故而 受到很多極客或技術工作者的喜愛。 

        WordPress是風靡全球的開源內容管理系統,是博客、企業官網、產品首 頁等內容相關平臺的主流實現方案之一。類似項目還有 Drupal、Joomla、Typo3等。WordPress基於PHP和MySQL,架構設計簡單明瞭,支持主題,插件和各種 功能模塊。更重要的是,WordPress擁有龐大的社區,在線資源非常豐富,並 且在各大網絡空間商和雲平臺中受到廣泛的支持。根據2013年8月的統計數 據,流量排名前一千萬的網站中其使用率高達22%。

9.4 持續開發與管理

       持續集成(Continuous integration,CI)正是針對這類問題的一種開 發實踐,它倡導開發團隊定期進行集成驗證。集成通過自動化的構建來完 成,包括自動編譯、發佈和測試,從而儘快地發現錯誤。CI所描述的軟件開發是從原始需求識別到最終產品部署整個過程中,需求以小批量形式在團隊的各個角色間順暢流動,能夠以較短地週期完成需求的小粒度頻繁交付。整個過程中,需求分析、產品的用戶體驗和交互設計、開發、測試、運維等角 色需要密切協作。

       持續集成特點包括:從檢出代碼、編譯構建、運行測試、結果記錄、測試統計等都是自動完成的,減少人工干預需要有持續集成系統的支持,包 括代碼託管機制支持,以及集成服務器等。 持續交付(Continuous delivery,CD)則是經典的敏捷軟件開發方法的 自然延伸,它強調產品在修改後到部署上線的流程要敏捷化、自動化。甚至 一些較小的改變也要今早的部署上線,這跟傳統軟件在較大版本更新後才上線的思想不同。

  • Jenkins是一個得到廣泛應用的持續集成和持續交付的工具。作爲開源軟 件項目,它旨在提供一個開放易用的持續集成平臺。Jenkins能實時監控集成中存在的錯誤,提供詳細的日誌文件和提醒功能,並用圖表的形式形象地展示項目構建的趨勢和穩定性。Jenkins特點包括安裝配置簡單、支持詳細的測試報表、分佈式構建等。
  • Gitlab是一款非常強大的開源源碼管理系統。它支持基於Git的源碼管 理、代碼評審、issue跟蹤、活動管理、wiki頁面,持續集成和測試等功能。 基於Gitlab,用戶可以自己搭建一套類似 Github的開發協同平臺。

9.5 數據庫應用

       目前,主流數據庫包括關係型(SQL)和非關係型(NoSQL)兩種。在使用數據庫容器時,建議將數據庫文件映射到宿主主機,一方面減少容器文件系統帶來的性能損耗,另一方面實現數據的持久化。

       關係數據庫是建立在關係模型基礎上的數據庫,藉助於集合代數等數學概念和方法來處理數據庫中的數據,支持複雜的事物處理和結構化查詢。代 表實現有MySQL、Oracle、PostGreSQL、MariaDB、SQLServer等。

       非關係數據庫是新興的數據庫技術,它放棄了傳統關係型數據庫的部分強一致性限制,帶來性能上的提升,使其更適用於需要大規模並行處理的場景。非關係型數據庫是關係型數據庫的良好補充,代表產品有 MongoDB、Redis、CouchDB等。

  • MongoDB是一款可擴展、高性能的開源文檔數據庫,是當今最流行的 NoSQL數據庫軟件之一。它採用C++開發,支持複雜的數據類型和強大的查 詢語言,提供了關係數據庫的絕大部分功能。由於MongoDB高性能、易部 署、易使用等特點,已經在很多領域都得到了廣泛的應用。mongodb的默認服務端口:27017

  • MySQL是全球最流行的開源的開源關係數據庫軟件之一,因爲其高性 能、成熟可靠和適應性而得到廣泛應用。MySQL目前在不少大規模網站和應用 中被使用,比如Facebook、Twitter和Yahoo!等。

  • Redis是一個開源(BSD許可)的基於內存的數據結構存儲系統,可以用 作數據庫、緩存和消息中間件。

  • CouchDB是一款面向文檔的NoSQL數據庫,以JSON格式存儲數據。它兼 容ACID,可以用於存儲網站的數據與內容,以及提供緩存等。CouchDB裏文檔 域(Field)都是以鍵值對的形式存儲的,對數據的每次修改都會得到一個新 的文檔修訂號。CouchDB側重於AP(可用性和分區容忍度)。相比之下,MongoDB側重於 CP(一致性和分區容忍度),Neo4j則提供了特有的面向圖形的結構。

  • Cassandra是個開源(Apache License 2.0)的分佈式數據庫,支持分散的 數據存儲,可以實現容錯以及無單點故障等。Cassandra在設計上引入了P2P 技術,具備大規模可分區行存儲能力,並支持Spark、Storm、Hadoop的集 成。目前Facebook、Twitter、Instagram、eBay、Github、Reddit、Netflix 等多家公司都在使用Cassandra。類似工具還有HBase等。

  • Memcached是一個高性能、分佈式的開源內存對象緩存系統。最初是Danga Interactive爲了優化LiveJournal的訪問速度而編寫的。目前已經非常廣 泛的應用於各種Web應用中。以BSD license授權協議發佈。Memcached守護進程基於C語言實現,基於libevent的事件處理可以實現 很高的性能。需要注意的是,由於數據僅存在於內存中,因此重啓 Memcached或重啓操作系統會導致數據全部丟失。

9.6 分佈式處理與大數據平臺

  • RabbitMQ是一個支持Advanced Message Queuing Protocol(AMQP)的開源消息隊列實現,由Erlang編寫,因以高性能、高可用以及可伸縮性出名。它支持多種客戶端,如:Java、Python、PHP、.NET、Ruby、JavaScript等。它主要用於在分佈式系統中存儲和轉發消息,方便組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。

    AMQP架構中有兩個主要組件:Exchange和Queue,兩者都在服務端,又稱Broker,由RabbitMQ實現的。客戶端通常有Producer和Consumer兩種類型。在使用RabbitMQ過程中需要注意的是,它將數據存儲在Node中,默認情 況爲hostname。用戶使用rabbitmqctl工具進行遠程管理,或跨容器管理的時候,會需要設置持久化的cookie。如果需要了解關於Erlang Cookie的信息,可以參見 RabbitMQ官網的集羣指南。

  • 除了通用的消息隊列外,任務隊列在分佈式處理中也十分重要。任務隊列的輸入是工作的一個單元,稱爲任務,有多個工作者監聽隊列來獲取任務 並執行。Celery是一個簡單、靈活、高可用、高性能的開源(BSD許可)分佈式任務處理系統,專注於實時處理的任務隊列管理,同時也支持任務調 度。Celery基於Python實現,跟包括Django、Pyramid、Pylons、Flask、Tornado等Web框架都無縫集成,有龐大 的用戶與貢獻者社區。Celery可以單機運行,也可以在多臺機器上運行,甚至可以跨越數據中心運行。

  • 作爲當今大數據處理領域的經典分佈式平臺,Apache Hadoop主要基於 Java語言實現,由三個核心子系統組成:HDFS、YARN、MapReduce,其 中,HDFS是一套分佈式文件系統;YARN是資源管理系統,MapReduce是運行 在YARN上的應用,負責分佈式處理管理。如果從操作系統的角度看,HDFS 相當於Linux的ext3/ext4文件系統,而Yarn相當於Linux的進程調度和內存分配模塊。

  • Apache Spark是一個圍繞速度、易用性和複雜分析構建的大數據處理框 架,基於Scala開發。最初在2009年由加州大學伯克利分校的AMPLab開發,並於2010年成爲Apache的開源項目之一。與Hadoop和Storm等其他大數據和MapReduce技術相比,Spark支持更靈 活的函數定義,可以將應用處理速度提升一到兩個數量級,並且提供了衆多 方便的實用工具,包括SQL查詢、流處理、機器學習和圖處理等: Spark體系架構包括如下三個主要組件:數據存儲、API、管理框架。

  • Apache Storm是一個實時流計算框架,由Twitter在2014年正式開源,遵循 Eclipse Public License 1.0。Storm基於Clojure等語言實現。Storm集羣與Hadoop集羣在工作方式上十分相似,唯一區別在於Hadoop 上運行的是MapReduce任務,在Storm上運行的則是topology。MapReduce任務完成處理即會結束,而topology則永遠在等待消息並處理(直到被停止)。

  • Elasticsearch是一個基於Lucene的開源搜索服務器,主要基於Java實現。 它提供了一個分佈式的,多租戶的全文搜索引擎,內含RESTful web接口。Elasticsearch提供了實時的分佈式數據存儲和分析查詢功能,很容易擴展 到上百臺服務器,支持處理PB級結構化或非結構化數據。配合 Logstash、Kibana等組件,可以快速構建一套對日誌消息的分析平臺。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章