亚洲精品综合久久中文字幕_国产女主播在线_日本中文一区二区三区_裸体一区二区三区_99re这里只有精品首页_成人国产精品免费网站_亚洲欧美网站在线观看_九九久久婷婷

5 個(gè)技巧,讓你的 Dockerfile 像個(gè)大師! 焦點(diǎn)關(guān)注

今天給朋友們分享的是我們的嘉賓- 前端大佬神光的關(guān)于 Dockerfile 使用技巧的文章,希望能對大家有所幫助。

以下是大佬原文:


Docker 是一種容器技術(shù),它可以在操作系統(tǒng)上創(chuàng)建多個(gè)相互隔離的容器。容器內(nèi)獨(dú)立安裝軟件、運(yùn)行服務(wù)。


(資料圖片)

但是,這個(gè)容器和宿主機(jī)還是有關(guān)聯(lián)的,比如可以把宿主機(jī)的端口映射到容器內(nèi)的端口、宿主機(jī)某個(gè)目錄掛載到容器內(nèi)的目錄。

比如映射了 3000 端口,那容器內(nèi) 3000 端口的服務(wù),就可以在宿主機(jī)的 3000 端口訪問了。

比如掛載了 /aaa 到容器的 /bbb/ccc,那容器內(nèi)讀寫 /bbb/ccc 目錄的時(shí)候,改的就是宿主機(jī)的 /aaa 目錄,反過來,改宿主機(jī) /aaa 目錄,容器內(nèi)的 /bbb/ccc 也會改,這倆同一個(gè)。

這分別叫做端口映射、數(shù)據(jù)卷(volume)掛載。

這個(gè)容器是通過鏡像起來的,通過 docker run image-name。

比如:

dockerrun-p3000:3000-v/aaa:/bbb/ccc--namexxx-containerxxx-image

通過 xxx-image 鏡像跑起來一個(gè)叫做 xxx-container 的容器。

-p 指定端口映射,映射宿主機(jī)的 3000 到容器的 3000 端口。

-v 指定數(shù)據(jù)卷掛載,掛載宿主機(jī)的 /aaa 到容器的 /bbb/ccc 目錄。

這個(gè)鏡像是通過 Dockerfile 經(jīng)過 build 產(chǎn)生的。

也就是這樣的流程:

一般在項(xiàng)目里維護(hù) Dockerfile ,然后執(zhí)行 docker build 構(gòu)建出鏡像、push 到鏡像倉庫,部署的時(shí)候 pull 下來用 docker run 跑起來。

基本 CI/CD 也是這樣的流程:

CI 的時(shí)候 git clone 項(xiàng)目,根據(jù) dockerfile 構(gòu)建出鏡像,打上 tag,push 到倉庫。

CD 的時(shí)候把打 tag 的鏡像下下來,docker run 跑起來。

這個(gè) Dockerfile 是在項(xiàng)目里維護(hù)的,雖然 CI/CD 流程不用自己搞,但是 Dockefile 還是要開發(fā)者自己寫的。

比如我創(chuàng)建一個(gè) nest 項(xiàng)目:

npxnestnewdockerfile-test-pnpm

然后執(zhí)行 npm run build,之后把它跑起來:

npmrunbuildnode./dist/main.js

這時(shí)候訪問 http://localhost:3000 可以看到 hello world,說明服務(wù)跑成功了:

那如何通過 Docker 部署這個(gè)服務(wù)呢?

首先,如果你沒安裝 docker,可以從 docker.com 下載 docker desktop,它自帶了 docker 命令:

跑起來可以看到本地的所有 docker 容器和鏡像:

命令行也是可用的:

然后我們來寫下 Dockerfile:

FROMnode:18WORKDIR/appCOPYpackage.json.COPY*.lock.RUNnpmconfigsetregistryhttps://registry.npmmirror.com/RUNnpminstallCOPY..RUNnpmrunbuildEXPOSE3000CMD[\"node\",\"./dist/main.js\"]

FROM node:18 是繼承 node:18 基礎(chǔ)鏡像。

WORKDIR /app 是指定當(dāng)前目錄為 /app

