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