Docker的架構與自制鏡像的發佈

一. docker 是什麼

你們都知道虛擬機吧,windows 上裝個 linux 虛擬機是大部分程序員的經常使用方案。公司生產環境大多也是虛擬機,虛擬機將物理硬件資源虛擬化,按需分配和使用,虛擬機使用起來和真實操做系統如出一轍,當廢棄不用時直接刪除虛擬機文件便可回收資源,很方便集中管理。php

因爲虛擬機很是龐大,同時對硬件資源的消耗也大,linux 發展出了另外一種虛擬化技術,即 linux 容器(Linux Containers,縮寫爲 LXC),它並不像虛擬機那樣模擬一個完整的操做系統,卻提供虛擬機同樣的效果。若是說虛擬機是操做系統級別的隔離,那麼容器就是進程級別的隔離,能夠想象這種級別隔離的優勢,無疑是快速的,節省資源的。java

docker 就是對 linux 容器的封裝,提供簡單實用的用戶接口,是目前最流行的 linux容器解決方案。node

下面是百科的定義:linux

docker 是基於 Go 語言的開源的應用容器引擎,並聽從Apache2.0協議,docker 讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的 linux 機器上,也能夠實現虛擬化。容器是徹底使用沙箱機制,相互之間不會有任何接口。nginx

二. docker 解決什麼問題

1. 解決虛擬機資源消耗問題。git

服務器操做系統之上運行着虛擬機,虛擬機上運行着客戶操做系統,客戶操做系統之上運行着用戶的應用程序,一臺服務器 80% 的資源開銷都花費在了硬件虛擬化和客戶機操做系統自己。程序員

圖1. 虛擬機架構與容器架構區別

圖1. 虛擬機架構與容器架構區別github

如圖 1 所示,若是採用 docker 容器技術,容器上運行着虛擬服務器,虛擬服務器中運行着用戶的應用程序,虛擬服務器和服務器操做系統使用同一內核,虛擬服務器的文件系統使用物理服務器的文件系統,但作了隔離,看上去每一個虛擬服務器都有本身獨立的文件系統;在物理服務器上創建了虛擬網橋設備,每一個虛擬服務器經過虛擬網橋設備鏈接網絡。虛擬服務器直接使用物理服務器的CPU、內存、硬盤,並不對硬件進行虛擬化,所以沒有硬件虛擬化和客戶機操做系統佔用的資源消耗,每一臺虛擬服務器的性能接近於物理服務器性能。web

一臺普通家用電腦運行一個 Linux 虛擬機可能已經很是卡,可是卻可使用 docker 虛擬出幾十甚至上百臺虛擬的 linux 服務器。若是換成性能強勁的服務器,使用 docker 就能夠提供私有云服務了。面試

2. 快速部署。

軟件開發的難題在於環境配置,在本身電腦上運行的軟件,換一臺機器可能就沒法運行,除非保證操做系統的設置正確,各類組件和庫的正確安裝。好比部署一個 Java 開發的 web 系統,計算機必須安裝 Java 和正確的環境變量,可能還須要安裝 tomcat、nginx。換臺機器部署就要重來一次。

使用 docker 能夠將應用程序及依賴打包在一個文件裏(docker 鏡像文件),運行這個文件就會啓動虛擬服務器,在虛擬服務器啓動應用程序或服務,就像在真實在物理機上運行同樣,有了 docker,就能夠一次部署,到處運行,也能夠用於自動化發佈。

3. 提供一次性的環境。

好比,本地測試他人的軟件、持續集成的時候提供單元測試和構建的環境,啓動或關閉一個虛擬服務器就像啓動或關閉一個進程同樣簡單和快速。

4. 提供彈性的雲服務。

由於 Docker 容器能夠隨開隨關,很適合動態擴容和縮容。

5. 組建微服務架構。

經過多個容器,一臺機器能夠跑不少個虛擬服務器,所以在一臺機器上就能夠模擬出微服務架構,也能夠模擬出分佈式架構。

三. docker 安裝部署與使用

本文介紹 ubuntu 18.04 系統下的安裝與使用。其餘操做系統請參考官方文檔https://docs.docker.com/

1. 安裝 docker 引擎

獲取最新版本的 Docker 安裝包

aaron@ubuntu:~$ wget -qO- https://get.docker.com/ | sh

執行上述命令,輸入當前用戶密碼,便可自動下載最新版的 docker 安裝包,並自動安裝。
安裝完成後有個提示:

If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker aaron

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.

當要以非 root 用戶能夠直接運行 docker 時,須要執行

sudo usermod -aG docker aaron

命令將用戶 aaron 添加到 docker 用戶組中,而後從新登錄,不然會報下面的錯誤:

docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.38/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

