自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Docker 是怎么實(shí)現(xiàn)的?前端怎么用 Docker 做部署?

系統(tǒng) Linux
Docker 是一種虛擬化技術(shù),通過(guò)容器的方式,它的實(shí)現(xiàn)原理依賴 linux 的 Namespace、Control Group、UnionFS 這三種機(jī)制。Namespace 做資源隔離,Control Group 做容器的資源限制,UnionFS 做文件系統(tǒng)的鏡像存儲(chǔ)、寫(xiě)時(shí)復(fù)制、鏡像合并。

代碼開(kāi)發(fā)完之后,要經(jīng)過(guò)構(gòu)建,把產(chǎn)物部署到服務(wù)器上跑起來(lái),這樣才能被用戶訪問(wèn)到。

不同的代碼需要不同的環(huán)境,比如 JS 代碼的構(gòu)建需要 node 環(huán)境,Java 代碼 需要 JVM 環(huán)境,一般我們會(huì)把它們隔離開(kāi)來(lái)單獨(dú)部署。

現(xiàn)在一臺(tái)物理主機(jī)的性能是很高的,完全可以同時(shí)跑很多個(gè)服務(wù),而我們又有環(huán)境隔離的需求,所以會(huì)用虛擬化技術(shù)把一臺(tái)物理主機(jī)變?yōu)槎嗯_(tái)虛擬主機(jī)來(lái)用。

現(xiàn)在主流的虛擬化技術(shù)就是 docker 了,它是基于容器的虛擬化技術(shù)。

它可以在一臺(tái)機(jī)器上跑多個(gè)容器,每個(gè)容器都有獨(dú)立的操作系統(tǒng)環(huán)境,比如文件系統(tǒng)、網(wǎng)絡(luò)端口等。

圖片

這也是為什么它的 logo 是這樣的:

圖片

那它是怎么實(shí)現(xiàn)的這種隔離的容器呢?

這就依賴操作系統(tǒng)的機(jī)制了:

linix 提供了一種叫 namespace 的機(jī)制,可以給進(jìn)程、用戶、網(wǎng)絡(luò)等分配一個(gè)命名空間,這個(gè)命名空間下的資源都是獨(dú)立命名的。

比如 PID namespace,也就是進(jìn)程的命名空間,它會(huì)使命名空間內(nèi)的這個(gè)進(jìn)程 id 變?yōu)?1,而 linux 的初始進(jìn)程的 id 就是 1,所以這個(gè)命名空間內(nèi)它就是所有進(jìn)程的父進(jìn)程了。

而 IPC namespace 能限制只有這個(gè) namespace 內(nèi)的進(jìn)程可以相互通信,不能和 namespace 外的進(jìn)程通信。

Mount namespace 會(huì)創(chuàng)建一個(gè)新的文件系統(tǒng),namespace 內(nèi)的文件訪問(wèn)都是在這個(gè)文件系統(tǒng)之上。

類似這樣的 namespace 一共有 6 種:

  • PID namespace:進(jìn)程 id 的命名空間
  • IPC namespace:進(jìn)程通信的命名空間
  • Mount namespace:文件系統(tǒng)掛載的命名空間
  • Network namespace:網(wǎng)絡(luò)的命名空間
  • User namespace:用戶和用戶組的命名空間
  • UTS namespace:主機(jī)名和域名的命名空間

通過(guò)這 6 種命名空間,Docker 就實(shí)現(xiàn)了資源的隔離。

但是只有命名空間的隔離還不夠,這樣還是有問(wèn)題的,比如如果一個(gè)容器占用了太多的資源,那就會(huì)導(dǎo)致別的容器受影響。

怎么能限制容器的資源訪問(wèn)呢?

這就需要 linux 操作系統(tǒng)的另一種機(jī)制:Control Group。

創(chuàng)建一個(gè) Control Group 可以給它指定參數(shù),比如 cpu 用多少、內(nèi)存用多少、磁盤(pán)用多少,然后加到這個(gè)組里的進(jìn)程就會(huì)受到這個(gè)限制。

這樣,創(chuàng)建容器的時(shí)候先創(chuàng)建一個(gè) Control Group,指定資源的限制,然后把容器進(jìn)程加到這個(gè) Control Group 里,就不會(huì)有容器占用過(guò)多資源的問(wèn)題了。

那這樣就完美了么?

其實(shí)還有一個(gè)問(wèn)題:每個(gè)容器都是獨(dú)立的文件系統(tǒng),相互獨(dú)立,而這些文件系統(tǒng)之間可能很大部分都是一樣的,同樣的內(nèi)容占據(jù)了很大的磁盤(pán)空間,會(huì)導(dǎo)致浪費(fèi)。

那怎么解決這個(gè)問(wèn)題呢?

