架構師分享 Docker 新手入門完全指南
0 快速入門
- ???????Docker?最初 dotCloud 公司內部的一個業(yè)余項目
- Docker 基于 Go 語言
- Docker 項目的目標是實現(xiàn)輕量級的操作系統(tǒng)虛擬化解決方案
- Docker 的基礎是?Linux?容器(LXC)等技術
- Docker 容器的啟動可以在秒級實現(xiàn),這相比傳統(tǒng)的虛擬機方式要快得多
- Docker 對系統(tǒng)資源的利用率很高,一臺主機上可以同時運行數(shù)千個 Docker 容器
下面的圖片比較了?Docker?和傳統(tǒng)虛擬化方式的不同之處,可見容器是在操作系統(tǒng)層面上實現(xiàn)虛擬化,直接復用本地主機的操作系統(tǒng),而傳統(tǒng)方式則是在硬件層面實現(xiàn)。


??容器除了運行其中應用外,基本不消耗額外的系統(tǒng)資源,使得應用的性能很高,同時系統(tǒng)的開銷盡量小。傳統(tǒng)虛擬機方式運行?10?個不同的應用就要起?10?個虛擬機,而Docker?只需要啟動?10?個隔離的應用即可。
主要優(yōu)勢為:
- 更快速的交付和部署 - 容器成為了最小單位
- 更高效的虛擬化 - 內核級虛擬化
- 更輕松的遷移和拓展
- 更簡單的管理
1 安裝
官方網站提供了?Mac, Linux 和?Windows?版本的安裝教程。我們只要跟著官方文檔即可,這里不再贅述。
不過需要提一下 Kitematic 這個圖形化工具(官方給出的定義是 Visual Docker?Container?Management on?Mac?&?Windows),對于熟悉和了解?Docker?是很好的幫助,大家可以體驗一下。
守護進程
運行 Docker 守護進程時,可以用?-H?來改變綁定接口的方式,比如
sudo?/usr/bin/docker?-d?-H?tcp://0.0.0.0:2375,
如果不想每次都輸入這么長的命令,需要加入以下環(huán)境變量
export?DOCKER_HOST="tcp://0.0.0.0:2375"
圖形用戶界面
雖然我們可以用命令來控制 docker,但是如果能有一個?web?管理界面,操作什么的會方便很多,比較常見的有
- Shipyard
- Potainer
2 基本概念
基本概念主要有三個:
- 鏡像(Image)
- 一個只讀的模板,鏡像可以用來創(chuàng)建 Docker 容器
- 用戶基于鏡像來運行自己的容器。鏡像是基于?Union?文件系統(tǒng)的層式結構
- 可以簡單創(chuàng)建或更新現(xiàn)有鏡像,或者直接下載使用其他人的??梢岳斫鉃樯扇萜鞯摹涸创a』
- 容器(Container)
- 容器是從鏡像創(chuàng)建的運行實例,在啟動的時候創(chuàng)建一層可寫層作為最上層(因為鏡像是只讀的)
- 可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺
- 可以把容器看做是一個簡易版的?Linux?環(huán)境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序
- 倉庫(Registry)
- 集中存放鏡像文件的場所,可以是公有的,也可以是私有的
- 最大的公開倉庫是 Docker Hub
- 國內的公開倉庫包括 Docker Pool 等
- 當用戶創(chuàng)建了自己的鏡像之后就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 pull 下來就可以了
- Docker 倉庫的概念跟 Git 類似,注冊服務器可以理解為?GitHub?這樣的托管服務
另外?Docker?采用的是客戶端/服務器架構,客戶端只需要向?Docker?服務器或守護進程發(fā)出請求即可完成各類操作。那么問題來了,我們能用?Docker?來做什么呢?我們可以:
- 統(tǒng)一、優(yōu)化和加速本地開發(fā)和構建流程
- 保證不同的環(huán)境中可以得到相同的運行結果
- 創(chuàng)建隔離環(huán)境用于測試
Docker?可以提供的隔離有:
- 文件系統(tǒng)隔離:每個容器都有自己的?root?文件系統(tǒng)
- 進程隔離:每個容器都運行在自己的進程環(huán)境中
- 網絡隔離:容器間的虛擬網絡接口和?IP?地址都是分開的
- 資源隔離和分組:使用?cgroups?將?CPU?和內存之類的資源獨立分配給每個 Docker 容器
3 常用命令
- 查看 docker 狀態(tài)?sudo docker?info
- 查看系統(tǒng)中正在運行的容器的列表?docker ps
- 加上?-a?可以列出所有容器
- 加上?-l?可以列出最后一次運行的容器
一個簡單的例子
接下來我們用一個簡單的例子來體驗下 docker
4 容器小介紹
容器是獨立運行的一個或一組應用,以及它們的運行態(tài)環(huán)境。對應的,虛擬機可以理解為模擬運行的一整套操作系統(tǒng)(提供了運行態(tài)環(huán)境和其他系統(tǒng)環(huán)境)和跑在上面的應用。
啟動容器有兩種方式,一種是基于鏡像新建一個容器并啟動,另外一個是將在終止狀態(tài)(stopped)的容器重新啟動。因為?Docker?的容器實在太輕量級了,很多時候用戶都是隨時刪除和新創(chuàng)建容器(對于初級應用來說后者更方便)。
當利用?docker?run?來創(chuàng)建容器時,Docker?在后臺運行的標準操作包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
- 利用鏡像創(chuàng)建并啟動一個容器
- 分配一個文件系統(tǒng),并在只讀的鏡像層外面掛載一層可讀寫層
- 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
- 從地址池配置一個 ip 地址給容器
- 執(zhí)行用戶指定的應用程序
- 執(zhí)行完畢后容器被終止
可以利用? docker start?命令,直接將一個已經終止的容器啟動運行。
5 運行容器
現(xiàn)在,我們來創(chuàng)建一個?ubuntu:14.04?的容器
docker?run?ubuntu:14.04?/bin/echo?'Hello?wdx!'
(結果如下圖所示)

