原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。mysql
Docker
是時下熱門的容器技術,相信做爲一名開發人員,你必定據說過或者使用過,不少人會把Docker
理解爲一個輕量級虛擬機,但其實Docker
與虛擬機(VM
)是兩種不一樣的計算機虛擬化技術,也有不少人會以爲,有了虛擬機,那爲何還要使用Docker
呢?linux
帶着內心的一點點疑問,讓咱們一塊兒來學習Docker
吧。程序員
咱們仔細想一想,在沒有計算虛擬化技術的「遠古」年代,若是咱們要部署一個應用程序(Application
),通常的步驟是怎麼樣的?sql
第一步確定是先要準備一臺物理服務器,而後在物理服務器上安裝一個操做系統(Operating System
),有了操做系統以後,便在操做系統上安裝運行咱們的應用程序,這個過程能夠用下面的圖來表示:docker
那麼,這種方式有什麼問題呢?其實,在物理機上部署應用有如下幾個缺點:編程
部署很是慢:由於咱們得先準備硬件服務器,接着還要安裝操做系統,而後再部署應用程序,並且應用程序還有不少的依賴軟件,因此這個過程是比較慢的。centos
成本很是高:主要是物理器成本過高,即便是部署一個簡單的應用,也須要一臺服務器。bash
資源浪費:若是應用太簡單,也容易浪費硬件資源,好比CPU
和內存服務器
遷移和擴展太慢:若是須要遷移應用,或者擴展應用,都要再準備其餘的物理服務器,過程很麻煩,也很慢。網絡
那麼有什麼辦法能夠解決這些問題呢?答案即是虛擬化技術。
談到計算機的虛擬化技術,咱們直接想到的即是虛擬機,虛擬機容許咱們在一臺物理計算機模擬出多臺機器,簡單地理解,虛擬化技術就是在一臺物理計算機上,經過中間虛擬軟件層Hypervisor
隔離CPU
、內存等硬件資源,虛擬出多臺虛擬服務器,這樣作的話,一臺物理服務器即可以安裝多個應用程序,達到資源利用的最大化,並且多個應用之間相互隔離,以下圖所示:
能夠把資源分配到不一樣的虛擬機,達到硬件資源的最大化利用
與直接在物理機上部署應用,虛擬機更容易擴展應用。
雲服務:經過虛擬機虛擬出不一樣的物理資源,能夠快速搭建雲服務。
虛擬機的不足之處在於對物理服務器資源的消耗,當咱們在物理服務器建立一臺虛擬機時,便須要虛擬出一套硬件並在上面運行完整的操做系統,每臺虛擬機都佔用許多的服務器資源。
相對於虛擬機的笨重,Docker
則更顯得輕量化,所以不會佔用太多的系統資源。
Docker
是使用時下很火的Golang
語言進行開發的,其技術核心是Linux
內核的Cgroup
,Namespace
和AUFS
類的Union FS
等技術,這些技術都是Linux
內核中早已存在不少年的技術,因此嚴格來講Docker
並非一個徹底創新的技術,Docker
經過這些底層的Linux
技術,對Linux
進程進行封裝隔離,而被隔離的進程也被稱爲容器,徹底獨立於宿主機的進程。
因此Docker
是容器技術的一種實現,也是操做系統層面的一種虛擬化,與虛擬機經過一套硬件再安裝操做系統徹底不一樣。
Docker
是在操做系統進程層面的隔離,而虛擬機是在物理資源層面的隔離,二者徹底不一樣,另外,咱們也能夠經過下面的一個比較,瞭解二者的根本性差別。
從上面的容器與虛擬機的對比中,咱們明白了容器技術的優點。
開發環境與生產環境折射的是開發人員與運維人員之間的矛盾,也許咱們經常會聽到開發人員對運維人員說的這樣一句話:「在個人電腦運行沒問題,怎麼到了你那裏就出問題了,確定是你的問題」,而運維人員則認爲是開發人員的問題。
開發人員須要在本機安裝各類各樣的測試環境,所以開發的項目須要軟件越多,依賴越多,安裝的環境也就越複雜。
一樣的,運維人員須要爲開發人員開發的項目提供生產環境,而運維人員除了應對軟件之間的依賴,還須要考慮安裝軟件與硬件之間的兼容性問題。
就是這樣,因此咱們常常看到開發與運維相互甩鍋,怎麼解決這個問題呢?
容器就是一個不錯的解決方案,容器能成爲開發與運維之間溝通的語言,由於容器就像一個集裝箱同樣,提供了軟件運行的最小化環境,將應用與其須要的環境一塊兒打包成爲鏡像,即可以在開發與運維之間溝通與傳輸。
Docker
分爲社區版(CE
)和企業版(EE
)兩個版本,社區版本能夠無償使用,而企業版則須要付費使用,對於咱們我的開發者或小企業來講,通常是使用社區版的。
Docker CE
有三個更新頻道,分別爲stable
、test
、nightly
,stable
是穩定版本,test
是測試後的預發佈版本,而nightly
則是開發中準備在下一個版本正式發佈的版本,咱們能夠根據本身的需求下載安裝。
好了,經過前面的介紹,咱們應該對Docker
有了初步的瞭解,下面開始進入Docker
的學習之旅了。
而學習Docker
的第一步,從安裝Docker
運行環境開始,咱們以Docker
的社區版本(CE
)安裝爲例。
Docker
社區版本提供了Mac OS
,Microsoft Windows
和Linux
(Centos
,Ubuntu
,Fedora
,Debian
)等操做系統的安裝包,同時也支持在雲服務器上的安裝,好比AWS Cloud
。
Docker
爲Windows
提供了一個桌面應用程序管理的安裝包(Docker Desktop for Windows
),不過對系統有如下幾點要求:
64
位Windows10
專業版,企業版,教育版,構建在15063
或更高版本,BIOS
中啓用虛擬化。一般,默認狀況下啓用虛擬化。4GB
內存。CPU
支持SLAT
。若是操做系統知足上面的要求,則能夠直接下載安裝包直接安裝,在安裝成功後,Docker
並不會自動啓動,須要咱們本身啓動,咱們能夠在開始菜單中找到Docker
,以下圖,單擊啓動即可啓動。
若是系統達不到上面的要求,好比說你用的是Windows 7
操做系統,這時候要想使用Docker
,便須要藉助Docker Toolbox
,Docker Toolbox
是Docker
提供的在比較舊的Mac OS
,Windows
操做系統上安裝Docker
環境的工具集。
Docker Toolbox
包括docker-cli(就是咱們在終端使用的docker命令行工具)
,docker-compose(多容器管理工具)
,docker-mecahine
,VirtualBox(虛擬機)
,Kitematic(docker的GUI管理工具)
。
本質上使用Docker Toolbox
安裝Docker
環境,其實是在VirtualBox
中建立一個Linux
虛擬機,並在虛擬機上安裝Docker
。
另外,在安裝過程當中會開啓Windows
的Hyper-V
模塊(Windows
操做系統實現虛擬化的一種技術),這裏面有個要注意的點是若是開啓了Hyper-V
,則VirtualBox
再也不生效了。
如同Windows
操做系統同樣,Docker
爲Mac OS
也同樣提供一個桌面應用程序(Docker Desktop for Mac
),比較簡單,從docker
官網上下載Dokcer.dmg
安裝,打開Docker.dmg
,以下圖所示:
直接拖動Docker
圖標便完成了安裝。
對於比較老的Mac OS
操做系統,也能夠像Windows
同樣,使用Docker Toolbox
,這點能夠參考上面的介紹。
在Mac OS
上安裝完成以後,在Application
中找到Docker
圖標,雙擊打開即可以啓動Docker
了,以下:
在Linux
操做系統上的安裝,主要以Centos7
爲例,其餘Linux
系統的發行版本,如Ubuntu
,Debian
,Fedora
等,能夠自行查詢Docker
的官方文檔。
可能有些Linux
預先安裝Docker
,但通常版本比較舊,因此能夠先執行如下代碼來刪除舊版本的Docker
。
$ sudo dnf remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
複製代碼
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
複製代碼
$ sudo yum install docker-ce docker-ce-cli containerd.io
複製代碼
# 啓動docker守護進程
$ sudo systemctl start docker
複製代碼
經過上面幾種方式安裝了Docker
以後,咱們能夠經過下面的方法來檢測安裝是否成功。
# 打印docker版本
$ docker version
複製代碼
# 拉取hello-world鏡像
docker pull hello-world
# 使用hello-world運行一個容器
docker run hello-world
複製代碼
運行上面的命令以後,若是有以下圖所示的輸出結果,則說明安裝已經成功了。
鏡像(Image
)、容器(Container
)與倉庫(Repository
),這三個是docker
中最基本也是最核心的概念,對這三個概念的掌握與理解,是學習docker
的關鍵。
什麼是Docker
的鏡像?
Docker
本質上是一個運行在Linux
操做系統上的應用,而Linux
操做系統分爲內核和用戶空間,不管是Centos
仍是Ubuntu
,都是在啓動內核以後,經過掛載Root
文件系統來提供用戶空間的,而Docker鏡像就是一個Root文件系統。
Docker
鏡像是一個特殊的文件系統,提供容器運行時所需的程序、庫、資源、配置等文件,另外還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。
鏡像是一個靜態的概念,不包含任何動態數據,其內容在構建以後也不會被改變。
下面的命令是一些對鏡像的基本操做,以下:
# 列出全部鏡像
docker image ls
複製代碼
因爲咱們前面已經拉取了hello-world
鏡像,因此會輸出下面的內容:
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 7 months ago 1.84kB
複製代碼
下面的命令也同樣能夠查看本地的鏡像列表,並且寫法更簡潔。
# 列表全部鏡像
docker images
複製代碼
前面咱們已經演示過使用docker pull
命令拉取了hello-world
鏡像了,固然使用docker image pull
命令也是同樣的。
通常默認是從Docker Hub
上拉取鏡像的,Docker Hub
是Docker
官方提供的鏡像倉庫服務(Docker Registry
),有大量官方或第三方鏡像供咱們使用,好比咱們能夠在命令行中輸入下面的命令直接拉取一個Centos
鏡像:
docker pull centos
複製代碼
docker pull
命令的完整寫法以下:
docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標籤]
複製代碼
拉取一個鏡像,須要指定Docker Registry
的地址和端口號,默認是Docker Hub
,還須要指定倉庫名和標籤,倉庫名和標籤惟一肯定一個鏡像,而標籤是可能省略,若是省略,則默認使用latest做爲標籤名,另外,倉庫名則由做者名和軟件名組成。
那麼,咱們上面使用centos
,那是由於省略做者名,則做者名library
,表示Docker
官方的鏡像,因此上面的命令等同於:
docker pull library/centos:latest
複製代碼
所以,若是拉取非官方的第三方鏡像,則須要指定完整倉庫名,以下:
docker pull mysql/mysql-server:latest
複製代碼
使用docker run
命令,能夠經過鏡像建立一個容器,以下:
docker run -it centos /bin/bash
複製代碼
當本地有些鏡像咱們不須要時,那咱們也能夠刪除該鏡像,以節省存儲空間,不過要注意,若是有使用該鏡像建立的容器未刪除,則不容許刪除鏡像。
# image_name表示鏡像名,image_id表示鏡像id
dockere image rm image_name/image_id
複製代碼
刪除鏡像的快捷命令:
docker rmi image_name/image_id
複製代碼
好了,關於Docker
鏡像的相關知識,咱們就簡單地介紹到這裏,有機會的話,咱們單獨寫一篇文章來談談,特別構建Docker
鏡像部分的相關知識,有必要深刻再學習一下。
Docker
的鏡像是用於生成容器的模板,鏡像分層的,鏡像與容器的關係,就是面向對象編程中類與對象的關係,咱們定好每個類,而後使用類建立對象,對應到Docker
的使用上,則是構建好每個鏡像,而後使用鏡像建立咱們須要的容器。
啓動容器有兩種方式,一種是咱們前面已經介紹過的,使用docker run
命令經過鏡像建立一個全新的容器,以下:
docker run hello-world
複製代碼
另一種啓動容器的方式就是啓動一個已經中止運行的容器:
# container_id表示容器的id
docker start container_id
複製代碼
要中止正在運行的容器可使用docker container stop
或docker stop
命令,以下:
# container_id表示容器的id
docker stop container_id
複製代碼
若是要查看本地全部的容器,可使用docker container ls
命令:
# 查看全部容器
docker container ls
複製代碼
查看全部容器也有簡潔的寫法,以下:
# 查看全部容器
docker ps
複製代碼
咱們也可使用docker container rm
命令,或簡潔的寫法docker rm
命令來刪除容器,不過不容許刪除正在運行的容器,所以若是要刪除的話,就必須先中止容器,
# container_id表示容器id,經過docker ps能夠看到容器id
$ docker rm container_id
複製代碼
當咱們須要批量刪除全部容器,能夠用下面的命令:
# 刪除全部容器
docker rm $(docker ps -q)
複製代碼
# 刪除全部退出的容器
docker container prune
複製代碼
# 進入容器,container_id表示容器的id,command表示linux命令,如/bin/bash
docker exec -it container_id command
複製代碼
在前面的例子中,咱們使用兩種方式構建鏡像,構建完成以後,能夠在本地運行鏡像,生成容器,但若是在更多的服務器運行鏡像呢?很明顯,這時候咱們須要一個可讓咱們集中存儲和分發鏡像的服務,就像Github可讓咱們本身存儲和分發代碼同樣。
Docker Hub
就是Docker提供用於存儲和分佈鏡像的官方Docker Registry
,也是默認的Registry
,其網址爲https://hub.docker.com
,前面咱們使用docker pull
命令便從Docker Hub
上拉取鏡像。
Docker Hub
有不少官方或其餘開發提供的高質量鏡像供咱們使用,固然,若是要將咱們本身構建的鏡像上傳到Docker Hub
上,咱們須要在Docker Hub
上註冊一個帳號,而後把本身在本地構建的鏡像發送到Docker Hub
的倉庫當中,Docker Registry
包含不少個倉庫,每一個倉庫對應多個標籤,不一樣標籤對應一個軟件的不一樣版本。
在安裝好並啓動了Docker
以後,咱們可使用在命令行中使用docker
命令操做docker,好比咱們使用以下命令打印docker
的版本信息。
docker verion
複製代碼
其結果以下:
從上面的圖中,咱們看到打出了兩個部分的信息:Client
和Server
。
這是由於Docker
跟大部分服務端軟件同樣(如MySQL
),都是使用C/S
的架構模型,也就是經過客戶端調用服務器,只是咱們如今恰好服務端和客戶端都在同一臺機器上而已。
所以,咱們可使用下面的圖來表示Docker
的架構,DOCKER_HOST
是Docker server
,而Clinet即是咱們在命令中使用docker
命令。
docker server
爲客戶端提供了容器、鏡像、數據卷、網絡管理等功能,其實,這些功能都是由Docker Engine
來實現的。
dockerd
:服務器守護進程。Client docker Cli
:命令行接口REST API
:除了cli命令行接口,也能夠經過REST API
調用docker
下面是Docker Engine
的示例圖:
做爲一名開發人員,在學習或開發過程當中,總須要安裝各類各樣的開發環境,另外,一個技術團隊在開發項目的過程,也經常須要統一開發環境,這樣可能避免環境不一致引起的一些問題。
雖然使用虛擬機能夠解決上面的問題,但虛擬機過重,對宿主機資源消耗太大,而做爲輕量級容器技術,Docker
能夠簡單輕鬆地解決上述問題,讓開發環境的安裝以及應用的部署變得很是簡單,並且使用Docker
,比在虛擬機安裝操做系統,要簡單得多。
歡迎掃碼關注,共同窗習進步