Docker的基本使用
1、docker的基本介紹
Docker 可以讓開發者打包他們的應用以及依賴包(環境)到一個輕量級、可移植的容器中,然后發布到任何流行的 Linux 機器上,也可以實現虛擬化。
Docker 是一個開源的應用容器引擎,基于 Go 語言 并遵從 Apache2.0 協議開源。Docker的主要目標是"Build, Ship and Run Any App,Anywhere" ,也就是通過對應用組件的封裝、分發、部署、運行等生命周期的管理,使用戶的APP (可以是一個WEB應用或數據庫應用等等)及其運行環境能夠做到“一次封裝,到處運行”。
Docker 的接口相當簡單,用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、復制、分享、修改,就像管理普通的代碼一樣。

1.1、為什么需要docker?
傳統上認為,軟件編碼開發/測試結束后,所產出的成果即是程序或是能夠編譯執行的二進制字節碼等(java為例),而為了讓這些程序可以順利執行,開發團隊也得準備完整的部署文件,讓維運團隊得以部署應用程式。開發需要清楚的告訴運維部署團隊,用的全部配置文件+所有軟件環境。不過,即便如此,仍然常常發生部署失敗的狀況。Docker鏡像的設計,使得Docker得以打破過去「程序即應用」的觀念。透過鏡像(images)將作業系統核心除外,運作應用程式所需要的系統環境,由下而上打包,達到應用程式跨平臺間的無縫接軌運作。
傳統開發存在的問題:
- 1、環境配置麻煩
軟件開發最大的麻煩事之一,就是環境配置。環境配置是十分麻煩的,每個機器都要部署環境。
一般我們寫程序的,能接觸到好幾個環境:開發環境、測試環境、生產環境,每個環境都需要進行配置才能將項目(jar、war包)給運用起來。可能會出現好不容易在測試環境下跑起來了,在生產環境就各種出錯的問題。并且如果重裝了某個機器的系統,或者換了一臺機器,你還得去重新配置環境,十分麻煩。
- 2、應用之間需要隔離
比如我寫了兩個應用(網站),這兩個應用部署在同一臺服務器上,那可能會出現什么問題?
- 如果一個應用出現了問題,導致CPU占100%。那另一個應用也會受到關聯,跟著一起涼涼了。
- 這兩個應用是完全不同技術棧的應用,比如一個
PHP,一個.NET。這兩個應用各種的依賴軟件都安裝在同一個服務器上,可能就會造成各種沖突/無法兼容,這可能調試就非常麻煩了。
docker 如何解決這些問題:
- 1、解決環境配置問題
比如說裝Linux虛擬機,重裝Windows系統,都是需要鏡像的。有了這個鏡像,我們就可以運行這個鏡像,來進行安裝系統的操作,于是我們的系統就裝好了。一般來說,我們去官方渠道下載的鏡像,都是純凈的。比如去官方下載Windows鏡像,裝完后之后桌面只有一個回收站。但有過了解裝系統的同學可能就會知道,有的鏡像裝完可能還有360這些軟件,但系統的的確確是變了。簡單來說,就是這些鏡像添加了其他的東西(比如360軟件、騰訊、千千靜聽等等軟件)。
Docker也是這種思路,可以將我們想要的環境構建(打包)成一個鏡像,然后我們可以推送(發布)到網上去。想要用這個環境的時候,在網上拉取一份就好了。
有了Docker,我們在搭環境的時候,跟以前的方式就不一樣了。
- 之前:在開發環境構建出了一個war包,想跑到Linux下運行。我們得先在Linux下載好Java、Tomcat、MySQL,配置好對應的環境變量,將war包丟到Tomcat的webapps文件夾下,才能跑起來。
- 現在:在Linux下直接拉取一份鏡像(各種環境都配好了),將鏡像運行起來,把war包丟進去就好了。將Docker的鏡像運行起來就是一兩秒的事情而已,十分方便的。
- 2、解決應用之間隔離的問題
Docker 底層用的 Linux 的 cgroup 和 namespace 這兩項技術來實現應用隔離。docker 通過隔離機制可以將服務器的資源利用到極致。
Linux 容器(LXC:Linux Containers):在Linux內核中,提供了cgroups功能,來達成資源的區隔化。它同時也提供了名稱空間(namespace)區隔化的功能,使應用程序看到的操作系統環境被區隔成獨立區間,包括進程樹,網絡,用戶id,以及掛載的文件系統。簡單來說就是:LXC是一個 Linux 內核包含特征的用戶接口。通過強大的API和簡單的工具,它可以讓 Linux 用戶輕松的創建和托管系統或者應用程序容器。
Linux 容器不是模擬一個完整的操作系統,而是對進程進行隔離。或者說,在正常進程的外面套了一個保護層。對于容器里面的進程來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。
Docker 屬于 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。Docker 將應用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。
總體來說,Docker 的接口相當簡單,用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、復制、分享、修改,就像管理普通的代碼一樣。
可參考:https://zhuanlan.zhihu.com/p/54512286
1.2、docker和虛擬機的對比
虛擬機(virtual machine)就是帶環境安裝的一種解決方案。它可以在一種操作系統里面運行另一種操作系統,比如在 Windows 系統里面運行 Linux 系統。應用程序對此毫無感知,因為虛擬機看上去跟真實系統一模一樣,而對于底層系統來說,虛擬機就是一個普通文件,不需要了就刪掉,對其他部分毫無影響。虛擬機技術是虛擬出一套硬件后,在該虛擬硬件之上運行一個完整的操作系統,再在該系統上運行所需的應用進程。
雖然用戶可以通過虛擬機還原軟件的原始環境。但是,這個方案有幾個缺點:
(1)資源占用多。虛擬機會獨占一部分內存和硬盤空間。它運行的時候,其他程序就不能使用這些資源了。哪怕虛擬機里面的應用程序,真正使用的內存只有 1MB,虛擬機依然需要幾百 MB 的內存才能運行。
(2)冗余步驟多。虛擬機是完整的操作系統,一些系統級別的操作步驟,往往無法跳過,比如用戶登錄。
(3)啟動慢。啟動操作系統需要多久,啟動虛擬機就需要多久。可能要等幾分鐘,應用程序才能真正運行。
由于虛擬機存在這些缺點,Linux 發展出了另一種虛擬化技術:Linux 容器(Linux Containers,縮寫為 LXC)。Linux 容器不是模擬一個完整的操作系統,而是對進程進行隔離。或者說,在正常進程的外面套了一個保護層。對于容器里面的進程來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。
由于容器是進程級別的,相比虛擬機有很多優勢:
(1)啟動快。容器里面的應用,直接就是底層系統的一個進程,而不是虛擬機內部的進程。所以,啟動容器相當于啟動本機的一個進程,而不是啟動一個操作系統,速度就快很多。
(2)資源占用少。容器只占用需要的資源,不占用那些沒有用到的資源;虛擬機由于是完整的操作系統,不可避免要占用所有資源。另外,多個容器可以共享資源,虛擬機都是獨享資源。
(3)體積小。容器只要包含用到的組件即可,而虛擬機是整個操作系統的打包,所以容器文件比虛擬機文件要小很多。
傳統虛擬機技術是虛擬出一套硬件后,在該虛擬硬件之上運行一個完整的操作系統,再在該系統上運行所需的應用進程。而容器內的應用進程直接運行于本機宿主的內核,容器內沒有自己的內核,而且也沒有進行硬件虛擬,因此容器要比虛擬機更為輕便。
容器可以理解為一個輕量級的虛擬機,能夠提供虛擬化的環境,但是成本開銷小得多。

