Docker容器學習梳理--基礎知識(2)
之前已經總結了Docker容器學習梳理--基礎知識(1),但是不夠詳細,下面再完整補充下Docker學習的一些基礎。
Docker是個什麼東西
Docker是一個程式執行、測試、交付的開放平臺,Docker被設計為能夠使你快速地交付應用。 在Docker中,你可以將你的程式分為不同的基礎部分,對於每一個基礎部分都可以當做一個應用程式來管理。 Docker能夠幫助你快速地測試、快速地編碼、快速地交付,並且縮短你從編碼到執行應用的週期。 Docker使用輕量級的容器虛擬化平臺,並且結合工作流和工具,來幫助你管理、部署你的應用程式。 Docker在其核心,Docker實現了讓幾乎任何程式都可以在一個安全、隔離的容器中執行。安全和隔離可以使你可以同時在機器上執行多個容器。 Docker容器輕量級的特性,意味著你可以得到更多的硬體效能。 圍繞著Docker容器的虛擬化工具和平臺,可以在以下幾個方面為你提供幫助: 1)幫助你把應用程式(包括其餘的支援元件)放入到Docker容器中。 2)分發和轉移你的容器至你的團隊其它成員來進行進一步的開發和測試。 3)部署這些應用程式至你的生產環境,不論是本地的資料中心還是雲平臺。
Docker的用途
1)快速交付你的應用程式 Docker可以為你的開發過程提供完美的幫助。Docker允許開發者在本地包含了應用程式和服務的容器進行開發,之後可以整合到連續的一體化和部署工作流中。 舉個例子,開發者們在本地編寫程式碼並且使用Docker和同事分享其開發棧。當開發者們準備好了之後,他們可以將程式碼和開發棧推送到測試環境中,在該環境進行一切所需要的測試。從測試環境中,你可以將Docker映象推送到伺服器上進行部署。 2)開發和拓展更加簡單 Docker的以容器為基礎的平臺允許高度可移植的工作。Docker容器可以在開發者機器上執行,也可以在實體或者虛擬機器上執行,也可以在雲平臺上執行。 Docker的可移植、輕量特性同樣讓動態地管理負載更加簡單。你可以用Docker快速地增加應用規模或者關閉應用程式和服務。Docker的快速意味著變動幾乎是實時的。 3)達到高密度和更多負載 Docker輕巧快速,它提供了一個可行的、符合成本效益的替代基於虛擬機器管理程式的虛擬機器。這在高密度的環境下尤其有用。例如,構建你自己的雲平臺或者PaaS,在中小的部署環境下同樣可以獲取到更多的資源效能。
Docker的主要組成
Docker有兩個主要的部件: Docker: 開源的容器虛擬化平臺。 Docker Hub: 用於分享、管理Docker容器的Docker SaaS平臺。
Docker的架構
Docker使用客戶端-伺服器(client-server)架構模式。 Docker 客戶端會與Docker守護程序進行通訊。Docker 守護程序會處理複雜繁重的任務,例如建立、執行、釋出你的 Docker 容器。 Docker 客戶端和守護程序可以執行在同一個系統上,當然也可以使用Docker客戶端去連線一個遠端的 Docker 守護程序。 Docker 客戶端和守護程序之間通過socket或者RESTful API進行通訊。
1)Docker守護程序
如上圖所示,Docker守護程序執行在一臺主機上。使用者並不直接和守護程序進行互動,而是通過 Docker 客戶端間接和其通訊。
2)Docker 客戶端
Docker 客戶端,實際上是 docker 的二進位制程式,是主要的使用者與 Docker 互動方式。它接收使用者指令並且與背後的 Docker 守護程序通訊,如此來回往復。
3)Docker 內部
要理解 Docker 內部構建,需要理解以下三種部件:
Docker 映象 - Docker images
Docker 倉庫 - Docker registeries
Docker 容器 - Docker containers
Docker 映象 Docker 映象是Docker容器執行時的只讀模板,每一個映象由一系列的層 (layers) 組成。Docker 使用 UnionFS 來將這些層聯合到單獨的映象中。UnionFS 允許獨立檔案系統中的檔案和資料夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的檔案系統。正因為有了這些層的存在,Docker 是如此的輕量。當你改變了一個 Docker 映象,比如升級到某個程式到新的版本,一個新的層會被建立。因此,不用替換整個原先的映象或者重新建立(在使用虛擬機器的時候你可能會這麼做),只是一個新 的層被新增或升級了。現在你不用重新發布整個映象,只需要升級,層使得分發 Docker 映象變得簡單和快速。 Docker 倉庫 Docker 倉庫用來儲存映象,可以理解為程式碼控制中的程式碼倉庫。同樣的,Docker 倉庫也有公有和私有的概念。公有的 Docker 倉庫名字是 Docker Hub。Docker Hub 提供了龐大的映象集合供使用。這些映象可以是自己建立,或者在別人的映象基礎上建立。Docker 倉庫是 Docker 的分發部分。 Docker 容器 Docker 容器和資料夾很類似,一個Docker容器包含了所有的某個應用執行所需要的環境。每一個 Docker 容器都是從 Docker 映象建立的。Docker 容器可以執行、開始、停止、移動和刪除。每一個 Docker 容器都是獨立和安全的應用平臺,Docker 容器是 Docker 的執行部分。
4)libcontainer
Docker 從 0.9 版本開始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系統的互動圖如下:
5)名稱空間「Namespaces」
1)pid namespace 不同使用者的程序就是通過pid namespace隔離開的,且不同 namespace 中可以有相同 PID。 具有以下特徵: 每個namespace中的pid是有自己的pid=1的程序(類似 /sbin/init 程序) 每個 namespace 中的程序只能影響自己的同一個 namespace 或子 namespace 中的程序 因為 /proc 包含正在執行的程序,因此在 container 中的 pseudo-filesystem 的 /proc 目錄只能看到自己namespace 中的程序 因為 namespace 允許巢狀,父 namespace 可以影響子 namespace 的程序,所以子 namespace 的程序可以在父namespace中看到,但是具有不同的 pid 2)mnt namespace 類似 chroot,將一個程序放到一個特定的目錄執行。mnt namespace 允許不同namespace的程序看到的檔案結構不同,這樣每個namespace 中的程序所看到的檔案目錄就被隔離開了。同 chroot 不同,每個 namespace 中的 container 在 /proc/mounts 的資訊只包含所在namespace的mount point。 3)net namespace 網路隔離是通過 net namespace 實現的, 每個 net namespace 有獨立的 network devices, IP addresses, IP routing tables, /proc/net 目錄。這樣每個 container 的網路就能隔離開來。 docker 預設採用 veth 的方式將 container 中的虛擬網絡卡同 host 上的一個 docker bridge 連線在一起。 4)uts namespace UTS ("UNIX Time-sharing System") namespace 允許每個 container 擁有獨立的 hostname 和 domain name, 使其在網路上可以被視作一個獨立的節點而非 Host 上的一個程序。 5)ipc namespace container 中程序互動還是採用 Linux 常見的程序間互動方法 (interprocess communication - IPC), 包括常見的訊號量、訊息佇列和共享記憶體。然而同 VM 不同,container 的程序間互動實際上還是 host 上具有相同 pid namespace 中的程序間互動,因此需要在IPC資源申請時加入 namespace 資訊 - 每個 IPC 資源有一個唯一的 32bit ID。 6)user namespace 每個 container 可以有不同的 user 和 group id, 也就是說可以以 container 內部的使用者在 container 內部執行程式而非 Host 上的使用者。 有了以上6種namespace從程序、網路、IPC、檔案系統、UTS 和使用者角度的隔離,一個 container 就可以對外展現出一個獨立計算機的能力,並且不同container從OS層面實現了隔離。然而不同 namespace 之間資源還是相互競爭的,仍然需要類似ulimit 來管理每個container所能使用的資源。
6)資源配額「cgroups」
cgroups 實現了對資源的配額和度量。 cgroups 的使用非常簡單,提供類似檔案的介面,在 /cgroup 目錄下新建一個資料夾即可新建一個 group,在此資料夾中新建 task 檔案,並將 pid 寫入該檔案,即可實現對該程序的資源控制。具體的資源配置選項可以在該資料夾中新建子 subsystem ,{子系統字首}.{資源項} 是典型的配置方法, 如 memory.usageinbytes 就定義了該 group 在 subsystem memory 中的一個記憶體限制選項。 另外,cgroups 中的 subsystem 可以隨意組合,一個 subsystem 可以在不同的 group 中,也可以一個 group 包含多個 subsystem - 也就是說一個 subsystem。 memory 記憶體相關的限制 cpu 在 cgroup 中,並不能像硬體虛擬化方案一樣能夠定義 CPU 能力,但是能夠定義 CPU 輪轉的優先順序,因此具有較高 CPU 優先順序的程序會更可能得到 CPU 運算。 通過將引數寫入 cpu.shares ,即可定義改 cgroup 的 CPU 優先順序 - 這裡是一個相對權重,而非絕對值 blkio block IO 相關的統計和限制,byte/operation 統計和限制 (IOPS 等),讀寫速度限制等,但是這裡主要統計的都是同步 IO devices 裝置許可權限制
Docker的工作原理
1)可以建立一個容納應用程式的容器。 2)可以從Docker映象建立Docker容器來執行應用程式。 3)可以通過Docker Hub或者自己的Docker倉庫分享Docker映象。
Docker映象是如何工作的?
Docker映象是Docker容器執行時的只讀模板,每一個映象由一系列的層(layers)組成; Docker使用UnionFS(聯合檔案系統)來將這些層聯合到一二映象中,UnionFS檔案系統允許獨立檔案系統中的檔案和資料夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的檔案系統。 正因為有了這些層(layers)的存在,Docker才會如此的輕量。當你改變了一個Docker映象,比如升級到某個程式到新的版本,一個新的層會被建立。因此,不用替換整個原先的映象或者重新建立(在使用虛擬機器的時候你可能會這麼做),只是一個新的層被新增或升級了。所以你不用重新發布整個映象,只需要升級。層使得分發Docker映象變得簡單和快速。 每個映象都是從一個基礎的映象開始的,比如ubuntu,一個基礎的Ubuntu映象,或者是Centos,一個基礎的Centos映象。你可以使用你自己的映象作為新映象的基礎,例如你有一個基礎的安裝了Nginx的映象,你可以使用該映象來建立你的Web應用程式映象。(Docker通常從Docker Hub獲取基礎映象) Docker映象從這些基礎的映象建立,通過一種簡單、具有描述性的步驟,我們稱之為 指令(instructions)。 每一個指令會在映象中建立一個新的層,指令可以包含這些動作: 1)執行一個命令。 2)增加檔案或者資料夾。 3)建立一個環境變數。 5)當執行容器的時候哪些程式會執行。 這些指令儲存在Dockerfile檔案中。當你需要建立映象的時候,Docker可以從Dockerfile中讀取這些指令並且執行,然後返回一個最終的映象。
Docker倉庫是如何工作的?
Docker倉庫是Docker映象的儲存倉庫。可以推送映象到Docker倉庫中,然後在Docker客戶端,可以從Docker倉庫中搜索映象。
Docker容器是如何工作的?
一個Docker容器包含了一個作業系統、使用者新增的檔案和元資料(meta-data)。每個容器都是從映象建立的,映象告訴Docker容器內包含了什麼,當容器啟動時執行什麼程式,還有許多配置資料。 Docker映象是隻讀的,當Docker執行一個從映象建立的容器,它會在映象頂部新增一個可讀寫的層,應用程式可以在這裡執行。
當執行docker容器時發生了什麼?
使用docker命令時,Docker客戶端都告訴Docker守護程序執行一個容器。 $ sudo docker run -i -t ubuntu /bin/bash 可以來分析這個命令,Docker客戶端使用docker命令來執行,run引數表明客戶端要執行一個新的容器。 Docker客戶端要執行一個容器需要告訴Docker守護程序的最小引數資訊是: 1)這個容器從哪個映象建立,這裡是ubuntu,基礎的Ubuntu映象。 2)在容器中要執行的命令,這裡是/bin/bash,在容器中執行Bash shell。 那麼執行這個命令之後在底層發生了什麼呢? 按照順序,Docker做了這些事情: 1)拉取ubuntu映象: Docker檢查ubuntu映象是否存在,如果在本地沒有該映象,Docker會從Docker Hub下載。如果映象已經存在,Docker會使用它來建立新的容器。 2)建立新的容器: 當Docker有了這個映象之後,Docker會用它來建立一個新的容器。 3)分配檔案系統並且掛載一個可讀寫的層: 容器會在這個檔案系統中建立,並且一個可讀寫的層被新增到映象中。 4)分配網路/橋接介面: 建立一個允許容器與本地主機通訊的網路介面。 5)設定一個IP地址: 從池中尋找一個可用的IP地址並且服加到容器上。 6)執行你指定的程式: 執行指定的程式。 7)捕獲並且提供應用輸出: 連線並且記錄標準輸出、輸入和錯誤讓你可以看到你的程式是如何執行的。 由此你就可以擁有一個執行著的Docker容器了!從這裡開始你可以管理你的容器,與應用互動,應用完成之後,可以停止或者刪除你的容器。
Docker的底層技術
Docker使用Go語言編寫,並且使用了一系列Linux核心提供的效能來實現我們已經看到的這些功能。 名稱空間(Namespaces)(這個上面也詳細說明了) Docker充分利用了一項稱為namespaces的技術來提供隔離的工作空間,我們稱之為 container(容器)。當你執行一個容器的時候,Docker為該容器建立了一個名稱空間集合。 這樣提供了一個隔離層,每一個應用在它們自己的名稱空間中執行而且不會訪問到名稱空間之外。 一些Docker使用到的名稱空間有: pid名稱空間: 使用在程序隔離(PID: Process ID)。 net名稱空間: 使用在管理網路介面(NET: Networking)。 ipc名稱空間: 使用在管理程序間通訊資源 (IPC: InterProcess Communication)。 mnt名稱空間: 使用在管理掛載點 (MNT: Mount)。 uts名稱空間: 使用在隔離核心和版本標識 (UTS: Unix Timesharing System)。 群組控制 Docker還使用到了cgroups技術來管理群組。使應用隔離執行的關鍵是讓它們只使用你想要的資源。這樣可以確保在機器上執行的容器都是良民(good multi-tenant citizens)。群組控制允許Docker分享或者限制容器使用硬體資源。例如,限制指定的容器的內容使用。 聯合檔案系統 聯合檔案系統(UnionFS)是用來操作建立層的,使它們輕巧快速。Docker使用UnionFS提供容器的構造塊。Docker可以使用很多種類的UnionFS包括AUFS, btrfs, vfs, and DeviceMapper。 容器格式 Docker連線這些組建到一個包裝中,稱為一個 container format(容器格式)。預設的容器格式是libcontainer。Docker同樣支援傳統的Linux容器使用LXC。在未來,Docker也許會支援其它的容器格式,例如與BSD Jails 或 Solaris Zone整合。
Docker的預設路徑: Docker執行時根目錄:/var/lib/docker Docker的配置檔案:在ubuntu中的位置是:/etc/default/docker;在centos7中的位置是:/etc/sysconfig/docker
Docker映象使用
Docker HUB : Docker映象首頁,包括官方映象和其它公開映象。Docker Hub上最受歡迎的10大映象(通過Docker registry API獲取不了映象被pull的個數,只能通過映象的star數量,來衡量映象的流行度。毫無疑問,擁有最高star數量的庫都是官方庫):
因為國情的原因,國內下載 Docker HUB 官方的相關映象比較慢,可以使用國內(docker.io)的一些映象加速器,映象保持和官方一致,關鍵是速度塊,推薦使用。
這裡需要明確一個問題,就是Mirror與Private Registry的區別。二者有著本質的差別:
1)Private Registry(私有倉庫)是開發者或者企業自建的映象儲存庫,通常用來儲存企業內部的 Docker 映象,用於內部開發流程和產品的釋出、版本控制。 2)Mirror是一種代理中轉服務,我們(比如daocloud)提供的Mirror服務,直接對接Docker Hub的官方Registry。Docker Hub 上有數以十萬計的各類 Docker 映象。 3)在使用Private Registry時,需要在Docker Pull 或Dockerfile中直接鍵入Private Registry 的地址,通常這樣會導致與 Private Registry 的繫結,缺乏靈活性。 4)使用 Mirror 服務,只需要在 Docker 守護程序(Daemon)的配置檔案中加入 Mirror 引數,即可在全域性範圍內透明的訪問官方的 Docker Hub,避免了對 Dockerfile 映象引用來源的修改。 5)簡單來說,Mirror類似CDN,本質是官方的cache;Private Registry類似私服,跟官方沒什麼關係。對使用者來說,由於使用者是要拖docker hub上的image,對應的是Mirror。 yum/apt-get的Mirror又有點不一樣,它其實是把官方的庫檔案整個拖到自己的伺服器上做映象(不管有沒有用),並定時與官方做同步;而Docker Mirror只會快取曾經使用過的image。
目前國內訪問docker hub速度上有點尷尬,使用docker Mirror勢在必行。
現有國內提供docker映象加速服務的商家有不少,下面重點介紹幾家:
1)ustc的映象
ustc是老牌的linux映象服務提供者了,還在遙遠的ubuntu 5.04版本的時候就在用。之前在blog裡有提到可以用ustc的docker倉庫映象.
使用方法參考ustc docker映象使用幫助
ustc的docker映象加速器速度很不錯,一直用的挺happy。ustc docker mirror的優勢之一就是不需要註冊,真正是公共服務啊。
----------------------------------這裡順便說下在新版Docker裡使用ustc的做法------------------------------------- 新版的Docker配置方法: [[email protected] ~]# vim /etc/docker/daemon.json //如果沒有該檔案的話,就手動建立。在該檔案裡新增下面內容 { "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] } 然後就可以直接docker pull下載映象了,速度槓槓滴!!! [[email protected] docker]# docker pull ubuntu Using default tag: latest Trying to pull repository docker.io/library/ubuntu ... latest: Pulling from docker.io/library/ubuntu d54efb8db41d: Pull complete f8b845f45a87: Pull complete e8db7bf7c39f: Pull complete 9654c40e9079: Pull complete 6d9ef359eaaa: Pull complete Digest: sha256:dd7808d8792c9841d0b460122f1acf0a2dd1f56404f8d1e56298048885e45535 Status: Downloaded newer image for docker.io/ubuntu:latest [[email protected] ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/ubuntu latest 0ef2e08ed3fa 2 weeks ago 130 MB ----------------------------------------------------------------------------------------------------------------------
2)daocloud映象
DaoCloud也提供了docker加速器,但是跟ustc不同,需要使用者註冊後才能使用,並且每月限制流量10GB。linux上使用比較簡單,一條指令碼命令搞定:
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://{your_id}.m.daocloud.io
實際上面的指令碼執行後,改的是/usr/lib/systemd/system/docker.service檔案,加了個–registry-mirror引數。如果不執行上面的指令碼命令,可以如下直接修改這個檔案也可:
ExecStart=/usr/bin/docker-current daemon --registry-mirror=http://{your_id}.m.daocloud.io\
設定後,需要重新載入配置&重啟:
# systemctl enable docker # systemctl daemon-reload # systemctl restart docker
但是最近使用DaoCloud的docker加速器體驗非常差,加速效果不是很明顯。
3)alicloud
阿里雲也提供了docker加速器,不過比daocloud更麻煩:不光要註冊為阿里雲的使用者,還得加入開發者平臺。
不過雖然麻煩,但是它的服務還真是不錯,pull速度很溜!配置方法跟daocloud類似,也是開通加速器以後給一個url。
可以直接去改/usr/lib/systemd/system/docker.service:
ExecStart=/usr/bin/docker-current daemon --registry-mirror=https://{your_id}.mirror.aliyuncs.com\
重新載入配置&重啟:
# systemctl enable docker # systemctl daemon-reload # systemctl restart docker
pull的時候還是顯示docker.io,但速度一點都不docker.io。
# docker pull ubuntu Using default tag: latest Trying to pull repository docker.io/library/ubuntu ... latest: Pulling from docker.io/library/ubuntu cad964aed91d: Pull complete 3a80a22fea63: Pull complete 50de990d7957: Pull complete 61e032b8f2cb: Pull complete 9f03ce1741bf: Pull complete Digest: sha256:28d4c5234db8d5a634d5e621c363d900f8f241240ee0a6a978784c978fe9c737 Status: Downloaded newer image for docker.io/ubuntu:latest
4)網易映象
網易也提供了Docker映象服務:網易蜂巢
$ sudo echo "DOCKER_OPTS=\"\$DOCKER_OPTS --registry-mirror=http://hub-mirror.c.163.com\"" >> /etc/default/docker $ service docker restart
綜上,雖然aliyun docker mirror用之前的流程有點繁瑣,但服務講真是很不錯的。不過我還是傾向於用ustc。
Docker新增特性和命令
1)docker exec
Docker 1.3 版本將使用數字簽名自動驗證所有官方庫的來源和完整性。如果一個官方映象被篡改或者被破壞,目前Docker只會對這種情況發出警告而並不阻止容器的執行。
[[email protected] ~]# docker exec --help Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] Run a command in a running container -d, --detach Detached mode: run command in the background --detach-keys Override the key sequence for detaching a container --help Print usage -i, --interactive Keep STDIN open even if not attached --privileged Give extended privileges to the command -t, --tty Allocate a pseudo-TTY -u, --user Username or UID (format: <name|uid>[:<group|gid>])
為了簡化除錯,可以使用docker exec命令通過 Docker API 和 CLI 在執行的容器上執行程式。
[[email protected] ~]# docker exec -it af40bd07fa0f /bin/bash
上例將在容器af40bd07fa0f中建立一個新的Bash會話。
2)docker create
可以通過docker run <image name>命令建立一個容器並執行其中的程式,因為有很多使用者要求建立容器的時候不啟動容器,所以docker create應運而生了。
[[email protected] docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos7 7.3.1611 d5ebea14da54 3 weeks ago 311 MB [[email protected] docker]# docker create -t -i centos7:7.3.1611 /bin/bash c51e8d8e9d214e0a842f267f738259538ce4ea744e76d66a2f6df29cc8d73748 上例建立了一個可寫的容器層,但是並不執行它。 [[email protected] docker]# docker ps [[email protected] docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c51e8d8e9d21 centos7:7.3.1611 "/bin/bash" About a minute ago Created boring_wilson 可以使用以下命令執行該容器並且登陸該容器 [[email protected] docker]# docker start -a -i c51e8d8e9d21 [[email protected] /]# [[email protected] ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c51e8d8e9d21 centos7:7.3.1611 "/bin/bash" About a minute ago Up 13 seconds boring_wilson
Docker的網路配置
Dokcer 通過使用Linux橋接提供容器之間的通訊,docker0橋接介面的目的就是方便Docker管理。當Docker daemon啟動時需要做以下操作:
1)如果docker0不存在則建立 2)搜尋一個與當前路由不衝突的ip段 3)在確定的範圍中選擇 ip 4)繫結 ip 到 docker0
1)Docker四種網路模式
docker run建立Docker容器時,可以用--net選項指定容器的網路模式,Docker有以下4種網路模式: 1)host模式,使用 --net=host指定。 2)container模式,使用 --net=container:NAMEorID 指定。 3)none模式,使用 --net=none指定。 4)bridge模式,使用 --net=bridge指定,預設設定。
host 模式
如果啟動容器的時候使用 host 模式,那麼這個容器將不會獲得一個獨立的 Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的 IP 等,而是使用宿主機的 IP 和埠。
比如:我們在 10.10.101.105/24 的機器上用 host 模式啟動一個含有 web 應用的 Docker 容器,監聽 tcp 80 埠。當我們在容器中執行任何類似 ifconfig 命令檢視網路環境時,看到的都是宿主機上的資訊。而外界訪問容器中的應用,則直接使用 10.10.101.105:80 即可,不用任何 NAT 轉換,就如直接跑在宿主機中一樣。但是,容器的其他方面,如檔案系統、程序列表等還是和宿主機隔離的。
container 模式
這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網絡卡,配置自己的 IP,而是和一個指定的容器共享 IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。兩個容器的程序可以通過 lo 網絡卡裝置通訊。
none模式
這個模式和前兩個不同。在這種模式下,Docker 容器擁有自己的 Network Namespace,但是,並不為 Docker容器進行任何網路配置。也就是說,這個 Docker 容器沒有網絡卡、IP、路由等資訊。需要我們自己為 Docker 容器新增網絡卡、配置 IP 等。
bridge模式
bridge 模式是 Docker 預設的網路設定,此模式會為每一個容器分配 Network Namespace、設定 IP 等,並將一個主機上的 Docker 容器連線到一個虛擬網橋上。當 Docker server 啟動時,會在主機上建立一個名為 docker0 的虛擬網橋,此主機上啟動的 Docker 容器會連線到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。接下來就要為容器分配 IP 了,Docker 會從 RFC1918 所定義的私有 IP 網段中,選擇一個和宿主機不同的IP地址和子網分配給 docker0,連線到 docker0 的容器就從這個子網中選擇一個未佔用的 IP 使用。如一般 Docker 會使用 172.17.0.0/16 這個網段,並將 172.17.42.1/16 分配給 docker0 網橋(在主機上使用 ifconfig 命令是可以看到 docker0 的,可以認為它是網橋的管理介面,在宿主機上作為一塊虛擬網絡卡使用)
2)列出當前主機網橋
[[email protected] ~]# brctl show //brctl工具依賴bridge-utils軟體包 bridge name bridge id STP enabled interfaces docker0 8000.024223421c41 no veth4b4f1b1
3)檢視當前 docker0 ip
[[email protected] ~]# ifconfig docker0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:23ff:fe42:1c41 prefixlen 64 scopeid 0x20<link> ether 02:42:23:42:1c:41 txqueuelen 0 (Ethernet) RX packets 181704 bytes 9952837 (9.4 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 286903 bytes 598331176 (570.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
在容器執行時,每個容器都會分配一個特定的虛擬機器口並橋接到 docker0。每個容器都會配置同 docker0 ip 相同網段的專用 ip 地址,docker0 的 IP 地址被用於所有容器的預設閘道器。
4)執行一個容器
[[email protected] ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/ubuntu latest 0ef2e08ed3fa 2 weeks ago 130 MB [[email protected] ~]# docker run -t -i -d docker.io/ubuntu /bin/bash bad5133ecd6a4c740d57621c8fdb536dd9512718a3cae371789b8063ec730944 //這個字串的前12位字元就是容器的ID [[email protected] ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bad5133ecd6a docker.io/ubuntu "/bin/bash" 33 seconds ago Up 32 seconds suspicious_rosalind [[email protected] ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.024223421c41 no veth4b4f1b1 vetheaa4add 以上, docker0 扮演著bad5133ecd6a這個容器的虛擬介面vetheaa4add interface 橋接的角色。
使用特定範圍的IP
Docker 會嘗試尋找沒有被主機使用的 ip 段,儘管它適用於大多數情況下,但是它不是萬能的,有時候我們還是需要對ip進一步規劃。Docker允許你管理docker0橋接或者通過-b選項自定義橋接網絡卡,需要安裝bridge-utils軟體包。 基本步驟如下: 1)確保docker的程序是停止的 2)建立自定義網橋 3)給網橋分配特定的ip 4)以-b的方式指定網橋 具體操作如下: $ sudo service docker stop $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 $ sudo brctl addbr bridge0 $ sudo ip addr add 192.168.5.1/24 dev bridge0 $ sudo ip link set dev bridge0 up $ ip addr show bridge0 $ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker $ sudo service docker start
5)不同主機間容器通訊
不同容器之間的通訊可以藉助於 pipework 這個工具: $ git clone https://github.com/jpetazzo/pipework.git $ sudo cp -rp pipework/pipework /usr/local/bin/ 安裝相應依賴軟體 $ sudo apt-get install iputils-arping bridge-utils -y 橋接網路 # brctl show bridge name bridge id STP enabled interfaces br0 8000.000c291412cd no eth0 docker0 8000.56847afe9799 no vetheb48029 可以刪除docker0,直接把docker的橋接指定為 br0。也可以保留使用預設的配置,這樣單主機容器之間的通訊可以通過 docker0,而跨主機不同容器之間通過pipework新建docker容器的網絡卡橋接到br0,這樣跨主機容器之間就可以通訊了。 具體操作如下: 1)ubuntu操作: $ sudo service docker stop $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 $ echo 'DOCKER_OPTS="-b=br0"' >> /etc/default/docker $ sudo service docker start 2)CentOS 7操作 $ sudo systemctl stop docker $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 $ cat /etc/sysconfig/docker | grep 'OPTIONS=' OPTIONS=--selinux-enabled -b=br0 -H fd:// $ sudo systemctl start docker
pipework
不同容器之間的通訊可以藉助於pipework這個工具給docker容器新建虛擬網絡卡並繫結IP橋接到br0 $ git clone https://github.com/jpetazzo/pipework.git $ sudo cp -rp pipework/pipework /usr/local/bin/ $ pipework Syntax: pipework <hostinterface> [-i containerinterface] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan] pipework <hostinterface> [-i containerinterface] <guest> dhcp [macaddr][@vlan] pipework --wait [-i containerinterface] 如果刪除了預設的 docker0 橋接,把 docker 預設橋接指定到了 br0,則最好在建立容器的時候加上--net=none,防止自動分配的 IP 在區域網中有衝突。 $ sudo docker run --rm -ti --net=none ubuntu:14.04 /bin/bash [email protected]:/# $ # Ctrl-P + Ctrl-Q 回到宿主機 shell,容器 detach 狀態 $ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a46657528059 ubuntu:14.04 "/bin/bash" 4 minutes ago Up 4 minutes hungry_lalande $ sudo pipework br0 -i eth0 a46657528059 192.168.115.10/[email protected] # 預設不指定網絡卡裝置名,則預設新增為 eth1 # 另外 pipework 不能新增靜態路由,如果有需求則可以在 run 的時候加上 --privileged=true 許可權在容器中手動新增, # 但這種安全性有缺陷,可以通過 ip netns 操作 $ sudo docker attach a46657528059 [email protected]:/# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 86:b6:6b:e8:2e:4d inet addr:192.168.115.10 Bcast:0.0.0.0 Mask:255.255.255.0 inet6 addr: fe80::84b6:6bff:fee8:2e4d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:9 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:648 (648.0 B) TX bytes:690 (690.0 B) [email protected]:/# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.115.2 0.0.0.0 UG 0 0 0 eth0 192.168.115.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 使用ip netns新增靜態路由,避免建立容器使用--privileged=true選項造成一些不必要的安全問題: $ docker inspect --format="{{ .State.Pid }}" a46657528059 # 獲取指定容器 pid 6350 $ sudo ln -s /proc/6350/ns/net /var/run/netns/6350 $ sudo ip netns exec 6350 ip route add 192.168.0.0/16 dev eth0 via 192.168.115.2 $ sudo ip netns exec 6350 ip route # 新增成功 192.168.0.0/16 via 192.168.115.2 dev eth0 ... ... 在其它宿主機進行相應的配置,新建容器並使用 pipework 新增虛擬網絡卡橋接到 br0,測試通訊情況即可。
另外,pipework 可以建立容器的vlan網路,這裡不作過多的介紹了,官方文件已經寫的很清楚了,可以檢視以下兩篇文章:
Pipework 官方文件
Docker 網路詳解及 pipework 原始碼解讀與實踐
Dockerfile
Docker 可以通過 Dockerfile 的內容來自動構建映象。Dockerfile 是一個包含建立映象所有命令的文字檔案,通過docker build命令可以根據 Dockerfile 的內容構建映象,在介紹如何構建之前先介紹下 Dockerfile 的基本語法結構。
Dockerfile 有以下指令選項: FROM MAINTAINER RUN CMD EXPOSE ENV ADD COPY ENTRYPOINT VOLUME USER WORKDIR ONBUILD
1)FROM
用法: FROM <image> 或者 FROM <image> FROM指定構建映象的基礎源映象,如果本地沒有指定的映象,則會自動從 Docker 的公共庫 pull 映象下來。 FROM必須是 Dockerfile 中非註釋行的第一個指令,即一個 Dockerfile 從FROM語句開始。 FROM可以在一個 Dockerfile 中出現多次,如果有需求在一個 Dockerfile 中建立多個映象。 如果FROM語句沒有指定映象標籤,則預設使用latest標籤。
2)MAINTAINER
用法: MAINTAINER <name> 指定建立映象的使用者 RUN 有兩種使用方式: RUN RUN "executable", "param1", "param2" 每條RUN指令將在當前映象基礎上執行指定命令,並提交為新的映象,後續的RUN都在之前RUN提交後的映象為基礎,映象是分層的,可以通過一個映象的任何一個歷史提交點來建立,類似原始碼的版本控制。 exec 方式會被解析為一個 JSON 陣列,所以必須使用雙引號而不是單引號。exec 方式不會呼叫一個命令 shell,所以也就不會繼承相應的變數,如: RUN [ "echo", "$HOME" ] 這種方式是不會達到輸出 HOME 變數的,正確的方式應該是這樣的 RUN [ "sh", "-c", "echo", "$HOME" ] RUN產生的快取在下一次構建的時候是不會失效的,會被重用,可以使用--no-cache選項,即docker build --no-cache,如此便不會快取。
3)CMD
CMD有三種使用方式: CMD "executable","param1","param2" CMD "param1","param2" CMD command param1 param2 (shell form) CMD指定在 Dockerfile 中只能使用一次,如果有多個,則只有最後一個會生效。 CMD的目的是為了在啟動容器時提供一個預設的命令執行選項。如果使用者啟動容器時指定了執行的命令,則會覆蓋掉CMD指定的命令。 另外注意不要弄混以下的概念: CMD會在啟動容器的時候執行,build時不執行,而RUN只是在構建映象的時候執行,後續映象構建完成之後,啟動容器就與RUN無關了
4)EXPOSE
EXPOSE <port> [<port>...] 告訴 Docker 服務端容器對外對映的本地埠,需要在 docker run 的時候使用-p或者-P選項生效。
5)ENV
ENV <key> <value> # 只能設定一個變數 ENV <key>=<value> ... # 允許一次設定多個變數 指定一個環節變數,會被後續RUN指令使用,並在容器執行時保留。 例子: ENV myName="John Doe" myDog=Rex\ The\ Dog \ myCat=fluffy 等同於 ENV myName John Doe ENV myDog Rex The Dog ENV myCat fluffy
6)ADD
ADD <src>... <dest> ADD複製本地主機檔案、目錄或者遠端檔案 URLS 從 並且新增到容器指定路徑中 。 支援通過GO的正則模糊匹配,具體規則可參見https://golang.org/pkg/path/filepath/#Match ADD hom* /mydir/ # adds all files starting with "hom" ADD hom?.txt /mydir/ # ? is replaced with any single character 路徑必須是絕對路徑,如果 不存在,會自動建立對應目錄 路徑必須是 Dockerfile 所在路徑的相對路徑 如果是一個目錄,只會複製目錄下的內容,而目錄本身則不會被複制
7)COPY
COPY <src>... <dest> COPY複製新檔案或者目錄從 並且新增到容器指定路徑中 。用法同ADD,唯一的不同是不能指定遠端檔案 URLS。
8)ENTRYPOINT
ENTRYPOINT "executable", "param1", "param2" ENTRYPOINT command param1 param2 (shell form) 配置容器啟動後執行的命令,並且不可被 docker run 提供的引數覆蓋,而CMD是可以被覆蓋的。如果需要覆蓋,則可以使用docker run --entrypoint選項。 每個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最後一個生效。 Exec form ENTRYPOINT 例子 通過ENTRYPOINT使用 exec form 方式設定穩定的預設命令和選項,而使用CMD新增預設之外經常被改動的選項。 FROM ubuntu ENTRYPOINT ["top", "-b"] CMD ["-c"] 通過 Dockerfile 使用ENTRYPOINT展示前臺執行 Apache 服務 FROM debian:stable RUN apt-get update && apt-get install -y --force-yes apache2 EXPOSE 80 443 VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] Shell form ENTRYPOINT 例子 這種方式會在/bin/sh -c中執行,會忽略任何CMD或者docker run命令列選項,為了確保docker stop能夠停止長時間執行ENTRYPOINT的容器,確保執行的時候使用exec選項。 FROM ubuntu ENTRYPOINT exec top -b 如果在ENTRYPOINT忘記使用exec選項,則可以使用CMD補上: FROM ubuntu ENTRYPOINT top -b CMD --ignored-param1 # --ignored-param2 ... --ignored-param3 ... 依此類推
9)VOLUME
VOLUME ["/data"] 建立一個可以從本地主機或其他容器掛載的掛載點,後續具體介紹。
10)USER
USER daemon 指定執行容器時的使用者名稱或 UID,後續的RUN、CMD、ENTRYPOINT也會使用指定使用者。
11)WORKDIR
WORKDIR /path/to/workdir 為後續的RUN、CMD、ENTRYPOINT指令配置工作目錄。可以使用多個WORKDIR指令,後續命令如果引數是相對路徑,則會基於之前命令指定的路徑。 WORKDIR /a WORKDIR b WORKDIR c RUN pwd 最終路徑是/a/b/c。 WORKDIR指令可以在ENV設定變數之後呼叫環境變數: ENV DIRPATH /path WORKDIR $DIRPATH/$DIRNAME 最終路徑則為 /path/$DIRNAME。
12)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 指令內容,等價於在後面添加了兩條指令。 # Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src 使用ONBUILD指令的映象,推薦在標籤中註明,例如 ruby:1.9-onbuild。
13)Dockerfile 示例
# Nginx # # VERSION 0.0.1 FROM ubuntu MAINTAINER Victor Vieux <[email protected]> RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server # Firefox over VNC # # VERSION 0.3 FROM ubuntu # Install vnc, xvfb in order to create a 'fake' display and firefox RUN apt-get update && apt-get install -y x11vnc xvfb firefox RUN mkdir ~/.vnc # Setup a password RUN x11vnc -storepasswd 1234 ~/.vnc/passwd # Autostart firefox (might not be the best way, but it does the trick) RUN bash -c 'echo "firefox" >> /.bashrc' EXPOSE 5900 CMD ["x11vnc", "-forever", "-usepw", "-create"] # Multiple images example # # VERSION 0.1 FROM ubuntu RUN echo foo > bar # Will output something like ===> 907ad6c2736f FROM ubuntu RUN echo moo > oink # Will output something like ===> 695d7793cbe4 # You᾿ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with # /oink.
14)docker build
$ docker build --help Usage: docker build [OPTIONS] PATH | URL | - Build a new image from the source code at PATH --force-rm=false Always remove intermediate containers, even after unsuccessful builds # 移除過渡容器,即使構建失敗 --no-cache=false Do not use cache when building the image # 不實用 cache -q, --quiet=false Suppress the verbose output generated by the containers --rm=true Remove intermediate containers after a successful build # 構建成功後移除過渡層容器 -t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success
15)dockerfile 最佳實踐
使用.dockerignore檔案 為了在docker build過程中更快上傳和更加高效,應該使用一個.dockerignore檔案用來排除構建映象時不需要的檔案或目錄。例如,除非.git在構建過程中需要用到,否則你應該將它新增到.dockerignore檔案中,這樣可以節省很多時間。 避免安裝不必要的軟體包 為了降低複雜性、依賴性、檔案大小以及構建時間,應該避免安裝額外的或不必要的包。例如,不需要在一個數據庫映象中安裝一個文字編輯器。 每個容器都跑一個程序 在大多數情況下,一個容器應該只單獨跑一個程式。解耦應用到多個容器使其更容易橫向擴充套件和重用。如果一個服務依賴另外一個服務,可以參考 https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/ 最小化層 我們知道每執行一個指令,都會有一次映象的提交,映象是分層的結構,對於Dockerfile,應該找到可讀性和最小化層之間的平衡。 多行引數排序 如果可能,通過字母順序來排序,這樣可以避免安裝包的重複並且更容易更新列表,另外可讀性也會更強,新增一個空行使用\換行: RUN apt-get update && apt-get install -y \ bzr \ cvs \ git \ mercurial \ subversion 建立快取 映象構建過程中會按照Dockerfile的順序依次執行,每執行一次指令 Docker 會尋找是否有存在的映象快取可複用,如果沒有則建立新的映象。如果不想使用快取,則可以在docker build時新增--no-cache=true選項。 從基礎映象開始就已經在快取中了,下一個指令會對比所有的子映象尋找是否執行相同的指令,如果沒有則快取失效。在大多數情況下只對比Dockerfile指令和子映象就足夠了。ADD和COPY指令除外,執行ADD和COPY時存放到映象的檔案也是需要檢查的,完成一個檔案的校驗之後再利用這個校驗在快取中查詢,如果檢測的檔案改變則快取失效。RUN apt-get -y update命令只檢查命令是否匹配,如果匹配就不會再執行更新了。 為了有效地利用快取,你需要保持你的 Dockerfile 一致,並且儘量在末尾修改。
Dockerfile 指令
FROM: 只要可能就使用官方映象庫作為基礎映象 RUN: 為保持可讀性、方便理解、可維護性,把長或者複雜的RUN語句使用\分隔符分成多行 不建議RUN apt-get update獨立成行,否則如果後續包有更新,那麼也不會再執行更新 避免使用RUN apt-get upgrade或者dist-upgrade,很多必要的包在一個非privileged許可權的容器裡是無法升級的。如果知道某個包更新,使用apt-get install -y xxx 標準寫法 RUN apt-get update && apt-get install -y package-bar package-foo 例子: RUN apt-get update && apt-get install -y \ aufs-tools \ automake \ btrfs-tools \ build-essential \ curl \ dpkg-sig \ git \ iptables \ libapparmor-dev \ libcap-dev \ libsqlite3-dev \ lxc=1.0* \ mercurial \ parallel \ reprepro \ ruby1.9.1 \ ruby1.9.1-dev \ s3cmd=1.1.0* CMD: 推薦使用CMD [“executable”, “param1”, “param2”…]這種格式,CMD [“param”, “param”]則配合ENTRYPOINT使用 EXPOSE: Dockerfile 指定要公開的埠,使用docker run時指定對映到宿主機的埠即可 ENV: 為了使新的軟體更容易執行,可以使用ENV更新PATH變數。如ENV PATH /usr/local/nginx/bin:$PATH確保CMD ["nginx"]即可執行 ENV也可以這樣定義變數: 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 ADDorCOPY:ADD比COPY多一些特性「tar 檔案自動解包和支援遠端 URL」,不推薦新增遠端URL 如不推薦這種方式: ADD http://example.com/big.tar.xz /usr/src/things/ RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things RUN make -C /usr/src/things all 推薦使用 curl 或者 wget 替換,使用如下方式: RUN mkdir -p /usr/src/things \ && curl -SL http://example.com/big.tar.gz \ | tar -xJC /usr/src/things \ && make -C /usr/src/things all 如果不需要新增 tar 檔案,推薦使用COPY。
Docker容器資料管理
docker管理資料的方式有兩種: 資料卷 資料卷容器
1)資料卷
資料卷是一個或多個容器專門指定繞過Union File System的目錄,為持續性或共享資料提供一些有用的功能: 1)資料卷可以在容器間共享和重用 2)資料卷資料改變是直接修改的 3)資料卷資料改變不會被包括在容器中 4)資料卷是持續性的,直到沒有容器使用它們 5)新增一個數據卷 你可以使用-v選項新增一個數據卷,或者可以使用多次-v選項為一個 docker 容器執行掛載多個數據卷。 $ sudo docker run --name data -v /data -t -i ubuntu:14.04 /bin/bash # 建立資料卷繫結到到新建容器,新建容器中會建立 /data 資料卷 bash-4.1# ls -ld /data/ drwxr-xr-x 2 root root 4096 Jul 23 06:59 /data/ bash-4.1# df -Th Filesystem Type Size Used Avail Use% Mounted on ... ... ext4 91G 4.6G 82G 6% /data 建立的資料卷可以通過docker inspect獲取宿主機對應路徑 $ sudo docker inspect data ... ... "Volumes": { "/data": "/var/lib/docker/volumes/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9" }, # 可以看到建立的資料卷宿主機路徑 ... ... 或者直接指定獲取 $ sudo docker inspect --format="{{ .Volumes }}" data map[/data: /var/lib/docker/volumes/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9] 掛載宿主機目錄為一個數據卷 -v選項除了可以建立卷,也可以掛載當前主機的一個目錄到容器中。 $ sudo docker run --name web -v /source/:/web -t -i ubuntu:14.04 /bin/bash bash-4.1# ls -ld /web/ drwxr-xr-x 2 root root 4096 Jul 23 06:59 /web/ bash-4.1# df -Th ... ... ext4 91G 4.6G 82G 6% /web bash-4.1# exit 預設掛載卷是可讀寫的,可以在掛載時指定只讀 $ sudo docker run --rm --name test -v /source/:/test:ro -t -i ubuntu:14.04 /bin/bash
2)建立和掛載一個數據卷容器(這樣即使刪除了剛開始的第一個資料卷容器或者中間層的資料卷容器,只要有其他容器使用資料卷,資料卷都不會被刪除的。)
如果你有一些永續性的資料並且想在容器間共享,或者想用在非永續性的容器上,最好的方法是建立一個數據卷容器,然後從此容器上掛載資料。 這樣就可以在容器之間共享資料了。 建立資料卷容器 $ sudo docker run -t -i -d -v /test --name test ubuntu:14.04 echo hello 使用--volumes-from選項在另一個容器中掛載 /test 卷。不管 test 容器是否執行,其它容器都可以掛載該容器資料卷,當然如果只是單獨的資料卷是沒必要執行容器的。 $ sudo docker run -t -i -d --volumes-from test --name test1 ubuntu:14.04 /bin/bash 新增另一個容器 $ sudo docker run -t -i -d --volumes-from test --name test2 ubuntu:14.04 /bin/bash 也可以繼承其它掛載有 /test 卷的容器 $ sudo docker run -t -i -d --volumes-from test1 --name test3 ubuntu:14.04 /bin/bash
3)備份、恢復或遷移資料卷
資料卷備份
$ sudo docker run --rm --volumes-from test -v $(pwd):/backup ubuntu:14.04 tar cvf /backup/test.tar /test tar: Removing leading `/' from member names /test/ /test/b /test/d /test/c /test/a 以上命令表示: 啟動一個新的容器並且從test容器中掛載卷,然後掛載當前目錄到容器中為backup,並備份test卷中所有的資料為test.tar,執行完成之後刪除容器--rm,此時備份就在當前的目錄下,名為test.tar。 注意:後面的/test是資料卷的目錄路徑(即資料卷建立時在容器裡的路徑) $ ls 宿主機當前目錄下產生了test卷的備份檔案test.tar ---------------------------------------------看看下面的一個例項--------------------------------------------- 先建立一個容器wang,包含兩個資料卷/var/volume1和/var/volume2(這兩個目錄是在容器裡的資料卷路徑) [[email protected] ~]# docker run -t -i -v /var/volume1 -v /var/volume2 --name wang docker.io/centos /bin/bash [[email protected] /]# 根據Docker的資料持久化之資料卷容器可知,上面建立的wang資料卷容器掛載了/var/volume1和/var/volume2兩個目錄 然後在資料卷裡寫些資料,以供測試。 [[email protected] /]# cd /var/volume1 [[email protected] volume1]# echo "test1" > test1 [[email protected] volume1]# echo "test11" > test11 [[email protected] volume1]# echo "test111" > test111 [[email protected] volume1]# ls test1 test11 test111 [[email protected] volume1]# cd ../volume2 [[email protected] volume2]# echo "test2" > test2 [[email protected] volume2]# echo "