后端系統(tǒng)會(huì)部署很多服務(wù),包括我們自己開發(fā)的服務(wù),還有 mysql、redis 等中間件的服務(wù),部署它們需要一系列依賴的安裝、環(huán)境變量的設(shè)置等等。
如果你要部署多臺(tái)機(jī)器的話,同樣的操作要重復(fù)多次,萬(wàn)一哪一步漏掉了,服務(wù)就跑不起來(lái)了。
就很麻煩。
而 Docker 就能完美解決這個(gè)問(wèn)題:
它把系統(tǒng)的所有文件封裝成一個(gè)鏡像,鏡像跑起來(lái)作為容器,它可以在一臺(tái)機(jī)器上跑多個(gè)容器,每個(gè)容器都有獨(dú)立的操作系統(tǒng)環(huán)境,比如文件系統(tǒng)、網(wǎng)絡(luò)端口等,在容器內(nèi)跑各種服務(wù)。
這樣整個(gè)環(huán)境都保存在這個(gè)鏡像里,部署多個(gè)實(shí)例只要通過(guò)這個(gè)鏡像跑多個(gè)容器就行。
這也是為什么它的 logo 是這樣的:
Docker 提供了 Docker Hub 鏡像倉(cāng)庫(kù),可以把本地鏡像 push 到倉(cāng)庫(kù)或者從倉(cāng)庫(kù) pull 鏡像到本地。
我們 pull 個(gè)鏡像下來(lái)試試看:
首先需要安裝 Docker,直接從官網(wǎng)下載 docker desktop 就行:
它內(nèi)置了 docker 命令。
把它安裝到系統(tǒng)之后,可以在命令行看下 docker 命令是否可用:
如果不可用,那要設(shè)置下這個(gè):
點(diǎn)擊 Settings > Advanced,里面有兩種安裝路徑,如果是 /user/local/bin,那 docker 命令就是直接可用的,因?yàn)檫@個(gè)路徑在 PATH 變量里。
如果是第二種,那就需要手動(dòng)把 $HOME/.docker/bin 加到 PATH 環(huán)境變量里。
然后我們來(lái)看看 docker desktop 的界面:
images 是本地的所有鏡像,containers 是鏡像跑起來(lái)的容器。
docker desktop 可以可視化的管理它們,很方便。
我們 pull 一個(gè)鏡像試試看。
搜索 nginx 鏡像,點(diǎn)擊 pull(搜索這步需要科學(xué)上網(wǎng),不然搜不到)。
pull 下來(lái)之后,就可以在本地 images 看到了:
點(diǎn)擊 run 會(huì)讓你填一些參數(shù):
首先是名字,如果不填,docker desktop 會(huì)給你生成隨機(jī)的容器名字。
就是這種:
然后是端口,容器內(nèi)跑的 nginx 服務(wù)是在 80 端口,你要把宿主機(jī)的某個(gè)端口映射到容器的 80 端口才可以訪問(wèn)。
接下來(lái)是數(shù)據(jù)卷 volume,這個(gè)是把宿主機(jī)某個(gè)目錄掛到容器內(nèi)。
因?yàn)槿萜魇晴R像跑起來(lái)的,下次再用這個(gè)鏡像跑的還是同樣的容器,那你在容器內(nèi)保存的數(shù)據(jù)就會(huì)消失。
所以我們都是把某個(gè)宿主機(jī)目錄,掛載到容器內(nèi)的某個(gè)保存數(shù)據(jù)的目錄,這樣數(shù)據(jù)是保存在宿主機(jī)的,下次再用鏡像跑一個(gè)新容器,只要把這個(gè)目錄掛載上去就行。
至于環(huán)境變量,這個(gè)就很容易理解了。
我們分別設(shè)置一下:
掛載本地的 /tmp/aaa 到容器內(nèi)的 /user/share/nginx/html 目錄。
點(diǎn)擊 run:
可以看到容器內(nèi)的 nginx 服務(wù)跑起來(lái)了。
我們?cè)?/tmp/aaa 目錄下添加一個(gè) index.html:
瀏覽器訪問(wèn) http://localhost 就可以訪問(wèn)到:
這就說(shuō)明數(shù)據(jù)卷掛載成功了。
點(diǎn)擊 files 標(biāo)簽就可以看到容器內(nèi)的文件。
可以看到 /usr/share/nginx/html 被標(biāo)識(shí)為 mounted,就是掛載目錄的意思:
我們?cè)僭诒镜靥砑右粋€(gè)文件:
你會(huì)發(fā)現(xiàn)容器內(nèi)這個(gè)目錄內(nèi)容也變了:
這就是 volume 掛載的作用。
如果你掛載某些目錄報(bào)錯(cuò),是因?yàn)?docker desktop 掛載的目錄是需要配置的,在 Settings > Resources > File Sharing 里加一下就行:
至于掛載到的目錄,在鏡像搜索結(jié)果頁(yè)有寫:
通過(guò)命令行 docker run 來(lái)跑鏡像, -v 是指定掛載的數(shù)據(jù)卷,后面的 :ro 代表 readonly,也就是容器內(nèi)這個(gè)目錄只讀,:rw 表示容器內(nèi)可以讀寫這個(gè)目錄。
這就是數(shù)據(jù)卷的作用。
此外,你還可以進(jìn)入到容器內(nèi)執(zhí)行各種命令:
是不是感覺(jué) docker 學(xué)起來(lái)還挺簡(jiǎn)單的?
docker 常用的就是這些東西。
當(dāng)然,在服務(wù)器上沒(méi)有 Docker Desktop 這種東西,還是要敲命令的。
比如我們點(diǎn)擊 pull 按鈕,就相當(dāng)于執(zhí)行了 docker pull:
dockerpullnginx:latest
latest 是標(biāo)簽,也就是這個(gè):
然后我們點(diǎn)擊 run 按鈕,填了個(gè)表單,就相當(dāng)于執(zhí)行了 docker run:
dockerrun--namenginx-test2-p80:80-v/tmp/aaa:/usr/share/nginx/html-eKEY1=VALUE1-dnginx:latest
-p 是端口映射
-v 是指定數(shù)據(jù)卷掛載目錄
-e 是指定環(huán)境變量
-d 是后臺(tái)運(yùn)行
對(duì)照下前面可視化界面,是不是瞬間就懂了:
docker run 會(huì)返回一個(gè)容器的 hash:
就是這里的 id:
這個(gè)界面可以用 docker ps 來(lái)獲取:
它是顯示容器列表的,默認(rèn)是運(yùn)行中的。
想顯示全部的,可以加個(gè) -a
除了 container 列表,image 鏡像列表也可以通過(guò) docker images 命令獲取:
我們?cè)谌萜鞯?terminal 里執(zhí)行命令,對(duì)應(yīng)的是 docker exec 命令:
-i 是 terminal 交互的方式運(yùn)行
-t 是 tty 終端類型
然后指定容器 id 和 shell 類型,就可以交互的方式在容器內(nèi)執(zhí)行命令了。
查看日志,對(duì)應(yīng) docker logs 命令:
輸入 exit 退出:
docker inspect 可以查看容器的詳情
對(duì)應(yīng) desktop 里的 inspect 的 tab:
docker volume 可以管理數(shù)據(jù)卷:
對(duì)應(yīng) desktop 的這部分:
此外,還有這些常用命令:
docker start:?jiǎn)?dòng)一個(gè)已經(jīng)停止的容器
docker rm:刪除一個(gè)容器
docker stop:停止一個(gè)容器
都可以通過(guò) docker desktop 很方便的操作。
那如果我們要自己制作一個(gè)這樣的鏡像,怎么做呢?
docker 容器內(nèi)就是一個(gè)獨(dú)立的系統(tǒng)環(huán)境,想想如果在這樣一個(gè)系統(tǒng)上,要安裝 nginx 服務(wù),怎么做呢?
需要執(zhí)行一些命令、復(fù)制一些文件進(jìn)來(lái),然后啟動(dòng)服務(wù)。
制作鏡像自然也要進(jìn)行這樣的過(guò)程,不過(guò)可以自動(dòng)化。
只要在 dockerfile 里聲明要做哪些事情,docker build 的時(shí)候就會(huì)根據(jù)這個(gè) dockerfile 來(lái)自動(dòng)化構(gòu)建出一個(gè)鏡像來(lái)。
比如這樣:
FROMnode:latest WORKDIR/app COPY.. RUNnpminstall-ghttp-server EXPOSE8080 CMD["http-server","-p","8080"]
這些指令的含義如下:
FROM:基于一個(gè)基礎(chǔ)鏡像來(lái)修改
WORKDIR:指定當(dāng)前工作目錄
COPY:把容器外的內(nèi)容復(fù)制到容器內(nèi)
EXPOSE:聲明當(dāng)前容器要訪問(wèn)的網(wǎng)絡(luò)端口,比如這里起服務(wù)會(huì)用到 8080
RUN:在容器內(nèi)執(zhí)行命令
CMD:容器啟動(dòng)的時(shí)候執(zhí)行的命令
我們先通過(guò) FROM 繼承了 node 基礎(chǔ)鏡像,里面就有 npm、node 這些命令了。
通過(guò) WORKDIR 指定當(dāng)前目錄。
然后通過(guò) COPY 把 Dockerfile 同級(jí)目錄下的內(nèi)容復(fù)制到容器內(nèi),這里的 . 也就是 /app 目錄
之后通過(guò) RUN 執(zhí)行 npm install,全局安裝 http-server
通過(guò) EXPOSE 指定要暴露的端口
CMD 指定容器跑起來(lái)之后執(zhí)行的命令,這里就是執(zhí)行 http-server 把服務(wù)跑起來(lái)。
把這個(gè)文件保存為 Dockerfile,然后在同級(jí)添加一個(gè) index.html
然后通過(guò) docker build 就可以根據(jù)這個(gè) dockerfile 來(lái)生成鏡像。
dockerbuild-taaa:ccc.
aaa 是鏡像名,ccc 是鏡像的標(biāo)簽
FROM 是繼承一個(gè)基礎(chǔ)鏡像,看輸出也可以看出來(lái),前面都是 node 鏡像的內(nèi)容,會(huì)一層層下載下來(lái)。
最后才是本地的我們添加的那些。
這時(shí)你在 desktop 的 images 列表里就可以看到這個(gè)鏡像了:
然后執(zhí)行 docker run 把這個(gè)鏡像跑起來(lái),用 desktop 我們就直接點(diǎn)擊 run 按鈕了:
會(huì)讓你輸入這些內(nèi)容:
是不是前面用 nginx 鏡像的感覺(jué)回來(lái)了?這次是我們自己 build 的鏡像。
指定容器名、映射的端口、點(diǎn)擊 run:
然后可以看到容器內(nèi)的日志,服務(wù)啟動(dòng)成功了:
當(dāng)然,容器內(nèi)打印的是 8080 端口,但在容器外要用映射的 8888 端口訪問(wèn):
訪問(wèn) http://localhost:8888 就可以看到我們?cè)?html 寫的內(nèi)容了:
在容器內(nèi)頁(yè)打印了一條訪問(wèn)日志:
至此,我們寫的第一個(gè) dockerfile 和 build 出的第一個(gè)鏡像就跑成功了!
我們?cè)?files 里看看 /app 下是啥內(nèi)容:
雙擊 index.html,可以看到這就是我們 build 鏡像的時(shí)候 COPY 進(jìn)去的文件。
但是我們想修改靜態(tài)文件怎么辦呢?
進(jìn)入容器內(nèi)改太麻煩,不如把這個(gè) /app 目錄設(shè)置為掛載點(diǎn)吧。
這樣改下 Dockerfile:
然后重新 build 出一個(gè)鏡像來(lái):
docker build -t aaa:ddd -f 2.Dockerfile
因?yàn)楝F(xiàn)在不是默認(rèn)的 Dockerfile 了,需要用 -f 指定下 dockefile 的文件名。
構(gòu)建完之后再 run 一下這個(gè)新鏡像:
這次把桌面目錄作為數(shù)據(jù)卷掛載到 /app 目錄了:
容器跑起來(lái)后可以看到確實(shí)掛載上去了,也標(biāo)識(shí)為了 mount:
瀏覽器訪問(wèn)下:
在 inspect 這里也可以看到掛載的目錄:
有同學(xué)說(shuō),就算不在 dockerfile 里指定 VOLUME,還是可以 docker run 的時(shí)候通過(guò) -v 掛載數(shù)據(jù)卷呀。
那為啥還要指定 VOLUME?
在 dockerfile 里指定 VOLUME 之后,如果你 docker run 的時(shí)候沒(méi)有帶 -v,那會(huì)放在一個(gè)臨時(shí)的目錄里。
比如直接點(diǎn)擊 run,不設(shè)置參數(shù):
docker 會(huì)隨機(jī)給他生成一個(gè)名字。
還會(huì)隨機(jī)生成一個(gè)目錄作為數(shù)據(jù)卷掛載上去:
inspect 可以看到這時(shí)候的路徑是一個(gè)臨時(shí)的目錄:
這樣就算你刪了容器,數(shù)據(jù)也可以在這里找回。
設(shè)想下,如果你跑了個(gè) mysql 容器,存了很多數(shù)據(jù),但是跑容器的時(shí)候沒(méi)指定數(shù)據(jù)卷。有一天,你把容器刪了,所有數(shù)據(jù)都沒(méi)了,可不可怕?
為了避免這種情況,mysql 的 dockerfile 里是必須聲明 volume 的,這樣就算你沒(méi)通過(guò) -v 指定數(shù)據(jù)卷,將來(lái)也可以找回?cái)?shù)據(jù)。
在鏡像詳情可以看到 mysql 的 dockerfile,確實(shí)聲明了 volume
這樣就能保證數(shù)據(jù)不丟失。
總結(jié)
Docker 可以把環(huán)境封裝成鏡像,鏡像跑起來(lái)是一個(gè)獨(dú)立的容器。通過(guò)這種方式可以快速部署多個(gè)相同的實(shí)例。
docker 提供了一個(gè) desktop 工具,可以可視化的操作 docker,包括容器、鏡像、volume 等
我們 pull 了一個(gè) nginx 鏡像下來(lái),指定端口映射、掛載的數(shù)據(jù)卷,并把它跑起來(lái)了。
這就是 docker 的基本用法。
當(dāng)然,這些可視化的操作都有對(duì)應(yīng)的命令,當(dāng)服務(wù)器上沒(méi)有桌面的時(shí)候,就需要用命令行操作了。
docker 鏡像是通過(guò) dockerfile 構(gòu)建出來(lái)的。
我們寫了第一個(gè) dockerfile,通過(guò) FROM、WORKDIR、COPY、RUN、EXPOSE、CMD 等指令聲明了一個(gè) http-server 提供靜態(tài)服務(wù)的鏡像。
docker run 這個(gè)鏡像就可以生成容器,指定映射的端口、掛載的數(shù)據(jù)卷、環(huán)境變量等。
VOLUME 指令看起來(lái)沒(méi)啥用,但能保證你容器內(nèi)某個(gè)目錄下的數(shù)據(jù)一定會(huì)被持久化,能保證沒(méi)掛載數(shù)據(jù)卷的時(shí)候,數(shù)據(jù)不丟失。
寫完這個(gè) dockerfile,相信你會(huì)對(duì) docker 鏡像、容器有更具體的理解了。
不得不說(shuō),用 desktop 來(lái)學(xué) docker 真是太簡(jiǎn)單了。
-
變量
+關(guān)注
關(guān)注
0文章
613瀏覽量
28360 -
鏡像
+關(guān)注
關(guān)注
0文章
164瀏覽量
10707 -
Docker
+關(guān)注
關(guān)注
0文章
457瀏覽量
11846
原文標(biāo)題:通過(guò) Desktop 學(xué) Docker 也太簡(jiǎn)單了
文章出處:【微信號(hào):良許Linux,微信公眾號(hào):良許Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論