架構圖對比:
容器架構:

虛擬機架構:

1.3、docker 的優點
Docker 屬于 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。
Docker 將應用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。
Docker是一個集開發、打包、運行應用于一體的開放式平臺。Docker可以用來快速交付應用。使用Docker,你可以將應用程序從你的基礎設施中分離出來,并將基礎設施當做一個管理平臺。Docker可以加快打包時間,加快測試,加快發布,縮短開發及運行代碼之間的周期。
Docker 的主要用途,目前有三大類:
(1)提供一次性的環境。比如,本地測試他人的軟件、持續集成的時候提供單元測試和構建的環境。
(2)提供彈性的云服務。因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容。
(3)組建微服務架構。通過多個容器,一臺機器可以跑多個服務,因此在本機就可以模擬出微服務架構。
2、docker的三要素
docker由三部分組成:image(鏡像)、容器(container)、倉庫(repository)。
Docker 本身是一個容器運行載體或稱之為管理引擎。我們把應用程序和配置依賴打包好形成一個可交付的運行環境,這個打包好的運行環境就是 image 鏡像文件。只有通過這個鏡像文件才能生成Docker容器。image 文件可以看作是容器的模板。Docker 根據 image 文件生成容器的實例。同一個image文件,可以生成多個同時運行的容器實例。
2.1、鏡像(image)
Docker 鏡像(Image)就是一個只讀的模板,其中包含有關創建Docker容器的說明。鏡像可以用來創建Docker容器,一個鏡像可以創建多個容器。
Docker 把應用程序及其依賴,打包在 image 文件里面。只有通過這個文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根據 image 文件生成容器的實例。同一個 image 文件,可以生成多個同時運行的容器實例。
image 是二進制文件。實際開發中,一個 image 文件往往通過繼承另一個 image 文件,加上一些個性化設置而生成。舉例來說,你可以在 Ubuntu 的 image 基礎上,往里面加入 Apache 服務器,形成你的 image。image 文件是通用的,一臺機器的 image 文件拷貝到另一臺機器,照樣可以使用。

