1. 程式人生 > >Docker入門到實踐(上)

Docker入門到實踐(上)

虛擬化技術 容器

Docker是一個開源的應用容器引擎,開發可以打包自己的應用或者是依賴包上傳到可移植的容器裏,然後進行發布到任何linux機器上,也可實現虛擬化

容器是完全使用沙箱機制的,相互之間不會存在任何接口,幾乎沒有額外的性能開銷,很容易的在機器和數據中興運行,最重要的是不依賴任何語言,框架或者是操作系統

Docker項目是實現輕量級的操作系統虛擬化解決方案,docker的基礎是LXC等技術,在LXC的基礎上,docker進行封裝,使得用戶不用關心容器的管理,操作更加簡單;

那麽Docker和傳統虛擬化(KVM,XEN等)有什麽區別嗎?

docker是在操作系統層面上實現的虛擬化技術,直接復用本地操作系統,而傳統的虛擬化是在硬件基礎上的,虛擬出自己的系統,然後再在系統上部署相應的軟件服務

【基本概念】

1)鏡像(Image)

docker鏡像就是一個只讀的模板,例如:一個鏡像包含一個完整的操作系統環境,裏面僅安裝了服務應用程序

鏡像可以用來創建容器的,docker提供了一個很簡單的機制來創建或者更新現有的鏡像,用戶甚至可以直接從第三方獲取已經做好的鏡像來使用,

2)容器(Container)

docker利用容器運行應用

容器是從鏡像創建的運行實例,可以被啟動,停止,刪除等操作,每個容器都是相互隔離的,從而實現安全性

可以把容器看作是一個簡易版的Linux系統環境(包括root用戶權限,進程空間,用戶空間,網絡空間等)運行在其中的應用程序

Ps:鏡像是只讀的,容器在運行啟動的時候創建了可寫層,作為最上層

3)倉庫(Repository)

倉庫 是集中存放鏡像文件的場所,分為公有倉庫(Public)和私有倉庫(Private)兩種形式,

最大的公開倉庫是Dcoekr Hub,存放了數量龐大的鏡像供用戶下載,國內的公開倉庫包括Docker Pool等,可以提供大陸用戶更穩定快速的訪問,當然用戶可以在本地網絡內創建一個私有倉庫。

Ps:docker倉庫的概念跟Git類似,註冊服務器可以理解為GitHub這樣的托管服務

【Docker安裝】

# docker search centos #搜索可用的docker鏡像

技術分享圖片

# docker pull docker.io/centos #下載鏡像

安裝docker之後啟動docker服務,並設置開機自啟

[root@localhost ~]# systemctl start docker
[root@localhost ~]# chkconfig docker on

[Docker鏡像]

Docker運行容器前需要本地存在對應的鏡像,如果鏡像不存在本地,docker會從鏡像倉庫下載(默認是Docker Hub公共註冊服務器中的倉庫)

1)獲取鏡像

可以使用docker pull命令從倉庫獲取所需要鏡像,下載過程中,會輸出鏡像的每一層信息。

例如:# docker pull docker.io/centos

[root@localhost ~]# docker pull nginx
Using default tag: latest
Trying to pull repository docker.io/library/nginx ...
latest: Pulling from docker.io/library/nginx
f2aa67a397c4: Pull complete
3c091c23e29d: Pull complete
4a99993b8636: Pull complete
Digest: sha256:0fb320e2a1b1620b4905facb3447e3d84ad36da0b2c8aa8fe3a5a81d1187b884
Status: Downloaded newer image for docker.io/nginx:latest

下載完成後,我們可以隨時使用該鏡像,例如創建一個容器,讓其中運行bash應用

[root@localhost ~]# docker run -t -i e934aafc2206 /bin/bash
[root@4069ed2f1da9 /]#

2)列出本地鏡像

# docker images

技術分享圖片

Ps:參數詳解:

REPOSITORY:鏡像倉庫名稱

TAG:鏡像標記,默認latest

IMAGE ID:鏡像ID

CREATE:創建時間

SIZE:鏡像大小

3)創建鏡像

創建鏡像很多種方法,用戶可以從docker hub獲取已有的鏡像並更新,也可以利用本地文件系統創建一個

修改已有的鏡像

先試用pull下載的鏡像啟動容器

[root@localhost ~]# docker run -itd --name Centos7.x e934aafc2206 /bin/bash
ae890b0784421c6ade9dca9fd7e02523a3e1aaf15d211b0d173e417cd2b83942