可以看到正確輸出了我們的?“Hello?wdx!”
接下來,我們用?docker?run?-t?-i?ubuntu:14.04?/bin/bash?可以啟動一個?bash?終端用來交互。參數(shù)的意思是:
- -t?選項讓Docker分配一個偽終端(pseudo-tty)并綁定到容器的標準輸入上
- -i?則讓容器的標準輸入保持打開
我們可以輸入一些命令來測試

容器的核心為所執(zhí)行的應用程序,所需要的資源都是應用程序運行所必需的。除此之外,并沒有其它的資源。我們用? ps?或? top?在偽終端中查看進程信息,可以看到只有我們運行的進程,沒有其他花里胡哨的(上圖最后一條命令)
試一試如下命令
- cat /etc/hosts
- ip a
- ps -aux
- cd ~ && echo "hello wdx" > hello.txt && cat hello.txt
(細心的同學可能會發(fā)現(xiàn)這里的輸出暗藏玄機)
操作完成后,輸入?exit?便可以退出這個?ubuntu?容器。退出之后這個容器依然存在,我們可以用?docker ps -l來看看:
每個容器有一個?Container?ID?和?Name,我們一般就是通過這倆來定位一個容器的。
6 鏡像
我們可以使用?docker pull?命令從倉庫中獲取所需要的鏡像。比如說
sudo?docker?pull?ubuntu:12.04,
相當于
sudo?docker?pull?registry.hub.docker.com/ubuntu:12.04,
即從注冊服務器 中的?ubuntu?倉庫來下載標記為12.04?的鏡像。
如果想從其他倉庫注冊服務器下載,需要輸入完成的地址,例如:
sudo?docker?pull?dl.dockerpool.com:5000/ubuntu:12.04
下載完成之后就可以使用該鏡像了,比如下面的語句就會創(chuàng)建容器,其中運行?bash:
sudo?docker?run?-t?-i?ubuntu:12.04?/bin/bash
可以使用?dokcer images?來顯示本地已有的鏡像,如下
具體字段的意思一目了然,這里不再贅述。然后我們來運行官方例子?whalesay?鏡像。
7 運行鏡像
打開瀏覽器,進入 Docker Hub