COPY 復(fù)制宿主機(jī)的 package.json 和 lock 文件到容器的當(dāng)前目錄,也就是 /app 下

RUN 是執(zhí)行命令,這里執(zhí)行了 npm install。

然后再復(fù)制其余的文件到容器內(nèi)。

EXPOSE 指定容器需要暴露的端口是 3000。

CMD 指定容器跑起來時(shí)執(zhí)行的命令是 node ./dist/main.js。

然后通過 docker build 把它構(gòu)建成鏡像:

dockerbuild-tdockerfile-test:first.

-t 是指定名字和標(biāo)簽,這里鏡像名為 dockerfile-test 標(biāo)簽為 first。

然后在 docker desktop 的 images 里就可以看到這個(gè)鏡像了:

就是現(xiàn)在鏡像稍微大了點(diǎn),有 1.45 G。

我們先跑起來看看:

docker run -d -p 2333:3000 --name first-container dockerfile-test:first

-d 是后臺運(yùn)行。

-p 指定端口映射,映射宿主機(jī)的 2333 端口到容器的 3000 端口。

--name 指定容器名

然后就可以看到容器部分有了這個(gè)容器了:

瀏覽器訪問 http://localhost:2333 就可以訪問容器內(nèi)跑的這個(gè)服務(wù):

這就是 Dockerfile 構(gòu)建成鏡像,然后通過容器跑起來的流程。

但是剛才也發(fā)現(xiàn)了,現(xiàn)在鏡像太大了,有 1.45G 呢,怎么優(yōu)化一下呢?

這就涉及到了第一個(gè)技巧:

使用 alpine 鏡像,而不是默認(rèn)的 linux 鏡像

docker 容器內(nèi)跑的是 linux 系統(tǒng),各種鏡像的 dockerfile 都會繼承 linux 鏡像作為基礎(chǔ)鏡像。

比如我們剛剛創(chuàng)建的那個(gè)鏡像,點(diǎn)開詳情可以看到它的鏡像繼承關(guān)系:

最終還是繼承了 debian 的 Linux 鏡像,這是一個(gè) linux 發(fā)行版。

但其實(shí)這個(gè) linux 鏡像可以換成更小的版本,也就是 alpine。

它裁剪了很多不必要的 linux 功能,使得鏡像體積大幅減小了。

alpine 是高山植物,就是很少的資源就能存活的意思。

我們改下 dockerfile,使用 alpine 的鏡像:

node:18-alpine3.14 是使用 18 版本的 node 鏡像,它底層使用 alpine 3.14 的基礎(chǔ)鏡像。

然后 docker build

dockerbuild-tdockerfile-test:second.

這次的 tag 為 second。

然后在 docker desktop 里看下:

好家伙,足足小了 900M。

我們點(diǎn)開看看:

可以看到它的底層 linux 鏡像是 alpine3.14。

體積小了這么多,功能還正常么?

我們跑跑看:

dockerrun-d-p2334:3000--namesecond-containerdockerfile-test:second

docker desktop 可以看到這個(gè)跑起來的容器:

瀏覽器訪問下,依然是正常的:

alpine 只是去掉了很多 linux 里用不到的功能,使得鏡像體積更小。

這就是第一個(gè)技巧。

然后再來看第二個(gè):

使用多階段構(gòu)建

看下這個(gè) dockerfile,大家發(fā)現(xiàn)有啥問題沒:

有的同學(xué)可能會說:為什么先復(fù)制 package.json 進(jìn)去,安裝依賴之后再復(fù)制其他文件,直接全部復(fù)制進(jìn)去不就行了?

不是的,這兩種寫法的效果不同。

docker 是分層存儲的,dockerfile 里的每一行指令是一層,會做緩存。

每次 docker build 的時(shí)候,只會從變化的層開始重新構(gòu)建,沒變的層會直接復(fù)用。

也就說現(xiàn)在這種寫法,如果 package.json 沒變,那么就不會執(zhí)行 npm install,直接復(fù)用之前的。

那如果一開始就把所有文件復(fù)制進(jìn)去呢?

那不管 package.json 變沒變,任何一個(gè)文件變了,都會重新 npm install,這樣沒法充分利用緩存,性能不好。