[root@ae890b078442 /]# yum install -y net-tools httpd httpd-server

當我們結束後,使用exit提出來之後,容器已經被我們改變了,使用docker commit命令來提交更新後的副本

格式:docker commit [容器ID] [目標鏡像倉庫名:tag信息]

[root@localhost ~]# docker commit b73ba30f94d0 Centos7.4/web:version1
sha256:6c317c7092f42b5f44f02027738cc4f9fb27806693230afd02f0b66af1803847

ps:docker commit 後面可以加上-m參數,用來指定提交說明信息;-a可以指定更新用戶信息;其實這些都可以省略

我們docker images查看新提交的鏡像

技術分享圖片

#之後再使用這個鏡像啟動容器,進入到容器裏面,我們會發現之前的操作記錄都會保存在裏面

[root@localhost ~]# docker run -itd --name centoswebserver 6c317c7092f4 /usr/sbin/init /sbin/bash
0a2b120aaec9297368535074f09d9f274eb98996bdc6837ad59c2666df1de33a

【利用dockerfile來創建鏡像】

使用戶docker commit來擴展一個鏡像比較簡單,但是不便於分享,我們可以通過docker build來創建一個新的鏡像,但是前提是我們需要創一個dockerfile,包含一些如何創建鏡像的指令

Dockerfile基本語法是:

*使用#註釋

*FROM指令告訴docker使用哪個鏡像作為基礎

*接著是維護者信息

*RUN開頭的指令會在創建中運行,比如說安裝一個軟件包,在這裏使用apt-get來安裝了一些軟件

編寫dockerfile後可以使用docker build來生成鏡像

[root@localhost ~]# vim dockerfile