2.2、容器(container)
容器的基本介紹:
- 容器是通過鏡像創建的運行實例
- Docker 利用容器(Container)來獨立運行一個或一組應用
- 容器可以被啟動、開始、停止、刪除,每個容器之間都是相互隔離的,保證平臺的安全。
- 可以把容器看做是一個簡易版的Linux環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。
- 容器的定義和鏡像幾乎一摸一樣,也是一堆層的統一視角,唯一區別在于容器的最上面那一層是可讀可寫的。
image 文件生成的容器實例,本身也是一個文件,稱為容器文件。
2.3、倉庫(repository)
倉庫的基本介紹:
- 倉庫(Repository)是集中存放鏡像文件的場所。
- 倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式。最大的公開倉庫是Docker Hub(https://hub.docker.com/),存放了數量龐大的鏡像供用戶下載。國內的公開倉庫包括阿里云、網易云等。
倉庫(Repository)很容易和Registry(倉庫注冊服務器)混淆。通俗地說,它們的關系是倉庫注冊服務器上往往存放著多個倉庫,每個倉庫又存放著一大堆Images,每個Image存在不同的標簽(Tag);用戶可以通過注冊服務器從倉庫拉取(帶有某個tag的)Image,從而創建Container。
3、docker的安裝
Docker 從 17.03 版本之后分為 CE(Community Edition: 社區版) 和 EE(Enterprise Edition: 企業版),一般用社區版就可以了。
如果是 centos 系統,則 Docker 支持以下CentOS 版本:CentOS 7(64-bit)、CentOS 8(64-bit)或者更高版本。Docker 運行在 centos7 上時,要求 CentOS 系統的內核版本高于 3.10 ;運行在 centos6.5或更高版本上時,要求系統內核版本為 2.6.32-431 或更高。
在不同版本系統上安裝 docker 不太一樣,下面我們在 centos7 版本的 Linux 系統上安裝社區版 docker。
首先,我們需要通過 uname -r 命令查看你當前的內核版本:

也可以通過 cat /etc/redhat-release 命令來查看 centos 系統的版本:

如果之前安裝過舊的版本的 docker,需要先卸載掉。較舊的Docker版本稱為docker或docker-engine。如果已安裝這些程序,請卸載它們以及相關的依賴項。
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
安裝需要的軟件包, yum-util 提供yum-config-manager功能,另外兩個是devicemapper驅動依賴的:
sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
設置yum源。使用以下命令來設置穩定的倉庫,官方的倉庫比較慢,下面我們使用阿里云的倉庫:
sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安裝docker。安裝最新版本的 Docker Engine-Community 和 containerd:
sudo yum install docker-ce docker-ce-cli containerd.io
安裝過程中可能會提示是否確認,可以直接選是。
上述過程中 docker 已安裝完成,我們可以直接啟動 Docker:
sudo systemctl start docker
安裝完成后,我們可以通過查看 docker 的版本來驗證是否安裝成功:
docker version
效果如下:

3.1、配置加速器
下面配置阿里云加速器。
參考:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
3.2、試運行hello-world 鏡像
Docker 允許你在容器內運行應用程序, 使用 docker run 命令來在容器內運行一個應用程序。下面我們試運行 hello-world 鏡像:
sudo docker run hello-world
run命令會從 image 文件,生成一個正在運行的容器實例。run命令具有自動抓取 image 文件的功能。如果發現本地沒有指定的 image 文件,就會從倉庫自動抓取。
運行效果如下:

輸出上面提示以后,hello world會自動停止運行,容器自動終止。但有些容器是不會自動終止的,因為提供的是服務,比如安裝運行 Ubuntu 的 image,就可以在命令行體驗 Ubuntu 系統。對于那些不會自動終止的容器,必須使用docker container kill 命令手動終止。
4、docker的原理和架構
4.1、docker運行原理
Docker是一個Client-Server結構的系統,Docker守護進程(Docker daemon)運行在主機上, 然后通過Socket連接從客戶端訪問,守護進程從客戶端接受命令并管理運行在主機上的容器。 容器,是一個運行時環境,就是我們前面說到的集裝箱。

4.2、docker架構
Docker使用了C/S體系架構,Docker客戶端與Docker守護進程通信,Docker守護進程(docker daemon)負責構建,運行和分發Docker容器。Docker客戶端和守護進程可以在同一個系統上運行,也可以將Docker客戶端連接到遠程Docker守護進程。Docker客戶端和守護進程使用REST API通過UNIX套接字或網絡接口進行通信。

5、Pod
Kubernetes 中的Pod是部署應用的最小單位。一個Pod封裝一個應用容器,存儲資源、一個獨立的網絡IP以及管理控制容器運行方式的策略選項。業務涉及到的所有應用均運行在容器云平臺所管理的一個個的Pod當中。
當應用的Pod創建好之后,就要考慮建立完整的訪問鏈路系統,最終實現對外提供服務的能力。建立網絡訪問的第一步,是實現各個Pod在所依賴宿主機——利用Kubernetes搭建的集群間內部的聯通和訪問。
集群內部Pod訪問邏輯
實現集群內部訪問有兩種方案,分別如下:
1) 直接使用docker分配的IP地址
在Pod運行時,docker會為其分配一個獨立的IP地址。拼接這個IP地址和服務的端口號,即可直接訪問此Pod中的服務。但是這種方式有一個巨大的問題,即Pod在重啟或銷毀重建后,將會分配新的IP地址。
2) 通過ClusterIP方式訪問
Pod的IP 地址實際存在于某個物理網卡或虛擬網卡上 ,而ClusterIP是創建Service的時候,由系統內部分配的一個全局唯一的虛擬IP.這個虛擬IP在網絡中是無法尋址到的,它沒有綁定到任何網卡設備上。這增加了它的訪問的靈活性。我們可以通過服務的ClusterIP加應用容器的服務端口號來進行訪問。
Service的業務入口訪問機制
當Pod的訪問有優選方案之后,我們接下來面臨了下一個問題:Pod的IP和ClusterIP都是在每次創建后隨之變化的,如何在應用的Pod重啟后,保證服務的可訪問性呢?此時,k8s中的Service可以解決此問題,它為應用的訪問提供了一套業務的入口機制。

浙公網安備 33010602011771號