執行下列命令啓動 docker 引擎

aaron@ubuntu:~$ sudo service docker start

安裝成功後已默認設置開機啓動並自動啓動,若是要手動設置,執行下面命令:

sudo systemctl enable docker
sudo systemctl start docker

測試運行

aaron@ubuntu:~$ sudo docker run hello-world

2. 使用 docker

1. 理解 docker 的架構

使用前先了解下 docker 的架構,以下圖所示:

docker 架構圖

docker 架構圖

docker 鏡象(image) 是存放在 docker 倉庫(Registry)的文件,是用於建立 docker 容器 的模板。

docker 容器 是獨立運行的一個或一組應用,能夠理解爲前述介紹的虛擬服務器。

docker 主機 是一個物理或者虛擬的機器用於執行 docker 守護進程和容器。

docker 客戶端 經過命令行或者其餘工具使用 docker API 與 docker 的守護進程通訊。
做爲用戶,咱們直接使用的是 docker 客戶端。

2. docker 命令

查看docker 命令的幫助信息

docker --help  #docker 所有命令幫助信息
docker COMMAND --help #docker 具體命令COMMAND的幫助信息

查看docker 信息

docker info

能夠看到容器的池、已用數據大小、總數據大小,基本容器大小、當前運行容器數量等。

搜索鏡像,從網絡中搜索別人作好的容器鏡像。

docker search ubuntu
docker search centos

ubuntu 鏡像

ubuntu 鏡像

從這裏能夠看出有的鏡像已經集成了 php、java、ansible 等應用,咱們也能夠製做包含本身應用或服務的鏡像文件,將此文件傳給別人,別人便可直接使用 docker 打開容器,不須要任何額外的操做,也不像虛擬機那樣消耗資源,便可運行你的應用或服務,是否是很是方便?!

若是對軟件測試、接口測試、自動化測試、性能測試、LR腳本開發、面試經驗交流。感興趣能夠175317069,羣內會有不按期的發放免費的資料連接,這些資料都是從各個技術網站蒐集、整理出來的,若是你有好的學習資料能夠私聊發我,我會註明出處以後分享給你們。

從網絡中下載別人作好的容器鏡像。

docker pull centos
docker pull ubuntu

導入下載好的容器鏡像文件

docker load < image_xxx.tar

查看鏡像

docker images
docker images -a

檢查鏡像

docker inspect ubuntu

能夠看到容器鏡像的基本信息。

刪除鏡像,經過鏡像的 id 來指定刪除

docker rmi ubuntu

刪除所有鏡像

docker rmi $(docker images -q)

顯示鏡像歷史

docker history ubuntu

運行容器

Docker容器能夠理解爲在沙盒中運行的進程,這個沙盒包含了該進程運行所必須的資源,包括文件系統、系統類庫、shell 環境等。但這個沙盒默認是不會運行任何程序的,須要在沙盒中運行一個進程來啓動某一個容器。這個進程是該容器的惟一進程,因此當該進程結束的時候,容器也會徹底中止。

運行 ubuntu 容器並進入交互式環境

aaron@ubuntu:~$ docker run -i --name="ubuntu1" --hostname="ubuntu1" ubuntu /bin/sh
cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  ubuntu1
whoami
root
uname -a
Linux ubuntu1 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

上述命令咱們建立了一個名字爲 ubuntu1 的容器,設置容器的主機名爲 ubuntu1,進入 /bin/sh 命令後咱們打印了 hosts 文件的內容,查看了內核版本(與本機操做系統版本一致),這裏可使用各類 linux 命令,就像在新的操做系統中使用命令一個樣。一樣的方法,咱們在新的終端建立一個 ubuntu2 的容器,並使用

docker ps

查看正在運行的容器。

查看正在運行的容器

查看正在運行的容器

輸入 exit 退出容器。

docker run -d ubuntu

會出現一串長的字母數字組成的串,爲容器的 id,請注意容器要有持續運行的進程存在,不然,容器會很快自動退出。

運行容器並指定MAC地址

docker run -d --name='centos3' --hostname='centos3' --mac-address="02:42:AC:11:00:24" docker-centos6.10-hadoop-spark

列出全部的容器

docker ps -a

列出最近一次啓動的容器

docker ps -l

檢查容器

docker inspect centos1

能夠獲取容器的相關信息。

獲取容器CID

docker inspect -f '{{.Id}}' centos1

獲取容器PID

docker inspect -f '{{.State.Pid}}' centos1

獲取容器IP

docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1

獲取容器網關

docker inspect -f '{{.NetworkSettings.Gateway}}' centos1

獲取容器 MAC

docker inspect -f '{{.NetworkSettings.MacAddress}}' centos1

查看容器 IP 地址

docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1

鏈接容器

ssh 容器的 IP 地址

輸入密碼:123456

容器運行後,能夠經過另外一種方式進入容器內部

docker exec -it centos /bin/sh

查看容器運行過程當中的日誌

docker logs centos1

列出一個容器裏面被改變的文件或者目錄,列表會顯示出三種事件,A 增長的;D 刪除的;C 被改變的

docker diff centos1

和初始容器鏡像項目,用戶或系統增長/修改/刪除了那些目錄文件,均可以查看到。

查看容器里正在運行的進程

docker top centos1

拷貝容器裏的文件/目錄到本地服務器

docker cp centos1:/etc/passwd /tmp/
ls /tmp/passwd

經過網絡 IP 地址也能夠將容器的文件拷貝到服務器,這種方式比較方便。

中止容器

docker stop centos1

中止全部容器

docker kill $(docker ps -a -q)

啓動容器

docker start centos1

刪除單個容器

docker stop centos1
docker rm centos1

刪除容器以前要先中止該容器的運行。

刪除全部容器

docker kill $(docker ps -a -q)
docker rm $(docker ps -a -q)

3. 卷的概念

爲了可以保存(持久化)數據以及共享容器間的數據,docker 提出了卷的概念。卷 Volume 就是容器的特定目錄,該目錄下的文件保存在宿主機上,而不是容器的文件系統內。

數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過容器默認的文件系統,能夠提供不少有用的特性:

(1)數據卷能夠在容器之間共享和重用;

(2)對數據卷的修改會立馬生效;

(3)對數據卷的更新,不會影響鏡像;

(4)數據卷默認會一直存在,即便容器被刪除。

注意:數據卷的使用,相似於 Linux下對目錄進行掛載 mount,容器中被指定爲掛載點的目錄中的文件會隱藏掉,能顯示看的是掛載的數據卷。

建立、使用數據卷

mkdir -p /root/volume1
mkdir -p /root/volume2
docker run -d -v /volume1 --name='centos5' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 --name='centos6' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 -v /root/volume2:/volume2 --name='centos7' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1:ro --name='centos8' docker-centos6.10-hadoop-spark

使用docker run命令建立容器,指定 -v 標記來建立一個數據卷並掛載到容器裏;能夠掛載多個數據卷;能夠設置卷的只讀屬性;能夠不指定服務器映射的目錄,由系統自動指定目錄,經過 docker inspect 來查看映射的路徑。

分別進入這些容器,查看 /volume一、/volume2目錄。

數據卷共享

若是要受權一個容器訪問另外一個容器的數據卷,可使用-volumes-from 參數來執行。

數據卷容器

若是有一些持續更新的數據須要在容器之間共享,最好建立數據卷容器。

數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。

(1)建立一個名爲 dbdata 的數據卷容器

docker run -d -v /dbdata --name dbdata docker-centos6.10-hadoop-spark

(2)在其餘容器中使用--volumes-from來掛載 dbdata 容器中的數據卷

docker run -d --volumes-from dbdata --name db1 docker-centos6.10-hadoop-spark
docker run -d --volumes-from dbdata --name db2 docker-centos6.10-hadoop-spark

這樣就能夠實現容器之間的數據共享。

分別進入這些容器,查看 /volume一、/volume2 目錄。

4. 自制鏡像併發布

保存容器修改,提交一個新的容器鏡像

docker commit centos1 centos111

將現有的容器提交造成一個新的容器鏡像,使用 docker images 能夠看到 centos111 鏡像。經過此方法,能夠建立一個新的容器鏡像。

查看鏡像

docker images

REPOSITORY TAG IMAGE ID   CREATED  SIZE

centos111 latest d691a75ee371   23 minutes ago 501.5 MB

根據新容器鏡像建立容器

docker run -d --name='centos111' centos111

查看容器

docker inspect centos111

導出和導入鏡像

當須要把一臺機器上的鏡像遷移到另外一臺機器的時候,須要導出鏡像與導入鏡像。

機器A

docker save docker-centos6.10-hadoop-spark > docker-centos6.10-hadoop-spark2.tar

docker save -o docker-centos6.10-hadoop-spark docker-centos6.10-hadoop-spark2.tar

使用 scp 命令同其餘方式將 docker-centos6.10-hadoop-spark2.tar 拷到機器 B 上

機器B

docker load < docker-centos6.10-hadoop-spark2.tar

docker load -i docker-centos6.10-hadoop-spark2.tar

發佈容器鏡像

docker push centos6.8-lamp1

將容器發佈到網絡中。

5. docker 網絡

