摘要:使用推出的語(yǔ)言開(kāi)發(fā)實(shí)現(xiàn),基于內(nèi)核的,,以及等技術(shù)。初步了解容器與虛擬機(jī)的區(qū)別原理不同上圖是關(guān)于和傳統(tǒng)虛擬機(jī)區(qū)別的截圖。從而實(shí)現(xiàn)模擬更改鏡像的作用。下面的實(shí)踐以為例,。指令讓外界能通過(guò)容器的端口進(jìn)行網(wǎng)絡(luò)通信。使用可以啟動(dòng)關(guān)閉容器。
Docker 是一個(gè)能讓程序跑在一個(gè)它無(wú)法感知的、用于隔絕外界環(huán)境里的容器的工具。Docker 簡(jiǎn)介
最初是 dotCloud 公司創(chuàng)始人 Solomon Hykes 發(fā)起的一個(gè)公司內(nèi)部項(xiàng)目,并于 2013 年 3 月以 Apache 2.0 授權(quán)協(xié)議開(kāi)源,代碼主要在 GitHub 上進(jìn)行維護(hù)。Docker 項(xiàng)目后來(lái)還加入了 Linux 基金會(huì),并成立推動(dòng) 開(kāi)放容器聯(lián)盟(OCI)。
Docker 使用 Google 推出的 Go 語(yǔ)言開(kāi)發(fā)實(shí)現(xiàn),基于 Linux 內(nèi)核的 cgroup,namespace,以及 UnionFS 等技術(shù)。最初實(shí)現(xiàn)基于 LXC,從 0.7 版本后去除 LXC,轉(zhuǎn)而開(kāi)始使用自行開(kāi)發(fā)的 libcontainer,從 1.11 開(kāi)始,則進(jìn)一步演進(jìn)為使用 runC 和 containerd。
在 2017 年 4 月 21 日 Pull Request #32691 將原有的 Docker 項(xiàng)目更名為 Moby,由 Moby 構(gòu)建出 Docker CE(社區(qū)版),而新的 Docker 項(xiàng)目則構(gòu)建出 Docker EE(企業(yè)版本)。
Docker 初步了解 Docker 容器與虛擬機(jī)的區(qū)別 原理不同
上圖是 Docker Doc 關(guān)于 Docker 和傳統(tǒng)虛擬機(jī)區(qū)別的截圖。
Docker 利用了 Linux 內(nèi)核的 cgroup 和 namespace 為程序的執(zhí)行創(chuàng)造一個(gè)隔離的環(huán)境,使得程序感知不到外界的存在,其本身仍然是跑在原有的內(nèi)核上的;而虛擬機(jī)則是通過(guò) Hypervisor 模擬了一整套系統(tǒng)環(huán)境,虛擬機(jī)里的程序是跑在虛擬機(jī)內(nèi)核上的。由于虛擬機(jī)需要模擬一整套操作系統(tǒng)環(huán)境,因此開(kāi)銷(xiāo)比 Docker 容器要高很多很多。
你可以把跑在容器里的程序想象成楚門(mén)(楚門(mén)的世界男主),他并不知道自己生活在一個(gè)精心布置的超大影棚里,但是他仍然是活在現(xiàn)實(shí)世界里的,呼吸著現(xiàn)實(shí)世界中的空氣,吃著和我們差不多的食物;跑在虛擬機(jī)里的程序就好像活在動(dòng)畫(huà)片里的小豬佩奇,他的一切都是虛擬的,雖然小豬佩奇并不知道自己活在動(dòng)畫(huà)片里,但是很顯然的是它和我們完全不在一個(gè)世界(不是同一個(gè)系統(tǒng)內(nèi)核)。
性能差異特性 | 容器 | 虛擬機(jī) |
---|---|---|
啟動(dòng) | 秒級(jí) | 分鐘級(jí) |
硬盤(pán)使用 | 一般為 MB | 一般為 GB |
性能 | 接近原生 | 弱于 |
系統(tǒng)支持量 | 單機(jī)上千個(gè)容器 | 一般幾十個(gè) |
鏡像 是一個(gè)包含操作系統(tǒng)完整 root 文件系統(tǒng) 的、只讀的,由多層文件系統(tǒng)聯(lián)合而成的打包文件。
Docker 為了讓?xiě)?yīng)用無(wú)感知的跑在容器中,提供了一套完整的 root 文件系統(tǒng),比如官方鏡像 library/ubuntu 就包含了一整套 root 文件系統(tǒng)。像 apache、nginx 都是基于該鏡像構(gòu)建的,由于 library/ubuntu 本身很大,所以 Docker 采用了分層存儲(chǔ)的方式。
本文假裝你已經(jīng)安裝了 Docker,上圖通過(guò) docker pull nginx 從 官方 Registry(下面會(huì)提到這是啥)拉取 nginx 鏡像,拉取 nginx 相當(dāng)于 library/nginx:latest,library 表示 nginx 是官方鏡像,因此可以省略,:latest 表示拉取標(biāo)簽為 latest 的鏡像。拉取后可以看到存在兩個(gè)鏡像,因?yàn)?nginx 鏡像本身就是基于 library:ubuntu:16.04 鏡像的。
上圖通過(guò) docker pull httpd 拉取了 apache 鏡像,由于 ubuntu:16.04 鏡像已經(jīng)在本地存在了,因此拉取的時(shí)候不會(huì)重復(fù)拉取。從而節(jié)約拉取時(shí)間。這就是 Docker 分層存儲(chǔ)的意義。
鏡像的只讀可以理解成以前的光盤(pán) CD,是不可更改的。為了模擬實(shí)現(xiàn)對(duì)光盤(pán) CD 的寫(xiě)的功能,會(huì)建立兩層文件系統(tǒng),一層是光盤(pán) CD 的只讀文件系統(tǒng);另外一層是存放更改數(shù)據(jù)的可寫(xiě)的文件系統(tǒng)。從而實(shí)現(xiàn)模擬更改鏡像的作用。Docker 也是采用這種類(lèi)似的分層的方式。
如圖,可以看出 ubuntu:15.04 是由很多層文件系統(tǒng)(鏡像)堆疊形成的,最底層是 root 文件系統(tǒng)(d3a1f33e8a5a)。這幾層文件系統(tǒng)都被設(shè)置成只讀的。多層文件系統(tǒng)利用了上面提到的 UnionFS、AUFS、OverlayFS,這是一類(lèi)文件系統(tǒng),這種聯(lián)合掛載文件系統(tǒng)最早就是用于解決 CD 這種只讀文件系統(tǒng)的修改問(wèn)題,Docker 之前使用 AUFS,但是由于 AUFS 不被 linus 喜歡(被 linus 評(píng)價(jià)為稠密、不可讀,無(wú)注釋?zhuān)?dǎo)致 AUFS 一直沒(méi)有被合并到 Linux 的主分支中。Docker 在 1.12 以后已經(jīng)將默認(rèn)的文件系統(tǒng)從 AUFS 替換成 OverlayFS2。因?yàn)?OverlayFS2 已經(jīng)被合并進(jìn)了 Linux 的主干分支中。
上面我們拉取了 nginx 鏡像到本地,我們可以使用 docker container start nginx(省略了 latest 標(biāo)簽)來(lái)運(yùn)行這個(gè)鏡像。運(yùn)行之前會(huì)先創(chuàng)建一個(gè)容器(其實(shí)本質(zhì)就是創(chuàng)建了一層可讀寫(xiě)的文件系統(tǒng),以提供程序運(yùn)行時(shí)的讀寫(xiě)支持),然后就會(huì)啟動(dòng)程序,讓程序跑在一個(gè)隔離環(huán)境(不是虛擬環(huán)境)里。你還可以通過(guò) docker container commit>來(lái)對(duì)當(dāng)前層進(jìn)行提交(就好像 Git 提交一樣),從而形成一個(gè)新的鏡像,但是這種方式是不推薦的;這是因?yàn)樵诔绦蜻\(yùn)行過(guò)程中可能會(huì)產(chǎn)生一些垃圾文件,而如果這些垃圾文件被提交后,新的鏡像又是不可修改的,只會(huì)增大鏡像的體積。具體怎么創(chuàng)建鏡像會(huì)在下面說(shuō)到。
可以看到上圖中在創(chuàng)建容器的時(shí)候其實(shí)就是創(chuàng)建了一個(gè)容器可讀寫(xiě)層。你還可以通過(guò) docker container stop
鏡像構(gòu)建完成后,可以很容易的在宿主機(jī)器上運(yùn)行,但是如果其他機(jī)器要使用這個(gè)鏡像,我們就需要一個(gè)集中存儲(chǔ)、分發(fā)鏡像的服務(wù),Docker Registry 就是這樣的服務(wù)。一個(gè) Docker Registry 可以包含多個(gè)倉(cāng)庫(kù),每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽,每個(gè)標(biāo)簽對(duì)應(yīng)一個(gè)鏡像。
就拿上面的 library/nginx:latest 舉例,library 表示這個(gè)鏡像是官方鏡像,如果不是官方鏡像,這里一般填注冊(cè)在 Docker Registry 的用戶(hù)名;library/nginx 是倉(cāng)庫(kù)的名字,latest 是該倉(cāng)庫(kù)一個(gè)標(biāo)簽。
誠(chéng)然,官方的 Docker Registry 是世界上最大的鏡像分發(fā)服務(wù),官方還提供了 Docker Registry 鏡像 用于搭建私有鏡像分發(fā)服務(wù)。而且 DockerHub 和社區(qū)一起制作了大量的、高質(zhì)量的鏡像,使得我們構(gòu)建鏡像更為方便。
Docker 簡(jiǎn)單實(shí)踐 Docker 單個(gè)鏡像前面提到可以通過(guò) docker commit 生成新的鏡像,但是這種方式并不推薦(原因已經(jīng)說(shuō)明),所以我們一般還是采用 Dockerfile 的方式。下面的實(shí)踐以 github-issue-rss 為例,demonstate how to containerization a normal project。
首先創(chuàng)建一個(gè) Dockerfile 文件,內(nèi)容如下:
FROM node:9-alpine MAINTAINER mrcode "[email protected]" WORKDIR /src # 表示容器內(nèi)的程序運(yùn)行時(shí)的當(dāng)前目錄 COPY . /src # 把構(gòu)建 Dockerfile 文件目錄下的文件全部復(fù)制到鏡像的 /src 目錄下 RUN npm install -g yarn && yarn install # 構(gòu)建時(shí)執(zhí)行 EXPOSE 3000 # 暴露容器的 3000 端口到外面 ENTRYPOINT ["npm", "start"] # 執(zhí)行 docker start時(shí)就會(huì)執(zhí)行 npm start
Dockerfile 里的每一行開(kāi)頭的大寫(xiě)字母單詞叫做 Dockerfile 指令。每執(zhí)行一條指令就會(huì)增加一層鏡像(本質(zhì)是執(zhí)行了一次 docker commit,而 AUFS 最大的層數(shù)是 127 層,因此 Dockerfile 里的層數(shù)最好不要太多!
FROM 表示基于哪一個(gè)鏡像構(gòu)建,node:9-alpine 表示基于官方的 node 鏡像構(gòu)建,標(biāo)簽 9-alpine 表示這是一個(gè) node 9 的鏡像,同時(shí)該 node9 鏡像是基于 alpine 鏡像構(gòu)建的,alpine 是 Linux 的一個(gè)精簡(jiǎn)發(fā)行版,大小只有 5MB 左右,而 Ubuntu 鏡像大小接近 200MB。
RUN 指令會(huì)在構(gòu)建鏡像時(shí)執(zhí)行,使用 && 符號(hào)是為了減少 RUN 命令的使用次數(shù),減少最終鏡像的層數(shù)。
EXPOSE 指令讓外界能通過(guò)容器的 3000 端口進(jìn)行網(wǎng)絡(luò)通信。
ENTRYPOINT 表示執(zhí)行 docker start
圖中執(zhí)行命令最后有一個(gè) ".",這是將當(dāng)前目錄作為上下文傳遞給 Docker daemon;Docker 的工作方式是基于 C-S 架構(gòu)的,你需要將構(gòu)建的所在目錄傳給 docker daemon,這也是上面的 Dockerfile 文件的 COPY 指令的當(dāng)前目錄。
接下來(lái)創(chuàng)建容器,一個(gè)鏡像可以創(chuàng)建多個(gè)容器(其實(shí)就是創(chuàng)建多個(gè)在同一層的讀寫(xiě)層)。
docker run 會(huì)拉取遠(yuǎn)程的鏡像(如果本地沒(méi)有的話),接著它會(huì)創(chuàng)建一個(gè)容器,基于 mrcode/github-issue-rss:test 鏡像(只有 latest 標(biāo)簽可以省略);-v 會(huì)創(chuàng)建一個(gè)數(shù)據(jù)卷(volume),表示當(dāng)容器對(duì) /var/log/github-issue-rss/ 寫(xiě)入數(shù)據(jù)時(shí)相當(dāng)于寫(xiě)在了宿主機(jī)的 ~/github-issue-rss/log 目錄上,從而維持容器的無(wú)狀態(tài)特性(無(wú)狀態(tài)特性是指容器在運(yùn)行時(shí)盡量不要將重要數(shù)據(jù)存儲(chǔ)在容器所在的讀寫(xiě)層里,雖然那是一層讀寫(xiě)層,但是是用來(lái)存放程序運(yùn)行時(shí)產(chǎn)生的臨時(shí)文件的,不應(yīng)將重要數(shù)據(jù)放在里面);-d 表示 daemon 執(zhí)行程序,否則的話容器進(jìn)程會(huì)掛載在當(dāng)前 shell 上,一般通過(guò) -d 掛載到 docker daemon 進(jìn)程上;—rm 表示容器退出后自動(dòng)刪除容器,這是推薦的用法,也是容器的無(wú)狀態(tài)特性的體現(xiàn)。
容器進(jìn)程具有和容器內(nèi)程序本身進(jìn)程相同的生命周期,容器進(jìn)程用來(lái)啟動(dòng)容器內(nèi)程序,相當(dāng)于 Linux 內(nèi)的 init 進(jìn)程;當(dāng)容器內(nèi)程序被 docker stop殺掉時(shí),容器就會(huì)退出,留下一個(gè)已創(chuàng)建的讀寫(xiě)層文件系統(tǒng),這也是容器存在的標(biāo)志。
由于創(chuàng)建容器僅僅是創(chuàng)建了一個(gè)可讀寫(xiě)的文件系統(tǒng),所以容器的存在是非常非常輕量級(jí)的。即便對(duì)一個(gè)鏡像創(chuàng)建多個(gè)容器,鏡像本身是不會(huì)被重新拷貝的,而是最大程度的復(fù)用,這是因?yàn)殓R像內(nèi)的多層文件系統(tǒng)的每一層都被設(shè)置成只讀的。
你可以通過(guò) docker container ls 查看當(dāng)前正在運(yùn)行的所有容器,如果還想查看已退出的容器,加上一個(gè) -a 參數(shù)。使用 docker container start/stop 可以啟動(dòng)/關(guān)閉容器。
最后可以通過(guò) docker push mrcode/github-issue-rss:test 發(fā)布到 DockerHub 上,分享到社區(qū)。
Docker 多個(gè)鏡像github-issue-rssis a tool converts the issues on GitHub to RSS.
這個(gè)工具需要用到了 mysql,為了以后方便數(shù)據(jù)遷移,我決定使用 mysql 鏡像,mysql 鏡像可以把所有狀態(tài)存放在宿主機(jī)的一個(gè)文件夾下。那我現(xiàn)在不僅需要啟動(dòng) mysql 和 github-issue-rss 鏡像,還需要建立他們之間的網(wǎng)絡(luò)連接關(guān)系,事情變得麻煩了。有一個(gè)工具叫 docker-compose (本文假裝你已經(jīng)安裝了這個(gè)工具)可以把這一切自動(dòng)化。下面是項(xiàng)目根目錄的一個(gè) docker-compose.yml 文件:
version: "3" services: db: image: mysql:5.7 volumes: - ~/.github-issue-rss/mysql:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: rootroot MYSQL_DATABASE: rss MYSQL_USER: mrcode MYSQL_PASSWORD: github-issue-rss github-issue-rss: image: mrcode/github-issue-rss:v0.1.0 depends_on: - db ports: - "3000:3000" restart: always environment: MYSQL_PORT: 3306 MYSQL_HOST: db MYSQL_SCHEMA: rss MYSQL_USERNAME: mrcode MYSQL_PASSWORD: github-issue-rss LOG_FILE: /var/log/github-issue-rss/ volumes: - ~/.github-issue-rss/log/:/var/log/github-issue-rss/
在 docker-compose 的世界里沒(méi)有容器,只有服務(wù)。它認(rèn)為它啟動(dòng)了兩服務(wù) db 和 github-issue-rss。沒(méi)有哪個(gè)是主服務(wù),所有服務(wù)都是平等的。
在 db service 中,設(shè)置了 volumes,將 mysql 的數(shù)據(jù)存儲(chǔ)在 ~/.github-issue-rss/mysql/ 里,還可以設(shè)置更多的 volume。restart 表示只要服務(wù)執(zhí)行失敗就重啟,防止依賴(lài)的 service 還沒(méi)有啟動(dòng)完成時(shí)導(dǎo)致的錯(cuò)誤引發(fā)連鎖反應(yīng)。給兩個(gè) service 配置的 environment 來(lái)建立兩者的數(shù)據(jù)連接,github-issue-rss 代碼會(huì)讀取這個(gè)環(huán)境變量,然后連接到 db 服務(wù),可以看到 github-issue-rss 里的環(huán)境變量 MYSQL_HOST 設(shè)置為 db,這是因?yàn)?docker-compose 會(huì)在啟動(dòng)的服務(wù)配置里建立這個(gè) DNS 映射關(guān)系。
還可以通過(guò) docker-compose down 來(lái)停止并且刪除服務(wù)對(duì)應(yīng)的容器。
現(xiàn)在你只需要克隆倉(cāng)庫(kù)到本地,然后執(zhí)行 docker-compose up 就可以啟動(dòng) github-issue-rss 了,因?yàn)?github-issue-rss 鏡像本身已經(jīng)構(gòu)建并發(fā)布到 Docker Hub 了。
Docker 的應(yīng)用 持續(xù)集成和持續(xù)交付使用 Docker 可以通過(guò)定制應(yīng)用鏡像來(lái)實(shí)現(xiàn)持續(xù)集成、持續(xù)交付、部署。開(kāi)發(fā)人員通過(guò) Dockerfile 進(jìn)行鏡像構(gòu)建,結(jié)合持續(xù)集成系統(tǒng)進(jìn)行集成測(cè)試,而運(yùn)維人員則可以在生產(chǎn)環(huán)境中快速部署該鏡像。甚至結(jié)合持續(xù)部署進(jìn)行自動(dòng)部署。
而且使用 Dockerfile 使鏡像的構(gòu)建透明化,不僅可以幫助開(kāi)發(fā)人員理解應(yīng)用運(yùn)行環(huán)境,也方便運(yùn)維團(tuán)隊(duì)理解應(yīng)用運(yùn)行所需條件,幫助更好的生產(chǎn)環(huán)境中部署該鏡像。
微服務(wù)Docker 和微服務(wù)架構(gòu)簡(jiǎn)直就是渾然天成,站在 Docker 的角度,軟件本質(zhì)是容器的組合:業(yè)務(wù)邏輯容器、數(shù)據(jù)庫(kù)容器、存儲(chǔ)容器、隊(duì)列容器……Docker 使得軟件拆分成若干的標(biāo)準(zhǔn)化容器,然后像積木一樣的搭建起來(lái)。這正是微服務(wù)的思想:軟件把任務(wù)外包出去,讓各種外部服務(wù)完成這些任務(wù),軟件本身只是底層服務(wù)的調(diào)用中心和組裝層。
參考文章
http://www.ruanyifeng.com/blo... by 阮一峰
https://github.com/yeasy/dock... by Baohua Yang
https://docs.docker.com by Docker Doc
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/8033.html
摘要:編程書(shū)籍的整理和收集最近一直在學(xué)習(xí)深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后也找了很多的書(shū)和文章,隨著不斷的學(xué)習(xí),也整理了下自己的學(xué)習(xí)筆記準(zhǔn)備分享出來(lái)給大家后續(xù)的文章和總結(jié)會(huì)繼續(xù)分享,先分享一部分的 編程書(shū)籍的整理和收集 最近一直在學(xué)習(xí)deep learning深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后...
摘要:感謝參考本文內(nèi)容還是相對(duì)很淺的,中關(guān)于分布式,集群的內(nèi)容沒(méi)有涉及,所以本文推薦前端同學(xué)看一看,后端同學(xué)就不推薦了。本文中所有命令都是針對(duì),拷貝粘貼時(shí)請(qǐng)注意。這一篇文章有些復(fù)讀機(jī) showImg(https://segmentfault.com/img/remote/1460000019424971); 感謝 & 參考 本文內(nèi)容還是相對(duì)很淺的,Docker中關(guān)于分布式,集群的內(nèi)容沒(méi)有涉及...
摘要:感謝參考本文內(nèi)容還是相對(duì)很淺的,中關(guān)于分布式,集群的內(nèi)容沒(méi)有涉及,所以本文推薦前端同學(xué)看一看,后端同學(xué)就不推薦了。本文中所有命令都是針對(duì),拷貝粘貼時(shí)請(qǐng)注意。這一篇文章有些復(fù)讀機(jī)showImg(https://user-gold-cdn.xitu.io/2019/5/22/16adf8cacec9db2d); 感謝 & 參考 本文內(nèi)容還是相對(duì)很淺的,Docker中關(guān)于分布式,集群的內(nèi)容沒(méi)有涉及...
閱讀 1118·2021-11-23 09:51
閱讀 1081·2021-10-18 13:31
閱讀 2991·2021-09-22 16:06
閱讀 4284·2021-09-10 11:19
閱讀 2206·2019-08-29 17:04
閱讀 437·2019-08-29 10:55
閱讀 2485·2019-08-26 16:37
閱讀 3381·2019-08-26 13:29