搜索? whalesay?這個鏡像,就可以看到結果,點進去可以看到詳細內容(基于 Ubuntu)

然后我們來運行一下,使用命令?
docker run docker/whalesay cowsay boo
其中?cowsay?是要運行的命令,后面的?boo?是參數(shù)。
Docker?會先在本地查找有沒有鏡像,如果沒有就從倉庫中下載,具體的運行結果是:

也可以讓鯨魚說不同的話,比如:

8 制作鏡像
如果想要制作自己的鏡像,需要自己寫?Dockerfile。具體步驟如下
1、創(chuàng)建一個文件夾?mkdir wdxtub; cd wdxtub,構造鏡像所需的所有東西都會放在這個文件夾中
2、創(chuàng)建一個名為?Dockerfile?的文件?gedit Dockerfile
3、添加第一句話?FROM?docker/whalesay:latest,表示我們的鏡像以?whalesay?為基礎
4、添加需要運行的命令,如?RUN apt-get -y update && apt-get install -y fortunes(fortunes?這個程序會輸出名言警句)
5、通過?CMD?指定鏡像載入之后需要執(zhí)行的命令,如?CMD /usr/games/fortune -a | cowsay
6、保存并關閉 Dockerfile
7、使用?sudo docker build -t wdx-whale .?來構造鏡像,簡單來說就是用 Dockerfile 中的內容按步驟構造
8、使用?docker images?應該就可以看到我們新創(chuàng)建的鏡像
然后我們就可以運行一下看看
docker run wdx-whale

還有更賤的(感覺可以玩一天)

??如果想要把自己的鏡像上傳到網上,就需要注冊一個 Docker Hub 帳號,然后點擊 Create Repository,這里我創(chuàng)建了一個名為? wdxtub/demo ?的公用倉庫。
接下來我們需要打上 tag,目前?docker images?的情況是:
記住我們的?IMAGE?ID?26ac9649d7da。用以下命令打?tag
docker?tag?26ac9649d7da?wdxtub/wdx-whale:latest,
然后再?docker images?一次:

然后用這個命令登錄
docker login --username=yourhubusername --email=yourmail@company.com,
對于我來說就是
docker login --username=wdxtub --email=dacrocodilee@gmail.com
成功之后大概是這樣:
然后就可以 push 上去了?docker push wdxtub/wdx-whale,像下面這樣

為了測試?pull?自己的鏡像,我們先把本地上的?whale?鏡像刪掉:
docker rmi -f wdxtub/wdx-whale; docker rmi -f wdx-whale
(如果有其他的用不著的也都刪掉),最后剩下(上課要用的鏡像):
接著來運行一下
docker run wdxtub/wdx-whale
9 管理鏡像
?我們可以把鏡像導出到本地文件,使用?docker save?命令即可,比如針對我現(xiàn)在有的鏡像?wdxtub/wdx-whale(id:26ac9649d7da),可以這樣:
??docker save -o wdx-local-whale.tar wdxtub/wdx-whale。
?如果要載入的話,使用下面的命令即可(會載入相關的元數(shù)據(jù)信息)
?docker load --input wdx-local-whale.tar# 或者docker load < wdx-local-whale.tar
?在刪除鏡像之前要先用? docker rm ?刪掉依賴于這個鏡像的所有容器.
?sudo docker rmi $(docker images -q -f "dangling=true")
?鏡像的實現(xiàn)原理
Docker?鏡像是怎么實現(xiàn)增量的修改和維護的??每個鏡像都由很多層次構成,Docker?使用?Union?FS?將這些不同的層結合到一個鏡像中去。
通常?Union?FS?有兩個用途,?一方面可以實現(xiàn)不借助?LVM、RAID?將多個?disk?掛到同一個目錄下,另一個更常用的就是將一個只讀的分支和一個可寫的分支聯(lián)合在一起,Live?CD?正是基于此方法可以允許在鏡像不變的基礎上允許用戶在其上進行一些寫操作。?Docker?在?AUFS?上構建的容器也是利用了類似的原理。
??10 容器啟動
舉個例子,
后臺運行
更多的時候,需要讓?Docker在后臺運行而不是直接把執(zhí)行命令的結果輸出在當前宿主機下。此時,可以通過添加?-d?參數(shù)來實現(xiàn)。
下面舉兩個例子來說明一下。
如果不使用 -d 參數(shù)運行容器
docker?run?ubuntu:14.04?/bin/sh?-c?"while?true;?do?echo?hello world; sleep 1; done"
容器會把輸出的結果(STDOUT)打印到宿主機上面
如果使用了 -d 參數(shù)運行容器
docker?run?-d?ubuntu:14.04?/bin/sh -c "while true; do?echo?hello world; sleep 1; done",
則顯示是這樣:
使用?docker logs containerid?可以查看輸出,如:

??使用?-d?參數(shù)啟動后會返回一個唯一的?id,也可以通過?docker?ps?命令來查看容器信息。容器是否會長久運行,是和docker?run指定的命令有關,和?-d?參數(shù)無關
??在使用?-d?參數(shù)時,容器啟動后會進入后臺。?某些時候需要進入容器進行操作,有很多種方法,包括使用?docker?attach?命令或?nsenter?工具等。具體參考這里
11 終止與重新啟動
使用? docker stop containerid ?來終止容器。 終止狀態(tài)的容器可以用? docker ps -a ?命令看到。
?另外, docker restart containerid ?命令會將一個運行態(tài)的容器終止,然后再重新啟動它。
12 導入導出與刪除
?如果要導出本地某個容器,可以使用? docker export?containerid?命令。
?可以使用? docker import?從容器快照文件中再導入為鏡像,例如
?cat ubuntu.tar |? sudo docker ?import?-?test/ubuntu: v1.0#?也可以通過指定?URL?或者某個目錄來導入,例如docker?import?http: //example.com/exampleimage.tgz?example/imagerepo
??用戶既可以使用?docker?load?來導入鏡像存儲文件到本地鏡像庫,也可以使用docker?import?來導入一個容器快照到本地鏡像庫。 這兩者的區(qū)別在于容器快照文件將丟棄所有的歷史記錄和元數(shù)據(jù)信息(即僅保存容器當時的快照狀態(tài)),而鏡像存儲文件將保存完整記錄,體積也要大。 此外,從容器快照文件導入時可以重新指定標簽等元數(shù)據(jù)信息。
?可以使用? docker rm ?來刪除一個處于終止狀態(tài)的容器。 如果要刪除一個運行中的容器,可以添加?-f?參數(shù)。 Docker?會發(fā)送?SIGKILL?信號給容器。
?用? docker ps -a ?命令可以查看所有已經創(chuàng)建的包括終止狀態(tài)的容器,如果數(shù)量太多要一個個刪除可能會很麻煩,用? docker rm $(docker ps -a -q) ?可以全部清理掉。
??注意: 這個命令其實會試圖刪除所有的包括還在運行中的容器,不過就像上面提過的 docker rm ?默認并不會刪除運行中的容器。
13 倉庫
??倉庫(Repository)是集中存放鏡像的地方。
?一個容易混淆的概念是注冊服務器(Registry)。實際上注冊服務器是管理倉庫的具體服務器,每個服務器上可以有多個倉庫,而每個倉庫下面有多個鏡像。從這方面來說,倉庫可以被認為是一個具體的項目或目錄。例如對于倉庫地址dl.dockerpool.com/ubuntu?來說,dl.dockerpool.com 是注冊服務器地址,ubuntu是倉庫名。
聲明:文章來源于網絡,侵刪!