Docker是Docker Inc公司開源的一項基於Ubuntu LXC技術構建的應用容器引擎Docker Engine的簡稱,徹底基於Go語言開發並遵照Apache2.0協議開源。Docker可讓開發者打包應用以及依賴包到一個輕量級、可移植的容器中,而後發佈到任何流行的Linux版本機器上,也能夠實現虛擬化。Docker容器徹底使用沙箱機制,容器相互之間不會有任何接口,而且容器性能開銷極低。
Docker最初在Ubuntu 12.04上基於LXC實現,從0.7版本開始使用自行開發的libcontainer,從1.11開始,進一步演進爲使用runC和containerd。RedHat從RHEL6.5開始對Docker進行支持。
Docker官網:http://www.docker.com
Github Docker源碼:https://github.com/docker/dockerlinux
Docker Engine是一個Client-Server應用程序,包含三個組件:
A、docker daemon,是Docker守護進程。
B、REST API接口,用於與守護進程進行通訊。
C、Docker CLI,命令行界面(CLI)客戶端。
Docker引擎組件的流程以下:git
Docker優勢以下:
(1)更高效地利用系統資源
Docker容器不須要硬件虛擬技術支持,是內核級的虛擬化,不須要運行完整操做系統,能夠實現更高性能。不管是應用執行速度、內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。所以,與虛擬機技術相比,相同配置的主機能夠運行更多數量的應用。
(2)更快的啓動時間
傳統的虛擬機技術啓動應用服務每每須要數十秒,而Docker容器應用直接運行於宿主機內核,無需啓動完整的操做系統,所以能夠作到秒級、甚至毫秒級的啓動時間,大大節約開發、測試、部署時間。
(3)一致的運行環境
開發過程當中一般存在環境一致性問題。因爲開發環境、測試環境、生產環境不一致,致使有些bug並未在開發過程當中被發現,而Docker的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性。
(4)快速交付和部署
使用Docker能夠經過定製應用鏡像來實現持續集成、持續交付、部署。開發人員能夠經過Dockerfile來進行鏡像構建,並結合持續集成(Continuous Integration) 系統進行集成測試;而運維人員則能夠直接在生產環境中快速部署鏡像,甚至結合持續部署(Continuous Delivery/Deployment)系統進行自動部署,並且使用Dockerfile使鏡像構建透明化,不只開發團隊能夠理解應用運行環境,也方便運維團隊理解應用運行所需條件,幫助更好的生產環境中部署鏡像。
(5)更輕鬆的遷移
因爲Docker 確保了執行環境的一致性,使得應用的遷移更加容易。Docker能夠在多種平臺上運行,不管是物理機、虛擬機、公有云、私有云,其運行結果是一致的。所以用戶能夠很輕易地將在一個平臺上運行的應用遷移到另外一個平臺上,而不用擔憂運行環境的變化致使應用沒法正常運行的狀況。
(6)更輕鬆的維護和擴展
Docker使用的分層存儲以及鏡像的技術,使得應用重複部分的複用更爲容易,也使得應用的維護更新更加簡單,基於基礎鏡像進一步擴展鏡像很是簡單。此外,Docker團隊同各個開源項目團隊一塊兒維護了大批高質量的官方鏡像,既能夠直接在生產環境使用,又能夠做爲基礎進一步定製,大大下降了應用服務的鏡像製做成本。github
虛擬機是一個運行在宿主機上的完整的操做系統,虛擬機運行自身操做系統會佔用較多的CPU、內存、硬盤資源。Docker容器不一樣於虛擬機,只包含應用程序以及依賴庫,基於libcontainer運行在宿主機上,並處於一個隔離的環境中,所以Docker容器更加輕量高效,啓動Docker容器只需幾秒鐘內完成。因爲Docker容器輕量、資源佔用少,使得Docker能夠輕易地應用到構建標準化的應用中。Docker容器缺點以下:
(1)隔離效果不如虛擬機,須要共享宿主機操做系統的一些基礎庫等。
(2)網絡配置功能相對簡單,主要以橋接方式爲主。
(3)查看日誌也不夠方便靈活。docker
Docker架構遵循C/S架構,分爲客戶端、Docker主機、Docker鏡像倉庫三部分。
客戶端(Client):Docker提供命令行界面(CLI)工具,客戶端與Docker守護進程交互。當使用docker命令時,客戶端將相應Docker命令發送到Docker主機的Docker守護進程進行運行,客戶端能夠構建、運行和中止應用程序。
Docker主機:包含容器、鏡像和Docker守護程序,提供完整的環境來執行和運行應用程序。Docker守護進程是一個用於監聽Docker API請求的進程,用於管理Docker對象,如Docker鏡像、容器、網絡等。
鏡像倉庫(Registry):Docker鏡像倉庫用於存儲Docker鏡像。Docker提供的Docker Hub和Docker Cloud是公共鏡像倉庫,Docker默認在Docker Hub上查找映像。當使用docker pull或docker run命令時,從配置的Docker鏡像倉庫中提取所需的鏡像;當使用docker push命令時,鏡像被推送到配置的鏡像倉庫中。shell
Docker鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。Docker鏡像不包含任何動態數據,其內容在構建後也不會被改變。
Docker的分層存儲架構充分利用了Union FS技術。Docker鏡像由一組文件系統或是多層文件系統聯合組成。Docker鏡像會一層層構建,前一層是後一層的基礎,每一層構建完就不會再發生改變,後一層上的任何改變只發生在本身本層。好比,刪除前一層文件的操做不是真的刪除前一層的文件,而是僅在當前層標記爲文件已刪除。在Docker容器運行時,雖然不會看到文件,但實際上文件會一直跟隨鏡像。所以,在構建Docker鏡像時須要額外當心,每一層儘可能只包含該層須要添加的東西,任何額外的東西應該在本層構建結束前清理掉。
分層存儲的特徵使得Docker鏡像的複用、定製變的更爲容易,可使用構建好的鏡像做爲基礎層,而後進一步添加新層以定製本身所需的內容,構建新鏡像。json
Docker鏡像是靜態的定義,Docker容器是Docker鏡像運行時的實例,Docker容器能夠被建立、啓動、中止、刪除、暫停等。
Docker容器的本質是進程,但與直接在宿主機執行的進程不一樣,Docker容器進程運行於屬於本身的獨立的命名空間。所以Docker容器能夠擁有本身的root文件系統、本身的網絡配置、本身的進程空間,甚至本身的用戶ID空間。Docker容器內的進程是運行在一個隔離的環境裏,使得容器封裝的應用比直接在宿主機運行更加安全。Docker容器使用分層存儲,每個Docker容器運行時,以鏡像爲基礎層,在其上建立一個當前容器的存儲層。容器存儲層的生存週期和容器同樣,容器消亡時容器存儲層也隨之消亡。所以,任何保存於容器存儲層的信息都會隨容器刪除而丟失。
按照Docker最佳實踐要求,Docker容器不該該向其存儲層內寫入任何數據,Docker容器存儲層要保持無狀態化,全部的文件寫入操做都應該使用數據卷(Volume)、或者綁定宿主機目錄,在數據卷或宿主機目錄位置的讀寫會跳過容器存儲層,直接對宿主機(或網絡存儲)發生讀寫,其性能和穩定性更高。數據卷的生存週期獨立於容器,容器消亡,數據卷不會消亡。所以,使用數據卷後,Docker容器刪除或者從新運行後,數據卻不會丟失。vim
Docker默認Registry是Docker公司運營提供的公共鏡像倉庫即Docker Hub,但訪問Docker Hub速度一般很慢,所以能夠在本地部署一個私有Registry只供局域網內使用。windows
Homebrew的Cask已經支持Docker for Mac:
加速器配置使用網易的鏡像地址:http://hub-mirror.c.163.com。
在任務欄點擊Docker for mac應用圖標->Perferences... ->Daemon ->Registry mirrors。
在列表中填寫加速器地址。修改完成後,點擊 Apply & Restart 按鈕,Docker就會重啓並應用配置的鏡像地址。
經過docker info來查看是否配置成功。安全
Docker運行在RHEL7上,要求系統爲64位、系統內核版本爲3.10以上。
Docker運行在 RHEL6.5 或更高的版本要求系統爲64位、系統內核版本爲2.6.32-431或者更高版本。
本文使用RHEL7.3安裝Docker。
安裝Docker:sudo yum install docker
啓動Docker:sudo systemctl start docker
錯誤信息:Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
查看錯誤信息:systemctl status docker.service
錯誤緣由:SELinux不支持Docker服務
解決方法:編輯sudo vim /etc/sysconfig/docker網絡
OPTIONS='--selinux-enabled=false --log-driver=journald --signature-verification=false' if [ -z "${DOCKER_CERT_PATH}" ]; then DOCKER_CERT_PATH=/etc/docker fi
運行示例:sudo docker run hello-world
Win七、Win8須要利用Docker Toolbox來安裝,國內可使用阿里雲的鏡像來下載。
Docker ToolBox下載地址:
http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/
Docker ToolBox是一個工具集,主要包含:
A、Docker CLI客戶端,用來運行docker引擎建立鏡像和容器
B、Docker Machine,用於在Windows的命令行中運行docker引擎命令
C、Docker Compose,用來運行Docker Compose命令
D、Kitematic,Docker的GUI版本
E、Docker QuickStart shell,配置好Docker的命令行環境
F、Oracle VM Virtualbox,虛擬機
下載完成後直接點擊安裝,安裝成功後,會出現三個圖標:
點擊Docker QuickStart圖標來啓動Docker Toolbox終端。
若是系統顯示User Account Control窗口來運行VirtualBox,選擇 Yes。
對於Win10專業版系統,Docker有專門的的安裝包,須要開啓Hyper-V。
Win10專業版系統Docker下載地址:
https://store.docker.com/editions/community/docker-ce-desktop-windows
Docker使用daemon.json文件做爲Docker服務的配置文件,Linux操做系統使用/etc/docker/daemon.json,Windows操做系統使用%programdata%\docker\config\daemon.json來配置Docker服務。若是相應目錄下不存在daemon.json文件,須要建立。
{ "registry-mirrors": ["http://hub-mirror.c.163.com"] }
網易的鏡像地址:http://hub-mirror.c.163.com。
爲了實現每一個用戶實例之間相互隔離,硬件虛擬化方法的解決方案是VM,而LXC的解決方案是container,即kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace將container的進程、網絡、消息、文件系統、UTS(UNIX Time-sharing System)和用戶空間隔離開。
(1)pid namespace
不一樣用戶的進程經過pid namespace隔離開,且不一樣namespace中能夠有相同pid。全部的LXC進程在Docker中的父進程爲Docker進程,每一個LXC進程具備不一樣的namespace,同時因爲容許嵌套,所以能夠很方便的實現 Docker in Docker。
(2)net namespace
經過pid namespace,每一個namespace中的pid可以相互隔離,但網絡端口還共享host的端口。網絡隔離是經過net namespace實現的,每一個net namespace有獨立的network devices、IP addresses、IP routing tables、/proc/net目錄。經過net namespace,每一個container的網絡就能隔離開來。Docker默認採用veth的方式將容器中的虛擬網卡同宿主機上的一個docker bridge:docker0鏈接在一塊兒。
(3)ipc namespace
container中進程交互採用linux常見的進程間交互方法(interprocess communication - IPC),包括常見的信號量、消息隊列和共享內存。然而與VM不一樣,container的進程間交互仍是host上具備相同pid namespace中的進程間交互,所以須要在IPC資源申請時加入namespace信息——每一個IPC 資源有一個惟一的32位 ID。
(4)mnt namespace
mnt namespace容許不一樣namespace的進程看到的文件結構不一樣,每一個namespace中的進程所看到的文件目錄就被隔離開。每一個namespace 中的container在/proc/mounts的信息只包含所在namespace的mount point。
(5)uts namespace
UTS(UNIX Time-sharing System)namespace容許每一個container擁有獨立的hostname和domain name,使其在網絡上能夠被視做一個獨立的節點而非Host上的一個進程。
(6)user namespace
每一個container能夠有不一樣的user和group id,能夠在container內部用container內部的用戶執行程序而非Host上的用戶。
cgroups實現了對資源的配額和度量。在/cgroup目錄下新建一個文件夾便可新建一個group,在此文件夾中新建task文件,並將pid 寫入該文件,便可實現對該進程的資源控制。groups能夠限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系統的資源,每一個子系統的詳細說明以下:
有序列表blkio子系統設置限制每一個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等。
cpu子系統使用調度程序爲cgroup任務提供cpu的訪問。
cpuacct:產生cgroup任務的cpu資源報告。
cpuset:對於多核心CPU,cpuset子系統會爲cgroup任務分配單獨的cpu和內存。
devices容許或拒絕cgroup任務對設備的訪問。
freezer暫停和恢復cgroup任務。
memory設置每一個cgroup的內存限制以及產生內存資源報告。
net_cls標記每一個網絡包以供cgroup方便使用。
ns名稱空間子系統。
AUFS(Another Union FS)是一種Union FS,支持將不一樣目錄掛載到同一個虛擬文件系統下的文件系統。AUFS支持爲每個成員目錄設定readonly、readwrite和whiteout-able權限,同時AUFS有分層的概念,對readonly權限的branch能夠邏輯上進行修改(增量地,不影響readonly部分)。
一般Union FS有兩個用途,一是能夠實現不借助LVM、RAID將多個disk掛到同一個目錄下;一個是將一個readonly的branch和一個writeable的 branch聯合在一塊兒(Live CD能夠容許在OS image不變的基礎上容許用戶在其上進行一些寫操做)。
典型的啓動Linux運行須要兩個FS:bootfs + rootfs
bootfs(boot file system)主要包含bootloader 和 kernel,bootloader引導加載kernel,當boot成功後kernel被加載到內存中後bootfs就被umount。rootfs(root file system)包含典型Linux系統中的dev、proc、bin、etc等標準目錄和文件。不一樣Linux發行版中bootfs基本是一致的,但rootfs會有差異,所以不一樣Linux發行版能夠共用bootfs。
典型Linux在啓動後,首先將rootfs設置爲readonly,進行一系列檢查,而後將其切換爲readwrite供用戶使用。在Docker中,初始化時將rootfs以readonly方式加載並檢查,而後利用union mount方式將一個 readwrite文件系統掛載在readonly的rootfs上,而且容許再次將下層FS(file system)設定爲readonly,而且向上疊加,readonly和writeable組成的結構構成一個container的運行時態,每個FS被稱做一個FS層。
基於AUFS的特性,每個對readonly層文件/目錄的修改都只會存在於上層writeable層中。因爲不存在競爭,多個container能夠共享readonly的FS層。所以,Docker將readonly的FS層稱做image。Docker容器中,rootfs是read-write的,但全部的修改都寫入最上層writeable層中,image不保存用戶狀態,只用於模板、新建和複製使用。
上層image依賴下層image,所以Docker中把下層image稱做父image,沒有父image的image稱做base image。所以要從一個image啓動一個容器,Docker會先加載image自己和依賴的父images以及 base image,用戶進程運行在writeable的layer中。全部parent image中的數據信息以及ID、網絡和LXC管理的資源限制等具體container的配置,構成一個Docker上的container。
Docker的安全特性包括三個方面:A、由kernel namespaces和cgroups實現的Linux系統固有的安全標準;B、Docker Deamon安全接口;C、Linux自己的安全加固解決方案,例如AppArmor,SELinux;