經(jīng)常寫程序的同學(xué)們往往會(huì)遇到這樣一些痛點(diǎn):代碼更新發(fā)布、部署效率實(shí)在是低下,環(huán)境的一致性也難以保證,明明在開發(fā)環(huán)境里能運(yùn)行的代碼,換了一臺(tái)機(jī)器怎么就跑不通了?
云計(jì)算時(shí)代,還在用傳統(tǒng)方式部署代碼,怎么好意思說自己是9102年的工程師?實(shí)在是不能忍!今天,你蝦就給大家安利一下被譽(yù)為“云計(jì)算時(shí)代的顛覆性技術(shù)”——Docker
什么是Docker?
Docker 是一個(gè)基于 Go 語(yǔ)言,并遵從 Apache2.0 協(xié)議開源的應(yīng)用容器引擎。
它是一種容器級(jí)的虛擬化技術(shù), 開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個(gè)輕量級(jí)、可移植的容器中,并發(fā)布到任何流行的 Linux 機(jī)器上,無(wú)需擔(dān)心環(huán)境的問題。
Docker 和 VM,傻傻分不清楚
前面我們提到,Docker 是一種基于虛擬化的技術(shù),談到虛擬化就不得不說 VM(Virtual Machine 虛擬機(jī)),既然都是基于虛擬化,Docker 和 VM 又有什么差別呢,別急,咱們慢慢來(lái)聊這個(gè)問題。
我們先來(lái)看右側(cè) VM 的架構(gòu)圖,在 Infrastucture(可以理解為底層硬件)之上,有一層 Hypervisor,它是一種運(yùn)行在物理服務(wù)器和操作系統(tǒng)之間的中間層,可以允許多個(gè)操作系統(tǒng)和應(yīng)用共享底層硬件。虛擬機(jī)在主操作系統(tǒng)之上運(yùn)行多個(gè)不同的子操作系統(tǒng),并通過 Hypervisor 調(diào)用底層的硬件。
假設(shè)你需要運(yùn)行3種相互隔離的應(yīng)用,那你得創(chuàng)建3臺(tái)虛擬機(jī),這也就意味著在 Hypervisor 之上會(huì)運(yùn)行著3個(gè)子操作系統(tǒng),這樣會(huì)產(chǎn)生特別大的資源開銷。
(P.S 其實(shí)圖中 Hypervisor 之上應(yīng)該還有一層 Host Operating System)
而 Docker 就顯得十分輕便了,它的守護(hù)進(jìn)程(Docker Daemon)取代了 Hypervisor,直接運(yùn)行在操作系統(tǒng)之上,應(yīng)用的源代碼與它的依賴都打包在Docker鏡像 (image) 中,Docker 引擎通過鏡像去創(chuàng)建容器(container)。不同的應(yīng)用運(yùn)行在不同的容器中,它們之間是相互隔離的。
并且,Docker 守護(hù)進(jìn)程可以直接與操作系統(tǒng)進(jìn)行通信,為各個(gè) Docker 容器分配資源,由于沒有臃腫的從操作系統(tǒng),虛擬機(jī)啟動(dòng)需要數(shù)分鐘,而 Docker 容器可以在數(shù)毫秒內(nèi)啟動(dòng),效率提升明顯,且節(jié)省了大量的磁盤空間以及其他系統(tǒng)資源。
說了這么多,你是不是認(rèn)為 Docker 完全可以吊打虛擬機(jī)了呢,其實(shí)不是。俗話說術(shù)業(yè)有專攻,相比 Docker,虛擬機(jī)更擅長(zhǎng)徹底隔離整個(gè)運(yùn)行環(huán)境,最常見的就是云廠商通過VM的方式來(lái)隔離不同的用戶;而 Docker 通常用于隔離不同的應(yīng)用。
如何使用Docker
Docker的安裝(以CentOS 7 為例)
#安裝一些必要的系統(tǒng)工具:
yum install -y yum-utils device-mapper-persistent-data lvm2
#更新系統(tǒng)內(nèi)核以及yum緩存
yum update
yum makecache fast
#安裝Docker并啟動(dòng)
yum -y install docker-ce
systemctl start docker
#測(cè)試Docker是否安裝成功
docker run hello-world
如果屏幕出現(xiàn)了 Hello from Docker ,恭喜你,安裝這一步就已經(jīng)大功告成了
Docker的相關(guān)概念
在進(jìn)一步學(xué)習(xí) Docker 之前,我們需要科普一些 Docker 的相關(guān)概念,這樣在下面的學(xué)習(xí)中,你才會(huì)有一種事半功倍的 feeling
Key | Value |
---|---|
Docker鏡像(Images) | Docker 鏡像是用于創(chuàng)建 Docker 容器的模板 |
Docker容器 (Container) | Docker通過鏡像創(chuàng)建出容器,用于運(yùn)行一組獨(dú)立的應(yīng)用 |
Docker倉(cāng)庫(kù) (Registry) | 用于保存鏡像的代碼倉(cāng)庫(kù) |
通常,我們會(huì)從Docker倉(cāng)庫(kù)中下載對(duì)應(yīng)的鏡像,并通過鏡像創(chuàng)建出運(yùn)行應(yīng)用的容器
Docker實(shí)例
多說無(wú)益,下面我們將通過兩個(gè)比較典型的實(shí)例,將相關(guān)的知識(shí)點(diǎn)串聯(lián)起來(lái),來(lái)學(xué)習(xí)如何使用Docker
使用Docker安裝Python
剛剛我們說過,想使用Docker容器,第一步是從倉(cāng)庫(kù)中下載相應(yīng)的鏡像,這就引出了我們教程中的第一條命令
docker search
作用:從鏡像倉(cāng)庫(kù)中查找指定鏡像
語(yǔ)法:docker search [OPTIONS] TERM
示例:docker search python
詳解:從倉(cāng)庫(kù)中尋找Python相關(guān)的鏡像
[root@FUCC ~]# docker search python
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/python Python is an interpreted, interactive, obj... 4356 [OK]
docker.io docker.io/django Django is a free web application framework... 856 [OK]
docker.io docker.io/pypy PyPy is a fast, compliant alternative impl... 196 [OK]
docker.io docker.io/kaggle/python Docker image for Python scripts run on Kaggle 125 [OK]
docker.io docker.io/arm32v7/python Python is an interpreted, interactive, obj... 38
docker.io docker.io/centos/python-35-centos7 Platform for building and running Python 3... 36
在這里我們直接選擇官方的鏡像,標(biāo)簽(版本)為3.7
docker pull
作用:從鏡像倉(cāng)庫(kù)中拉取或者更新指定鏡像
語(yǔ)法:docker pull [OPTIONS] NAME:TAG
示例:docker pull python:3.7
詳解:從倉(cāng)庫(kù)中下載標(biāo)簽為3.7的 Python鏡像
[root@FUCC ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...
3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============> ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================> ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==> ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7
此時(shí),Docker便已經(jīng)幫我們從倉(cāng)庫(kù)中下載指定的鏡像了,下載完成后,可以使用下面這條命令來(lái)查看本地已經(jīng)存在的Docker鏡像
docker images
作用:列出本地鏡像
語(yǔ)法:docker images [OPTIONS] [REPOSITORY[:TAG]]
示例:docker images
詳解:查看本地所有的docker鏡像
[root@FUCC ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/python 3.7 42d620af35be 6 days ago 918 MB
docker.io/rabbitmq 3-management 7aae48fa6ef6 7 days ago 179 MB
docker.io/golang latest f50db16df5da 9 days ago 774 MB
可以看到,此時(shí)本地已經(jīng)存在了python3.7的鏡像,事不宜遲,我們就用這個(gè)鏡像來(lái)創(chuàng)建一個(gè)容器吧,Let's go !
docker run
在創(chuàng)建容器之前,我們先簡(jiǎn)單聊一下ID的概念,在Docker中,我們通常使用ID來(lái)作為一個(gè)鏡像或者容器的唯一標(biāo)識(shí),一般以"命令 + ID"的方式對(duì)一個(gè)鏡像或者容器進(jìn)行操作,如上面這段代碼,我們可以看到python3.7這個(gè)鏡像的ID為42d620af35be
作用:創(chuàng)建一個(gè)新的容器
語(yǔ)法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
為了測(cè)試我們的python環(huán)境是否安裝完成,我們先在本地新建一個(gè) hello.py 的文件
##!/usr/bin/python
import sys
print("Hello, Docker!")
print(sys.version) #輸出Python版本號(hào)
以我的環(huán)境為例,我把這段代碼保存在了本地的 /root/code/python 目錄下
接下來(lái),我們就使用 docker 中的 python 環(huán)境去運(yùn)行這段代碼吧
[root@FUCC python]# docker run -v $PWD:/usr/src/code -w /usr/src/code python:3.7 python hello.py
Hello,Docker!
3.7.4 (default, Jul 13 2019, 14:04:11)
[GCC 8.3.0]
乍一看,這么長(zhǎng)的一段命令著實(shí)有點(diǎn)嚇人,別慌,待我來(lái)把命令拆解開細(xì)細(xì)講給你聽
docker run: 用于創(chuàng)建一個(gè)容器,這段我們剛剛聊過,pass
-v $PWD:/usr/src/code: 用于掛載本地的目錄到docker容器中,以這條命令為例,它將執(zhí)行這段命令所在的目錄,掛載到了容器中的 /usr/src/code 目錄下,冒號(hào)前面是本地路徑,后面為對(duì)應(yīng)的容器中的目錄,你也可以不用PWD,直接用絕對(duì)路徑的寫法
-w /usr/src/code: -w用于指定容器的工作目錄,在上一步中,我們將本地存放python代碼的目錄掛載到了容器中的 /usr/src/code 目錄,所以我們將這個(gè)目錄設(shè)置為容器的工作目錄
python:3.7:指定鏡像,你也可以用Image ID 來(lái)替換這里的鏡像名稱
python hello.py:這里應(yīng)該就不用我多說了,這是在容器中執(zhí)行的命令
看到這里,我給你布置一道思考題,假設(shè)我在本地的 /root/data/ 目錄中存放了一個(gè) hello.go 的代碼文件,想要使用Image ID 為 f50db16df5da 的golang 容器運(yùn)行這段代碼,命令應(yīng)該怎么寫呢,歡迎在評(píng)論區(qū)留言
(P.S 運(yùn)行g(shù)o語(yǔ)言代碼的命令為 go run FILENAME)
使用Docker安裝MariaDB
從Docker倉(cāng)庫(kù)中搜索并下載MariaDB鏡像的過程相信你已經(jīng)能無(wú)師自通了,這里我們主要是聊啟動(dòng)的過程。
相信你已經(jīng)知道,類似于數(shù)據(jù)庫(kù)這類的服務(wù),需要在本地開啟相對(duì)應(yīng)的端口,那么在Docker中應(yīng)該如何實(shí)現(xiàn)呢,還記得在剛剛的Python案例中,我們將存放代碼的本地目錄和容器中的目錄做了一個(gè)映射嗎,同樣的,端口也可以有這種操作
[root@FUCC python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --restart unless-stopped 3a2ef06682ac
-d:將容器在后臺(tái)運(yùn)行
-p 3306:3306:將容器中3306的端口映射到主機(jī)的3306端口
-e MYSQL_ROOT_PASSWORD=123456:初始化root的密碼為123456
--restart unless-stopped: 設(shè)置當(dāng)容器意外停止時(shí)自動(dòng)重啟
3a2ef06682ac:創(chuàng)建容器的Image ID
這時(shí)我們可以驗(yàn)證一下數(shù)據(jù)庫(kù)服務(wù)是否啟動(dòng)
docker ps
作用:列出容器
語(yǔ)法:docker ps [OPTIONS]
[root@FUCC ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
107b52416c13 3a2ef06682ac "docker-entrypoint..." 5 minutes ago Up 5 minutes 0.0.0.0:3306->3306/tcp quizzical_mcnulty
接下來(lái),我們進(jìn)入容器內(nèi)部看一看
docker exec
作用:在運(yùn)行的容器中執(zhí)行命令
語(yǔ)法:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
示例:docke exec -it 107b52416c13 bash
詳解:進(jìn)入ID為107b52416c13的容器中執(zhí)行bash命令
進(jìn)入容器中,我們和平時(shí)操作Linux沒什么兩樣,使用之前創(chuàng)建好的賬戶進(jìn)入MariaDB,成功!
[root@FUCC ~]# docker exec -it 107b52416c13 bash
root@107b52416c13:/# mysql -u root -p123456
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
講到這里,相信你對(duì)Docker已經(jīng)有了一些簡(jiǎn)單的認(rèn)識(shí),但這些都只是滄海一粟,單靠這篇文章是絕對(duì)講不完的(你標(biāo)題不是說入門看這一篇就夠了嗎),在下一篇文章里(如果有的話),咱們?cè)俸煤昧囊涣倪M(jìn)階的內(nèi)容,Bye~