我們試試看就知道了:

現(xiàn)在重新跑 docker build,不管跑多少次,速度都很快,因?yàn)槲募]變,直接用了鏡像緩存:

dockerbuild-tdockerfile-test:second.

現(xiàn)在我們改下 README.md:

然后重新跑 build:

現(xiàn)在花了 25s,其實(shí)是沒有重新 npm install 的。

然后改下 package.json:

再跑 docker build

時(shí)間明顯多了很多,過程中你可以看到在 npm install 那層停留了很長時(shí)間。

這就是為什么要這樣寫:

這里沒問題,大家還能發(fā)現(xiàn)有沒有什么別的問題么?

問題就是源碼和很多構(gòu)建的依賴是不需要的,但是現(xiàn)在都保存在了鏡像里。

實(shí)際上我們只需要構(gòu)建出來的 ./dist 目錄下的文件還有運(yùn)行時(shí)的依賴。

那怎么辦呢?

這時(shí)可以用多階段構(gòu)建:

FROMnode:18-alpine3.14asbuild-stageWORKDIR/appCOPYpackage.json.RUNnpminstallCOPY..RUNnpmrunbuild#productionstageFROMnode:18-alpine3.14asproduction-stageCOPY--from=build-stage/app/dist/appCOPY--from=build-stage/app/package.json/app/package.jsonWORKDIR/appRUNnpminstall--productionEXPOSE3000CMD[\"node\",\"/app/main.js\"]

FROM 后面添加一個(gè) as 來指定當(dāng)前構(gòu)建階段的名字。

通過 COPY --from=xxx 可以從上個(gè)階段復(fù)制文件過來。

然后 npm install 的時(shí)候添加 --production,這樣只會安裝 dependencies 的依賴。

docker build 之后,只會留下最后一個(gè)階段的鏡像。

也就是說,最終構(gòu)建出來的鏡像里是沒有源碼的,有的只是 dist 的文件和運(yùn)行時(shí)依賴。

這樣鏡像就會小很多。

我們來試試看:

dockerbuild-tdockerfile-test:third-f222.Dockerfile.

標(biāo)簽為 third。

-f 是指定 Dockerfile 的名字。

然后 desktop 里看下構(gòu)建出來的鏡像:

鏡像體積比沒有用多階段構(gòu)建的時(shí)候小了 250 M。

然后跑起來試試看:

這次映射 2335 端口到容器內(nèi)的 3000 端口。

依然能正常訪問:

這就是第二個(gè)技巧,多階段構(gòu)建。

使用 ARG 增加構(gòu)建靈活性

我們寫一個(gè) test.js

console.log(process.env.aaa);console.log(process.env.bbb);

打印了環(huán)境變量 aaa、bbb

跑一下:

exportaaa=1bbb=2node./test.js

可以看到打印了這倆環(huán)境變量:

然后我們寫個(gè) dockerfile,文件名是 333.Dockerfile:

FROMnode:18-alpine3.14ARGaaaARGbbbWORKDIR/appCOPY./test.js.ENVaaa=${aaa}\bbb=${bbb}CMD[\"node\",\"/app/test.js\"]

使用 ARG 聲明構(gòu)建參數(shù),使用 ${xxx} 來取

然后用 ENV 聲明環(huán)境變量。

dockerfile 內(nèi)換行使用 \

之后構(gòu)建的時(shí)候傳入構(gòu)建參數(shù):

dockerbuild--build-argaaa=3--build-argbbb=4-targ-test-f333.Dockerfile.

通過 --build-arg xxx=yyy 傳入 ARG 參數(shù)的值。

點(diǎn)擊查看鏡像詳情,可以看到 ARG 已經(jīng)被替換為具體的值了:

然后跑起來:

dockerrun--namefourth-containerarg-test

這次就不用 -d 后臺運(yùn)行了,直接看下日志:

可以看到容器內(nèi)拿到的環(huán)境變量就是 ENV 設(shè)置的。

也就是說 ARG 是構(gòu)建時(shí)的參數(shù),ENV 時(shí)運(yùn)行時(shí)的變量。

靈活使用 ARG,可以增加 dockerfile 的靈活性。

這就是第三個(gè)技巧。

CMD 結(jié)合 ENTRYPOINT

前面我們指定容器跑起來之后運(yùn)行什么命令,用的是 CMD:

其實(shí)還可以寫成 ENTRYPOINT:

這兩種寫法有什么區(qū)別么?

我們來試試:

寫個(gè) 444.Dockerfile

FROMnode:18-alpine3.14CMD[\"echo\",\"光光\",\"到此一游\"]

然后 build:

dockerbuild-tcmd-test-f444.Dockerfile.

然后 run 一下:

dockerruncmd-test

沒有指定 --name 時(shí),會生成一個(gè)隨機(jī)容器名。

就是這種:

這不是重點(diǎn)。

重點(diǎn)是用 CMD 的時(shí)候,啟動命令是可以重寫的:

dockerruncmd-testecho\"東東\"

可以替換成任何命令。

而用 ENTRYPOINT 就不會:

FROMnode:18-alpine3.14ENTRYPOINT[\"echo\",\"光光\",\"到此一游\"]

docker build:

dockerbuild-tcmd-test-f444.Dockerfile.

docker run:

dockerruncmd-testecho\"東東\"

可以看到,現(xiàn)在 dockerfile 里 ENTRYPOINT 的命令依然執(zhí)行了。

docker run 傳入的參數(shù)作為了 echo 的額外參數(shù)。

這就是 ENTRYPOINT 和 CMD 的區(qū)別。

一般還是 CMD 用的多點(diǎn),可以靈活修改啟動命令。

其實(shí) ENTRYPOINT 和 CMD 是可以結(jié)合使用的。

比如這樣:

FROMnode:18-alpine3.14ENTRYPOINT[\"echo\",\"光光\"]CMD[\"到此一游\"]

docker build:

dockerbuild-tcmd-test-f444.Dockerfile.

docker run:

dockerruncmd-testdockerruncmd-test66666

當(dāng)沒傳參數(shù)的時(shí)候,執(zhí)行的是 ENTRYPOINT + CMD 組合的命令,而傳入?yún)?shù)的時(shí)候,只有 CMD 部分會被覆蓋。

這就起到了默認(rèn)值的作用。

所以,用 ENTRYPOINT + CMD 的方式更加靈活。

這是第四個(gè)技巧。

COPY vs ADD

其實(shí)不只是 ENTRYPOINT 和 CMD 相似,dockerfile 里還有一對指令也比較相似,就是 ADD 和 COPY。

這倆都可以把宿主機(jī)的文件復(fù)制到容器內(nèi)。

但有一點(diǎn)區(qū)別,就是對于 tar.gz 這種壓縮文件的處理上:

我們創(chuàng)建一個(gè) aaa 目錄,下面添加兩個(gè)文件:

使用 tar 命令打包:

tar-zcvfaaa.tar.gz./aaa

然后寫個(gè) 555.Dockerfile

FROMnode:18-alpine3.14ADD./aaa.tar.gz/aaaCOPY./aaa.tar.gz/bbb

docker build 生成鏡像:

dockerbuild-tadd-test-f555.Dockerfile.

docker run 跑起來:

dockerrun-d--namesixth-containeradd-test

可以看到,ADD 把 tar.gz 給解壓然后復(fù)制到容器內(nèi)了。

而 COPY 沒有解壓,它把文件整個(gè)復(fù)制過去了:

image.png
image.png

也就是說,ADD、COPY 都可以用于把目錄下的文件復(fù)制到容器內(nèi)的目錄下。

但是 ADD 還可以解壓 tar.gz 文件。

一般情況下,還是用 COPY 居多。

案例代碼上傳了 github:

https://github.com/QuarkGluonPlasma/nestjs-course-code/tree/main/dockerfile-test

總結(jié)

Docker 是流行的容器技術(shù),它可以在操作系統(tǒng)上創(chuàng)建多個(gè)隔離的容器,在容器內(nèi)跑各種服務(wù)。

它的流程是 Dockerfile 經(jīng)過 docker build 生成 docker 鏡像,然后 docker run 來跑容器。

docker run 的時(shí)候可以通過 -p 指定宿主機(jī)和容器的端口映射,通過 -v 掛載數(shù)據(jù)卷到容器內(nèi)的某個(gè)目錄。

CI/CD 基本也是這套流程,但是 Dockerfile 是要開發(fā)者自己維護(hù)的。

Dockerfile 有挺多技巧:

使用 alpine 的鏡像,而不是默認(rèn)的 linux 鏡像,可以極大減小鏡像體積,比如 node:18-alpine3.14 這種 使用多階段構(gòu)建,比如一個(gè)階段來執(zhí)行 build,一個(gè)階段把文件復(fù)制過去,跑起服務(wù)來,最后只保留最后一個(gè)階段的鏡像。這樣使鏡像內(nèi)只保留運(yùn)行需要的文件以及 dependencies。 使用 ARG 增加構(gòu)建靈活性,ARG 可以在 docker build 時(shí)通過 --build-arg xxx=yyy 傳入,在 dockerfile 中生效,可以使構(gòu)建過程更靈活。如果是想定義運(yùn)行時(shí)可以訪問的變量,可以通過 ENV 定義環(huán)境變量,值使用 ARG 傳入。 CMD 和 ENTRYPOINT 都可以指定容器跑起來之后運(yùn)行的命令,CMD 可以被覆蓋,而 ENTRYPOINT 不可以,兩者結(jié)合使用可以實(shí)現(xiàn)參數(shù)默認(rèn)值的功能。 ADD 和 COPY 都可以復(fù)制文件到容器內(nèi),但是 ADD 處理 tar.gz 的時(shí)候,還會做一下解壓。

靈活使用這些技巧,可以讓你的 Dockerfile 更加靈活、性能更好。


最后,歡迎學(xué)編程的朋友們加入魚皮的,和上萬名學(xué)編程的同學(xué)共享知識、交流進(jìn)步,學(xué)習(xí)原創(chuàng)項(xiàng)目并享有答疑指導(dǎo)服務(wù)。

往期推薦

關(guān)鍵詞:

資訊

日本韩国一区二区三区视频| 国产精品电影一区二区三区| 欧美69视频| 深夜在线视频| 亚洲品质视频自拍网| 亚洲精品中文字幕乱码三区| 性欧美videos高清hd4k| 精品国产区一区| 99热国产精品| 91成人国产| 亚洲欧美综合| 亚洲毛片av| 国产一区不卡在线| 亚洲影视综合| 国产精品综合| 国产亚洲毛片在线| 国产一区二区欧美| 金瓶狂野欧美性猛交xxxx | 国产精品入口麻豆九色| 青青草国产成人99久久| 香蕉人人精品| 精品剧情v国产在线观看| 99re成人精品视频| 91日韩在线专区| 喷水一区二区三区| 97在线精品| 欧美a视频在线| 国模套图日韩精品一区二区| 一二三四区精品视频| 欧美aaa在线| 日韩中文字幕一区二区三区| 中日韩免视频上线全都免费| 91丨精品丨国产| 18+视频在线观看| 在线视频网站| 亚洲的天堂在线中文字幕| 国产欧美日韩在线观看| 日韩av不卡一区二区| www 日韩| 欧美高清www午色夜在线视频| 国产一区二区成人久久免费影院| 国产中文一区| 日本不卡一区二区三区高清视频| 经典三级在线一区| 国产乱人伦丫前精品视频| 日韩午夜视频在线| 96sao精品免费视频观看| yiren22综合网成人| 91精品综合久久久久久| 岛国av一区二区| 欧美日韩不卡一区| 麻豆免费网站| 天堂电影一区| 最新国产一区| 久久亚洲春色中文字幕久久久| 欧美高清在线精品一区| 日本乱人伦aⅴ精品| 都市激情亚洲色图| 姬川优奈aav一区二区| 欧美国产综合一区二区| 国产拍揄自揄精品视频麻豆 | 午夜在线一区| 日韩av中文字幕一区二区三区 | 97se亚洲国产综合自在线观| 久久综合色综合88| 欧美在线高清视频| 狠狠干狠狠久久| 日韩欧美999| 亚洲色图丝袜美腿| 欧美日韩在线另类| 精品久久久久久久久久久久| 日韩欧美国产黄色| 欧美色老头old∨ideo| 亚洲一二三区视频在线观看| 91色九色蝌蚪| 国产精品久久777777| 最新不卡av在线| 国产亚洲视频系列| 国产精品白丝在线| 亚洲婷婷综合色高清在线| 久久大逼视频| 国产高清一区| 欧美日本不卡| 国产一区二区三区四区五区| 韩日一区二区| 国内自拍欧美| 在线免费观看欧美| 福利一区福利二区| 精品丝袜在线| 未满十八勿进黄网站一区不卡| 一区二区在线免费播放| 免费国产在线观看| 亚洲成人久久网| 精品日本高清在线播放| 不卡的电视剧免费网站有什么| 亚洲无线视频| 中文字幕一区二区三区中文字幕| se在线电影| av播放在线| 亚洲欧洲日产国码av系列天堂| 欧美性猛交xxxx黑人| 亚洲人吸女人奶水| 亚洲男人天堂| 欧美日韩亚洲精品内裤| 豆国产96在线|亚洲| 一本一本久久| 在线观看亚洲| 天天影视综合| 欧美美女黄色| 成人在线视频中文字幕| 亚洲男人在线| 国产精品久久久久久久久免费高清 | 成人免费视频视频在线观看免费| 国产精品久久占久久| 精品一区免费| 日本欧美大码aⅴ在线播放| 尤物网精品视频| 免费精品视频在线| 国产美女诱惑一区二区| 欧美日韩亚洲一区二区三区在线| 2020国产精品小视频| 在线免费观看的av| 亚洲综合影视| 在线三级中文| 亚洲少妇视频| 国产精品蜜月aⅴ在线| 国产综合色区在线观看| 麻豆蜜桃在线观看| 欧美激情啪啪| 亚洲伊人伊成久久人综合网| 日本一区二区三区中文字幕| 欧美经典一区| 精品国产一区二区三区四区| 亚洲手机视频| 欧美日韩不卡在线| 二区三区不卡| 懂色一区二区三区免费观看| h短视频大全在线观看| 久青青在线观看视频国产| 伪装者免费全集在线观看| 蜜桃视频在线观看www社区 | 狠狠色丁香久久综合频道| 激情婷婷亚洲| 蜜桃av一区二区| 91在线视频网址| 亚洲美女淫视频| 亚洲最色的网站| 欧美视频中文一区二区三区在线观看| 日韩欧美精品在线视频| av资源种子在线观看| 激情开心成人网| 另类春色校园亚洲| 久久精品不卡| 喷白浆一区二区| 久久99国产精品免费| av男人天堂一区| 午夜视黄欧洲亚洲| 精品国产电影一区二区| 欧美性猛交7777777| 成人a在线视频免费观看| 日本美女久久| 99久精品视频在线观看视频| 不卡视频一二三四| 麻豆导航在线观看| 久久精品中文| 日韩你懂的电影在线观看| 国产精品日韩精品在线播放| 久久久久久9999| 日本道免费精品一区二区三区| 欧美精品一区二区三区蜜臀 | 精品av久久707| 视频国产一区二区三区| 少妇一区视频| 中文字幕日韩一区二区不卡| 国产成人亚洲精品青草天美| 亚洲日本青草视频在线怡红院| 91精品国产免费久久综合| 成人三级黄色免费网站| 日韩三级不卡| 久久av中文字幕片| 欧美性猛交视频| 欧美精品少妇| 久久99精品国产自在现线| 久久福利资源站| 欧美日韩一本到| 蜜臀av在线| 欧美三级小说| 在线观看日韩高清av| 91在线看片| 久久久久久久久国产一区| 久久久久国产成人精品亚洲午夜| 日韩欧美不卡一区| 国产成人天天5g影院在线观看| 97超碰成人| 丁香啪啪综合成人亚洲小说| 91.麻豆视频| 97在线视频免费观看完整版| 红桃视频国产一区| 亚洲国产精品影院| 快射av在线播放一区|