FROM docker.io/centos:latest
MAINTAINER hexunbixiaoyu
RUN yum install -y pcre-devel openssl-devel
RUN yum install -y httpd httpd-devel httpd-server
RUN echo "This is hexun.com" >> /var/www/html/index.html
EXPOSE 80
CMD ["/usr/sbin/apachectl","-D "FOREGROUD"]

[root@localhost ~]# docker build -t="docker.io/centos" .

PS:其中-t標記來添加tag,指定新的景象用戶信息、“.”時候dpclerfile所在的路徑(當前目錄)也可以替換為一個具體的dockerfile路徑

執行的過程中我們可以看到build進程在執行操作,要做的第一件事情就是上傳dockerfile內容,因為所有的操作都要一句dockerfile來進行,然後dockerfile中的指令被一條一條的執行,每一步都創建一個新的容器,在容器中執行指令並提交修改(這一點和之前介紹的docker cimmit一樣)當所有的指令都執行完畢之後 ,返回最終的鏡像ID,所有的中間步驟所產生的容器都被刪除和清理;

Ps:註意一個鏡像不能超過127層

此外還可以利用ADD命令賦值本地文件到鏡像,用EXPOSE命令來向外開放端口 ,用CMD命令來描述容器啟動後臺運行的程序等

還可以用docker tag 命令來修改鏡像標簽名稱

# docker tag ce1247d52651 docker.io/centos:Version

【從本地文件系統導入 】

要從本地系文件系統導入一個鏡像,可以使用openvz(容器須奴話先鋒技術)的模板來創建;openvz的模板下載地址為https://openvz.org/Download/templates/precreated

#cat centos-7-x86_64-minimal.tar.gz | docker import - centos7:7.33

技術分享圖片

上傳鏡像

用戶可以通過docker push命令,把自己創建的鏡像上傳到倉庫中來共享.例如:將做好的鏡像上傳到自己的docker hub倉庫中

上傳docker hub鏡像需註意其過程:

自定義鏡像之是存在本地images列表的

1:登陸docker hub:docker login

2:修改需要上傳的鏡像標簽tag:docker tag <imageID> <namespace>/<image name>:<version tag>

3:開始上傳:docker push <namespace>/<image name>:<version tag>

# docker push bixiaoyu/dockercentos:1.1

技術分享圖片

下載鏡像docker pull <nemaspace>/<image name>:<version tag>

# docker pull bixiaoyu/dockercentos:1.1

[存出和載入鏡像]

如果要導出鏡像到本地文件,可以使用docker save 命令

格式:docker save -o <鏡像最新名稱> <REPOSITOR>

技術分享圖片

# docker save -o centos.tar centos/docker:version2

# 載入鏡像

可以使用docker load 從導出的本地文件中在導入到本地鏡像;這將導入鏡像以及其相關的元數據信息(包括標簽等)

# docker load --input centos.tar

或者

docker load < centos.tar

鏡像的實現原理】

Docke鏡像是如何實現增量的修改和維護呢?每個鏡像都有很多層次的構成,docker使用union FS將這些不同的層集合到一個鏡像中

PS:通常Union FS有兩個用途,一方面可以實現不借助LVM,RAID將多個disk掛載到同一個目錄下,另一個更常用的就是將一個制度的分支和一個可寫的分支聯合在一起,Live CD正是基於此方法可以允許在鏡像不變的基礎上允許用戶在其上進行一些寫操作,Docker在AUFS上構建的容器也就是利用了類似的原理

【Docker容器】

容器是docker又一核心概念

簡單的是獨立運行的一個或一組應用,以及它們的運行狀態環境,對應的,虛擬機可以理解為模擬運行的一整套操作系統(提供了運行狀態環境和其他系統環境 )和跑在上面的應用

當利用docker run來創建容器時,docker在後臺運行的標準操作包括:

#檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載

#利用鏡像創建並啟動一個容器

#分配一個文件系統,並在只讀的鏡像層外面在封裝一層讀寫層

#從宿主機配置的網橋接口中關聯一個虛擬接口到容器中去

#從地址池配置一個IP地址給容器

#執行用戶指定的容器

#執行完畢後容器被終止

當我們docker start命令將已經終止的容器啟動運行,我們會發現容器的核心為所執行的應用程序,所需要的資源都是應用程序運行必須的,除此之外,我們可以進入容器,利用ps或者top來查看一下進程信息;可見,容器僅僅是運行了指定的bash應用,這種特點,對docker資源利用非常高 ,是真正意義上的輕量級虛擬化

要獲取docker容器啟動輸出信息,可以通過docler logs 命令來輸出

技術分享圖片

【導出和導入容器】

導出容器

技術分享圖片

[root@www-jfedu-net ~]# docker export b54d8cc3a14c > version.tar

這樣將導出的容器快照到本地文件

導入容器快照

可以使用docker import從容器快照文件中再導入為鏡像,例如

# cat version.tar | docker import - version2
sha256:d7d484184868990927f83fe4ace8ce7c0f55d14bcf7ed3ec479d7357e2aff2f6

Ps:用戶既可以使用docker load來導入鏡像存儲文件到本地images鏡像庫,也可以使用docker import 來導入一個容器快照到本地鏡像庫,這兩者區別在於容器快照文件將丟失所有的歷史記錄和元數據信息(只保存容器當時的快照狀態)而鏡像存儲文件將保存完整的記錄,體積也大,此外,從容器快照文件導入時可以重新指定標簽等元數據信息;

[Docker網絡通信]

基於Docker run創建的docker容器時,可以使用--net選項指定容器的的網絡模式,Docker默認有一下四種網絡模式:

host模式:使用--net=host指定;

container模式:使用--net=container:NAME或者ID指定

none模式,使用--net=none指定

bridge模式,使用--net=bridge指定,默認設置;

1)Host模式:

默認docker容器運行會分配獨立的network Namespace隔離子系統,基於host模式,容器將不會獲得獨立的Network Namespace,而是和宿主機共用一個network namespace,容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口

2)Container模式詳解:

container模式指定新建的容器與容器之間共享network namespace,而不是和宿主機共享,也就是說新創建的容器不會創建自己的網卡,配置自己的IP,而是和一個指定的容器共享IP和端口範圍。同樣兩個容器除了網絡方面相同之外,其他的如文件系統,進程列表還是隔離的,

3)None模式詳解

None模式與其他模式都不同,如果處於None模式,docker容器擁有自己的network Namespace,但是並不為docker容器進行任何網絡配置,也就是說None模式下容器沒有任何網路配置,包括網卡IP,路由信息,需要手工為docker容器添加網卡,配置IP等,典型的pipework工具為docker容器指定IP等信息;

4)Bridge橋接模式

Bridge模式是docker默認的網絡模式,該模式會為每一個docker容器分配network namespace,設置IP,路由等配置,默認會將docker容器連接到一個虛擬網橋交換Docker0上

技術分享圖片

Docker入門到實踐(上)