若是對軟件測試、接口測試、自動化測試、性能測試、LR腳本開發、面試經驗交流。感興趣能夠175317069,羣內會有不按期的發放免費的資料連接,這些資料都是從各個技術網站蒐集、整理出來的,若是你有好的學習資料能夠私聊發我,我會註明出處以後分享給你們。

docker 啓動時會在宿主機器上建立一個名爲 docker0 的虛擬網絡接口。它會從RFC 1918 定義的私有地址中隨機選擇一個主機不用的地址和子網掩碼,並將它分配給 docker0,默認選擇 172.18.0.1/16,一個 16 位的子網掩碼給容器提供了 65534 個 IP 地址。

docker0 並非正常的網絡接口,只是一個在綁定到這上面的其餘網卡間自動轉發數據包的虛擬以太網橋,可使容器與主機相互通訊、容器與容器間相互通訊。

docker 每建立一個容器,就會建立一對對等接口(Peer Interface),相似於一個管子的兩端,在一邊能夠收到另外一邊發送的數據包。docker會將對等接口中的一個作爲 eth0 接口鏈接到容器上,並使用相似於vethAQI2QT 這樣的唯一名稱來持有另外一個,該名稱取決於主機的命名空間。經過將全部 veth* 接口綁定到 docker0 橋接網卡上,docker 在主機和全部 docker 容器間建立一個共享的虛擬子網。

docker NAT 網絡

docker 容器默認經過 nat 方式訪問網絡,docker 啓動時會在宿主主機上建立一個名爲 docker0 的虛擬網絡接口,docker0 只是一個在綁定到這上面的其餘網卡間自動轉發數據包的虛擬以太網橋,它可使容器和主機相互通訊、容器與容器間通訊。

docker0 的網關地址是172.18.0.1,掩碼是 16 位,提供了 65534 個IP地址。

NAT 方式,虛擬器容器能夠訪問外網(宿主機之外),但宿主機之外的機器不能訪問容器內網。

docker Bridage 網絡

docker 容器能夠經過 bridge 方式訪問網絡。

bridge方式,虛擬器容器能夠訪問外網(宿主機之外),宿主機之外的機器也能訪問容器內網。

6. docker pipework

docker 自身的網絡功能比較簡單,不能知足不少複雜的應用場景。所以有不少開源項目用來改善 docker 的網絡功能,如 pipework、weave、flannel 等。

pipework 是由 docker 的工程師 Jérôme Petazzoni 開發的一個 docker 網絡配置工具,由 200 多行 shell 實現,方便易用。

安裝 pipework

git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /bin/

wget [http://172.17.1.240/docker/software/pipework](http://172.17.1.240/docker/software/pipework)
chmod a+x pipework
cp pipework /bin/

運行容器

docker run -d --net='none' --name='centos9' docker-centos6.10-hadoop-spark

配置容器網絡,並連到網橋 docker0 上;網關在IP地址後面加 @ 指定。

pipework docker0 centos9 172.18.0.100/16@172.18.0.1

7. docker 網絡端口映射

容器若是使用 docker0 虛擬網絡,那麼容器的網絡是 172.17.0.0/16,容器能夠經過 NAT 方式訪問外網;但外網不能訪問內網。若是容器使用 br0 虛擬網絡,容器和服務器能夠在同一個網絡地址段;容器能夠訪問外網;外網也能夠訪問容器網絡。
對於使用 docker0 虛擬網絡的容器,能夠經過端口映射的方式,讓外網訪問容器某些端口。

運行容器

docker run -d -p 38022:22 --name='centos10' docker-centos6.10-hadoop-spark

鏈接容器

ssh localhost -p 38022

在其餘服務器上經過訪問物理服務器加端口便可訪問容器,能夠一次映射多個端口。

運行容器

docker run -d -p 38022:22 -p 38080:80 --name='centos11' docker-centos6.10-hadoop-spark

其實現原理是在服務器上經過 iptables 轉發來實現。固然也能夠經過iptables 轉發整個容器 IP 地址。

四. 總結

因爲容器是進程級別的,相比虛擬機有不少優點。

(1)啓動快

容器裏面的應用,直接就是底層系統的一個進程,而不是虛擬機內部的進程。因此,啓動容器至關於啓動本機的一個進程,而不是啓動一個操做系統,速度就快不少。

(2)資源佔用少

容器只佔用須要的資源,不佔用那些沒有用到的資源;虛擬機因爲是完整的操做系統,不可避免要佔用全部資源。另外,多個容器能夠共享資源,虛擬機都是獨享資源。

(3)體積小

容器只要包含用到的組件便可,而虛擬機是整個操做系統的打包,因此容器文件比虛擬機文件要小不少。

總之,容器有點像輕量級的虛擬機,可以提供虛擬化的環境,可是成本開銷小得多。

相關文章
相關標籤/搜索