Docker 設(shè)計(jì)了一種分層機(jī)制:

每一層都是不可修改的,也叫做鏡像。那要修改怎么辦呢?

會(huì)創(chuàng)建一個(gè)新的層,在這一層做修改

圖片

然后通過(guò)一種叫做 UnionFS 的機(jī)制把這些層合并起來(lái),變成一個(gè)文件系統(tǒng):

圖片

這樣如果有多個(gè)容器內(nèi)做了文件修改,只要?jiǎng)?chuàng)建不同的層即可,底層的基礎(chǔ)鏡像是一樣的。

Docker 通過(guò)這種分層的鏡像存儲(chǔ),寫(xiě)時(shí)復(fù)制的機(jī)制,極大的減少了文件系統(tǒng)的磁盤(pán)占用。

而且這種鏡像是可以復(fù)用的,上傳到鏡像倉(cāng)庫(kù),別人拉下來(lái)也可以直接用。

比如下面這張 Docker 架構(gòu)圖:

圖片

docker 文件系統(tǒng)的內(nèi)容是通過(guò)鏡像的方式存儲(chǔ)的,可以上傳到 registry 倉(cāng)庫(kù)。docker pull 拉下來(lái)之后經(jīng)過(guò) docker run 就可以跑起來(lái)。

回顧一下 Docker 實(shí)現(xiàn)原理的三大基礎(chǔ)技術(shù):

  • Namespace:實(shí)現(xiàn)各種資源的隔離
  • Control Group:實(shí)現(xiàn)容器進(jìn)程的資源訪問(wèn)限制
  • UnionFS:實(shí)現(xiàn)容器文件系統(tǒng)的分層存儲(chǔ),寫(xiě)時(shí)復(fù)制,鏡像合并

都是缺一不可的。

上圖中還有個(gè) docker build 是干啥的呢?

一般我們生成鏡像都是通過(guò) dockerfile 來(lái)描述的。

比如這樣:

FROM node:10

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install http-server -g

RUN npm install && npm run build

CMD http-server ./dist

Dokcer 是分層存儲(chǔ)的,修改的時(shí)候會(huì)創(chuàng)建一個(gè)新的層,所以這里的每一行都會(huì)創(chuàng)建一個(gè)新的層。

這些指令的含義如下:

  • 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í)行的命令

上面這個(gè) dockerfile 的作用不難看出來(lái),就是在 node 環(huán)境下,把項(xiàng)目復(fù)制過(guò)去,執(zhí)行依賴安裝和構(gòu)建。

我們通過(guò) docker build 就可以根據(jù)這個(gè) dockerfile 來(lái)生成鏡像。

然后執(zhí)行 docker run 把這個(gè)鏡像跑起來(lái),這時(shí)候就會(huì)執(zhí)行 http-server ./dist 來(lái)啟動(dòng)服務(wù)。

這個(gè)就是一個(gè) docker 跑 node 靜態(tài)服務(wù)的例子。

但其實(shí)這個(gè)例子不是很好,從上面流程的描述我們可以看出來(lái),構(gòu)建的過(guò)程只是為了拿到產(chǎn)物,容器運(yùn)行的時(shí)候就不再需要了。

那能不能把構(gòu)建分到一個(gè)鏡像里,然后把產(chǎn)物賦值到另一個(gè)鏡像,這樣單獨(dú)跑產(chǎn)物呢?

確實(shí)可以,而且這也是推薦的用法。

那豈不是要 build 寫(xiě)一個(gè) dockerfile,run 寫(xiě)一個(gè) dockerfile 嗎?

也不用,docker 支持多階段構(gòu)建,比如這樣:

# build stage
FROM node:10 AS build_image

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install && npm run build

# production stage
FROM node:10

WORKDIR /app

COPY --from=build_image /app/dist ./dist

RUN npm i -g http-server

CMD http-server ./dist

我們把兩個(gè)鏡像的生成過(guò)程寫(xiě)到了一個(gè) dockerfile 里,這是 docker 支持的多階段構(gòu)建。

第一個(gè) FROM 里我們寫(xiě)了 as build_image,這是把第一個(gè)鏡像命名為 build_image。

后面第二個(gè)鏡像 COPY 的時(shí)候就可以指定 --from=build_image 來(lái)從那個(gè)鏡像復(fù)制內(nèi)容了。

這樣,最終只會(huì)留下第二個(gè)鏡像,這個(gè)鏡像里只有生產(chǎn)環(huán)境需要的依賴,體積更小。傳輸速度、運(yùn)行速度也會(huì)更快。

構(gòu)建鏡像和運(yùn)行鏡像分離,這個(gè)算是一種最佳實(shí)踐了。

