引言
假如我們沒有虛擬機,該怎么樣讓別人運行我們的項目犹撒,初學(xué)的時候,我們往往是打包代碼粒褒,發(fā)給對方识颊,然后讓對方安裝相應(yīng)的環(huán)境,比如node奕坟、數(shù)據(jù)庫祥款,要是配置不同,項目很有可能無法運行月杉,還會報錯刃跛,如果多個人想要運行這份代碼,那還得多次安裝配置環(huán)境苛萎。
當(dāng)學(xué)習(xí)完虛擬機之后桨昙,我們可以直接發(fā)個鏈接給別人就可以查看,就得開始部署在服務(wù)器上腌歉。然后去買了服務(wù)器蛙酪,學(xué)了linux,去服務(wù)器上搭建環(huán)境,下載node翘盖、mongogb桂塞,安裝各種項目啟動需要的東西,中途可能還安裝不成功馍驯,然后XShell上傳打包好的代碼阁危,然后解壓運行玛痊,測試是否運行正常,ok狂打,可以鏈接發(fā)給別人看了擂煞。
但是總歸是有些不方便吧,畢竟安裝虛擬機配置環(huán)境菱父,運行起來之后還特別吃內(nèi)存颈娜,占用資源直接一半。
直到學(xué)習(xí)docker之后浙宜,發(fā)現(xiàn)這些問題突然就可以得到解決了官辽,那接下來讓我們看看docker到底是什么,解決了什么樣的問題粟瞬,怎么操作吧
1.環(huán)境配置的問題
軟件開發(fā)的時候同仆,環(huán)境配置不同,很可能造成項目無法運行裙品,每次其他人運行都需要配置相應(yīng)的環(huán)境俗批,
從根本上解決問題:軟件帶環(huán)境安裝,安裝的時候把原始環(huán)境一模一樣的復(fù)制過去
解決方案:
(1)虛擬機
帶環(huán)境安裝的一種解決辦法市怎,可以在windows上運行l(wèi)inux系統(tǒng)岁忘,通過虛擬機可以還原軟件原始環(huán)境
優(yōu)點:
- 相當(dāng)于真實系統(tǒng),但是對于底層又是一個普通文件区匠,可以隨時刪除干像,方便刪除
缺點:
資源占用多:在物理服務(wù)器創(chuàng)建一臺虛擬機時,便需要虛擬出一套硬件并在上面運行完整的操作系統(tǒng)
冗余步驟多:必須有完整的操作過程驰弄,比如登錄
啟動慢
(2)Linux容器
Linux 容器(Linux Containers麻汰,縮寫為 LXC):Linux不是模擬的完整的操作系統(tǒng),而是對進程進行隔離戚篙,在正常進程的外面套了一個保護層形成容器五鲫。對于容器里面的進程來說,它接觸到的各種資源都是虛擬的岔擂,從而實現(xiàn)與底層系統(tǒng)的隔離
優(yōu)勢【相對于虛擬機】:
啟動快
用資源少
體積形晃埂:只是一個進程,而不是完整的操作系統(tǒng)
類似一個輕量級的虛擬機乱灵,但是對比于虛擬機忆某,優(yōu)點很多,虛擬機和linux都是帶環(huán)境安裝的解決辦法阔蛉,而Docker就是在linux容器的基礎(chǔ)上發(fā)展的弃舒。
2.Docker是什么
Docker 基于Linux 容器的一種封裝,提供簡單易用的容器使用接口。
Docker 將應(yīng)用程序與該程序的依賴聋呢,打包在一個文件里面苗踪。運行這個文件,就會生成一個虛擬容器削锰。就不用擔(dān)心環(huán)境問題了通铲,容器還可以進行版本管理、復(fù)制修改等器贩。
常常我們會覺得Docker是一個小型的虛擬機颅夺,但是其實本質(zhì)不同,Docker不是在宿主機上虛擬出一套硬件后再虛擬出一個操作系統(tǒng)蛹稍,而是讓 Docker 容器里面的進程直接運行在宿主機上(Docker 會做文件吧黄、網(wǎng)絡(luò)等的隔離),被隔離的進場也就是容器唆姐,可以完全獨立于宿主機的進程
(1)Docker優(yōu)點
(1)提供一次性的環(huán)境:本地測試他人軟件拗慨,持續(xù)集成的時候提供單元測試和構(gòu)建的環(huán)境
(2)配置簡化:將環(huán)境和配置放入代碼然后部署,同樣的Docker配置能夠在各種環(huán)境中使用
(3)快速部署:適用于持續(xù)集成和持續(xù)交付(CI/CD)
(2)docker容器和虛擬機的對比
對比 | docker容器 | 虛擬機 |
---|---|---|
啟動時間 | 秒級 | 分鐘級 |
系統(tǒng)支持量 | 上千個 | 一般只能幾十個 |
硬盤占用 | KB-MB | GB-TB |
隔離級別 | 進程級 | 操作系統(tǒng)級 |
3.Docker組成
(1)Docker架構(gòu)
Docker使用C/S架構(gòu)
客戶端:Docker客戶端與 Docker守護進程對話奉芦,赵抢,比如使用docker run等命令
服務(wù)端:負(fù)責(zé)構(gòu)建、運行和分發(fā) Docker 容器的繁重工
Client:客戶端是是Docker用戶和Docker交互的方式,比如那些執(zhí)行命令
DOCKER_HOST:用來監(jiān)聽客戶端請求命令管理Docker對象的
-
Registry:鏡像倉庫存儲Docker鏡像声功,類似代碼倉庫github烦却,比如Docker Hub (官方的),本文后續(xù)使用Harbor(私有的)
(2)Docker對象:
Docker管理的對象包含鏡像先巴、容器其爵、網(wǎng)絡(luò)、數(shù)據(jù)卷筹裕,僅介紹鏡像和容器醋闭,是在操作中常用的
Image(鏡像):Docker 把應(yīng)用程序及其依賴[提供運行項目的時候所需的程序窄驹,庫朝卒,資源,配置等]乐埠,打包在 image 文件里面抗斤。只有通過image,才能生成 Docker 容器丈咐。image 文件可以看作是容器的模板瑞眼。Docker 根據(jù) image 文件生成容器的實例。同一個 image 文件棵逊,可以生成多個同時運行的容器實例伤疙。
Container(容器):容器 = 鏡像 (dockerfile每個命令生成一層,但是都是只讀層) + 讀寫層(可讀可寫的最后一層包含容器),容器可以被創(chuàng)建徒像、啟動黍特、停止、刪除锯蛀、暫停等灭衷。
4.Docker的使用教程
(1)安裝Docker
菜鳥教程中有各個平臺安裝Docker的方法,本文將在windows上進行安裝操作
windows docker安裝【win10上安裝需要查看電腦屬性旁涤,需要符合64位的win10專業(yè)版翔曲,企業(yè)版,或者教育版構(gòu)建在15063或者更高版本】
安裝之后報錯:Docker. ApiServices. WSL2. WslKernelUpdateNotIns talledException的異常
檢查windows版本之后安裝wsl劈愚,重啟電腦之后報錯消失
cmd里面運行docker version
或者docker info
查看是否安裝成功
通常使用cli命令行來操作Docker,就像git一樣
// 打印docker版本
docker version
(2)運行Docker測試
創(chuàng)建文件夾 hello-docker,創(chuàng)建index.html文件瞳遍,隨便寫點兒什么
再創(chuàng)建Dockerfile文件,復(fù)制以內(nèi)容:
# 基于哪個鏡像
FROM nginx
# 將宿主機中的./index.html文件復(fù)制進容器里的/html/index.html
COPY ./index.html html/index.html
# 容器對外暴露80端口
EXPOSE 80
然后打包鏡像:
cd hello-docker/ // 進入剛剛的目錄 以管理員身份打開PowerShell
docker image build ./ -t hello-docker:1.0.0 // 打包鏡像 基于路徑./(當(dāng)前路徑)打包一個鏡像造虎,鏡像的名字是hello-docker傅蹂,版本號是1.0.0。該命令會自動尋找Dockerfile來打包出一個鏡像
然后查看本機已有鏡像【基礎(chǔ)命令可以在cmd里面執(zhí)行算凿,也可以直接打開安裝好的docker desktop 直接查看鏡像容器等情況】:
docker images
docker images ls
刪除本機已有的鏡像:
docker rmi [imageId] // 可刪除
運行容器:
docker container create -p 5000:80 hello-docker:1.0.0 // 根據(jù)鏡像創(chuàng)建一個容器并返回容器id 端口是本機暴露5000端口
docker container start xxx // xxx 為上一條命令運行得到的結(jié)果 ## 啟動一個創(chuàng)建好的容器
查看容器:
docker container ls//查看正在運行的容器
docker ps //查看正在運行的容器
docker ps -a // 查看所有的容器份蝴,包括停止運行的容器
最后訪問http://localhost:5000/就可以查看到index.html里面的內(nèi)容
更多創(chuàng)建容器的命令請查看官方文檔https://docs.docker.com/engine/reference/commandline/create/
(3)下拉官方鏡像運行
讓我們繼續(xù)進行Docker的使用
我們可以直接使用Docker 的官方倉庫里面的東西,比如一個hello world 案例氓轰,直接在某個文件夾中進行下面的操作
docker image pull library/hello-world // 將 image 文件從倉庫抓取到本地婚夫。
docker image ls // 看到所有的image文件
docker container run hello-world // 運行image生成的運行的容器實例
docker container kill [containID] //終止容器 有的是可以自動終止的
docker container rm [containerID] // 刪除容器
docker container ls --all //列出本機所有容器,包括終止運行的容器
學(xué)習(xí)如上操作之后署鸡,Docker的基本操作都上手了一遍案糙,從上面的簡單例子中知道要image文件之后,需要生成image文件就需要Dockerfile 文件靴庆,是一個包含用于組合映像的命令的文本文檔时捌,用來配置image的。
下面進行Dockerfile文件內(nèi)容的編寫和學(xué)習(xí)炉抒,學(xué)完之后就可以進行自己項目的鏡像奢讨,提供給其他人使用了。
(4)Dockerfile文件學(xué)習(xí)
Docker 根據(jù) 該文件生成二進制的 image 文件焰薄。
- 基本結(jié)構(gòu)
基礎(chǔ)鏡像信息拿诸、維護者信息、鏡像操作指令和容器啟動時執(zhí)行指令塞茅,’#’ 為 Dockerfile 中的注釋
- 常用文件說明
FROM:指定基礎(chǔ)鏡像亩码,必須是第一個命令
// FROM <image>:<tag>
// FROM <image>@<digest>
// FROM <image>
FROM mysql:5.6
// tag或digest是可選的,不使用這兩個值時野瘦,會使用latest版本的基礎(chǔ)鏡像
MAINTAINER:指定作者
MAINTAINER <name>
// MAINTAINER sorex@163.com
RUN:構(gòu)建鏡像時執(zhí)行的命令
// RUN 《command》
ADD:將本地文件添加到容器中
// ADD 《src》 《destination》
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
COPY:復(fù)制命令 類似ADD
CMD:提供了容器默認(rèn)的執(zhí)行命令,構(gòu)建容器后調(diào)用描沟,也就是在容器啟動時才進行調(diào)用。多個CMD就只會執(zhí)行最后一個,
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
// CMD ["executable","param1","param2"] (執(zhí)行可執(zhí)行文件吏廉,優(yōu)先)
// CMD ["param1","param2"] (設(shè)置了ENTRYPOINT蠢络,則直接調(diào)用ENTRYPOINT添加參數(shù))
// CMD command param1 param2 (執(zhí)行shell內(nèi)部命令)
EXPOSE:指定容器在運行時監(jiān)聽的端口
EXPOSE <port>;
// EXPOSE 80;
ENV:設(shè)置環(huán)境變量。它們使用鍵值對迟蜜,增加運行程序的靈活性
// ENV <key> <value>
ENV LOG_LEVEL=debug
ENV NODE_ENV=production
USER:鏡像正在運行時設(shè)置一個UID
USER <uid>
WORKDIR:相當(dāng)于cd 進入文件夾
// WORKDIR path
WORKDIR /usr/local/hello
(5)本地項目操作封裝成docker
本地項目使用主要技術(shù)如下
1.Vue3.0+ts+element-plus構(gòu)建前端頁面
2.koa+koa-router+ts構(gòu)建后臺服務(wù)
新建忽略文件.dockerignore
.git
node_modules
npm-debug.log
由于docker是只能啟動一個服務(wù)刹孔,所以把前后端合在一起,然后打包前端項目
如果是單獨的前端項目娜睛,則只需要直接進行打包之后新建一個文本文件 Dockerfile髓霞,按照上面的Dockerfile進行學(xué)習(xí)之后編寫即可
項目Dockerfile如下
# Build environment 指定基礎(chǔ)鏡像
FROM node:alpine
# Copy packages 復(fù)制本地的代碼
COPY . .
# run Monorepo 安裝依賴
RUN yarn install
# run project 進入運行目錄
WORKDIR packages/back
# 導(dǎo)出端口
EXPOSE 3000
# 運行命令
CMD ["node","dist/index.js"]
運行啟動
docker image build ./ -t filedemo:1.0.0
docker container create -p 5000:3000 filedemo:1.0.0 //-p參數(shù):容器的 3000 端口映射到本機的 5000 端口,訪問時啟動5000端口
docker container start 容器id號
直接訪問ip:5000端口即可,現(xiàn)在在本機可以進行項目的自由訪問了畦戒,但是如果別人需要使用方库,就需要上傳倉庫。
5.Harbor鏡像上傳和下載操作
雖然docker官方提供了公共的鏡像倉庫障斋,但是出于安全和效率方面的考慮纵潦,將鏡像上傳私有倉庫也是非常好的選擇,比如Harbor
下面將項目上傳私有倉庫
(1)Harbor鏡像上傳
賬號登錄
// docker login ip地址
docker login 192.168.0.7
// 然后輸入賬號密碼即可
// or
// docker login -u 賬號名 -p 密碼 倉庫地址端口
docker login -u xxx -p xxx 192.168.0.7
// WARNING! Using --password via the CLI is insecure. Use --password-stdin.
// Error response from daemon: Get "https://192.168.0.7/v2/": dial tcp 192.168.0.7:443: connect: connection refused
// 如果登錄失敗垃环,則是原因是因為倉庫沒有配置https 的問題
// 去修改docker里面的daemon.json
"insecure-registries": [
"192.168.0.7"http:// 加上遠程的倉庫地址
],
// 然后重啟docker
給項目打tag
//查看image
docker images
// docker tag 本地鏡像名字:標(biāo)簽名字 倉庫tag名字
docker tag filedemo:1.0.1 192.168.0.7/node/fileupload:v1.0.1
上傳倉庫
docker push 192.168.0.7/node/fileupload:v1.0.1
(2)Harbor鏡像下載操作
依舊登錄進去
然后拉取鏡像,和代碼倉庫命令類似
docker pull 192.168.0.7/node/fileupload:v1.0.1
拉取后docker images查看是否拉取到本地
直接創(chuàng)建容器并運行
docker container create -p 3002:3000 192.168.0.7/node/fileupload:v1.0.1 # 根據(jù)鏡像創(chuàng)建一個容器并返回容器id
docker container start 前一步返回的ID # 運行容器
訪問localhost:3002即可
(3)portainer基礎(chǔ)使用教程
portainer是docker的圖形化管理界面邀层,可以把倉庫里面的docker放在上面進行管理,就不需要使用命令進行啟動這些操作遂庄,圖形化界面操作會更簡單容易寥院。
拉取私有倉庫的images
創(chuàng)建容器,選擇側(cè)邊的containers->add container
如上所示涛目,就建好了容器管理了私有倉庫的鏡像秸谢,然后就可以根據(jù)根據(jù)自己設(shè)置的端口進行訪問,別人也可以直接訪問霹肝,可以形成和虛擬機一樣的效果估蹄,但是操作更簡單方便。
(4)Docker容器的重啟策略
Docker容器的重啟策略是面向生產(chǎn)環(huán)境的啟動策略沫换,開發(fā)過程中可以忽略臭蚁。
never,默認(rèn)策略苗沧,在容器退出時不重啟容器 on-failure刊棕,在容器非正常退出時(退出狀態(tài)非0)炭晒,才會重啟容器 on-failure:3待逞,在容器非正常退出時重啟容器,最多重啟3次 always网严,在容器退出時總是重啟容器 unless-stopped识樱,在容器退出時總是重啟容器,但是不考慮在Docker守護進程啟動時就已經(jīng)停止了的容器
6.Docker鏡像的優(yōu)化
由于構(gòu)建鏡像之后,發(fā)現(xiàn)鏡像比較大怜庸,可能有幾百MB或者有的上TB当犯,那其實應(yīng)該進行一個優(yōu)化的,讓這些鏡像盡量占用少的空間割疾,因為本來容器設(shè)計初衷就是為了快速和小巧獨立嚎卫,利于一次構(gòu)建,多處運行
(1)命令合在一起使用&&等操作符,減少層
docker鏡像是分層構(gòu)建的宏榕,Dockerfile每條指令都會新建一層作為只讀層拓诸,如果你新建容器,就會在最頂部添加讀寫層麻昼,每新增一層都會增加鏡像的尺寸奠支,所以可以減少命令的條數(shù),把運行命令合在一起
RUN cd /home/app && npm install --production
(2)使用小的基礎(chǔ)鏡像
可以使用Alpine作為基礎(chǔ)鏡像,一般基礎(chǔ)鏡像有Ubuntu抚芦、CentOs倍谜、Debian、Alpine,下面是一般的基礎(chǔ)鏡像的大小
REPOSITORY TAG IMAGE ID SIZE
centos 7 49f7960eb7e4 200MB
debian latest 0af60a5c6dd0 101MB
ubuntu 18.04 47b19964fb50 88.1MB
ubuntu latest 47b19964fb50 88.1MB
alpine 3.8 3f53bb00af94 4.41MB
一看alpine就小得多叉抡,可以減少大部分的體積
(3)依賴的話需要打包的只需要安裝到生產(chǎn)環(huán)境里面
需要的運行時的依賴尔崔,放到生產(chǎn)環(huán)境中,開發(fā)時候的依賴褥民,放到開發(fā)環(huán)境中您旁,不必要放到生產(chǎn)環(huán)境中
(4)善用.dockerignore文件
.dockerignore文件,是用來聲明不會被鏡像包括的文件和目錄轴捎。這有助于避免將不必要的大文件或敏感文件打包進去鹤盒,并避免將它們添加到公共鏡像。
7.參考資料
3.Linux容器