一般我們都是在 jenkins 里跑,push 代碼的時(shí)候,通過(guò) web hooks 觸發(fā) jenkins 構(gòu)建,最終產(chǎn)生運(yùn)行時(shí)的鏡像,上傳到 registry。

部署的時(shí)候把這個(gè)鏡像 docker pull 下來(lái),然后 docker run 就完成了部署。

node 項(xiàng)目的 dockerfile 大概怎么寫(xiě)我們知道了,那前端項(xiàng)目呢?

大概是這樣的:

# build stage
FROM node:14.15.0 as build-stage

WORKDIR /app

COPY package.json ./

RUN npm install

COPY . .

RUN npm run build

# production stage
FROM nginx:stable-perl as production-stage

COPY --from=build-stage /app/dist /usr/share/nginx/html

COPY --from=build-stage /app/default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

也是 build 階段通過(guò)一個(gè)鏡像做構(gòu)建,然后再制作一個(gè)鏡像把產(chǎn)物復(fù)制過(guò)去,然后用 nginx 跑一個(gè)靜態(tài)服務(wù)。

一般公司內(nèi)部署前端項(xiàng)目都是這樣的。

不過(guò)也不一定。

因?yàn)楣静渴鹎岸舜a的服務(wù)是作為 CDN 的源站服務(wù)器的,CDN 會(huì)從這里取文件,然后在各地區(qū)的緩存服務(wù)器緩存下來(lái)。

而阿里云這種云服務(wù)廠商都提供了對(duì)象存儲(chǔ)服務(wù),可以直接把靜態(tài)文件上傳到 oss,根本不用自己部署:

圖片

但是,如果是內(nèi)部的網(wǎng)站,或者私有部署之類的,還是要用 docker 部署的。

總結(jié)

Docker 是一種虛擬化技術(shù),通過(guò)容器的方式,它的實(shí)現(xiàn)原理依賴 linux 的 Namespace、Control Group、UnionFS 這三種機(jī)制。

Namespace 做資源隔離,Control Group 做容器的資源限制,UnionFS 做文件系統(tǒng)的鏡像存儲(chǔ)、寫(xiě)時(shí)復(fù)制、鏡像合并。

一般我們是通過(guò) dockerfile 描述鏡像構(gòu)建的過(guò)程,然后通過(guò) docker build 構(gòu)建出鏡像,上傳到 registry。

鏡像通過(guò) docker run 就可以跑起來(lái),對(duì)外提供服務(wù)。

用 dockerfile 做部署的最佳實(shí)踐是分階段構(gòu)建,build 階段單獨(dú)生成一個(gè)鏡像,然后把產(chǎn)物復(fù)制到另一個(gè)鏡像,把這個(gè)鏡像上傳 registry。

這樣鏡像是最小的,傳輸速度、運(yùn)行速度都比較快。

前端、node 的代碼都可以用 docker 部署,前端代碼的靜態(tài)服務(wù)還要作為 CDN 的源站服務(wù)器,不過(guò)我們也不一定要自己部署,很可能直接用阿里云的 OSS 對(duì)象存儲(chǔ)服務(wù)了。

理解了 Docker 的實(shí)現(xiàn)原理,知道了怎么寫(xiě) dockerfile 還有 dockerfile 的分階段構(gòu)建,就可以應(yīng)付大多數(shù)前端部署需求了。

責(zé)任編輯:武曉燕 來(lái)源: 神光的編程秘籍
相關(guān)推薦

2022-04-13 08:20:32

DockerGo項(xiàng)目

2024-02-19 00:00:00

Docker輕量級(jí)容器

2014-11-25 14:04:59

DockerDocker Nodeweb應(yīng)用部署

2020-12-18 09:23:41

KubernetesDocker

2020-03-16 09:45:09

前端docker代碼

2012-05-24 14:58:55

開(kāi)源代碼

2023-12-14 17:21:28

前端性能優(yōu)化

2014-12-02 10:47:53

Nginxdocker私有Docker注冊(cè)

2022-05-05 09:14:41

AlpineDocker鏡像開(kāi)發(fā)

2011-03-11 09:53:46

FacebookMySQL

2017-07-20 13:11:46

Code ReviewPR評(píng)審

2024-05-31 09:31:00

2024-03-19 00:52:52

前端網(wǎng)頁(yè)篡改

2013-12-16 15:19:10

GitDocker

2021-06-07 05:46:20

前端架構(gòu)前端架構(gòu)

2023-06-13 07:54:17

DOM 封裝作用域

2023-07-23 08:17:20

系統(tǒng)Linux

2009-02-17 18:52:06

網(wǎng)絡(luò)虛擬化路由系統(tǒng)數(shù)據(jù)中心

2024-09-18 13:49:42

2019-12-04 11:00:42

前端DockerKubernetes
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)