這篇文章主要介紹“怎么創(chuàng)建用于安裝應(yīng)用的Dockerfile”,在日常操作中,相信很多人在怎么創(chuàng)建用于安裝應(yīng)用的Dockerfile問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么創(chuàng)建用于安裝應(yīng)用的Dockerfile”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
創(chuàng)新互聯(lián)致力于互聯(lián)網(wǎng)品牌建設(shè)與網(wǎng)絡(luò)營(yíng)銷(xiāo),包括成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、SEO優(yōu)化、網(wǎng)絡(luò)推廣、整站優(yōu)化營(yíng)銷(xiāo)策劃推廣、電子商務(wù)、移動(dòng)互聯(lián)網(wǎng)營(yíng)銷(xiāo)等。創(chuàng)新互聯(lián)為不同類(lèi)型的客戶提供良好的互聯(lián)網(wǎng)應(yīng)用定制及解決方案,創(chuàng)新互聯(lián)核心團(tuán)隊(duì)十年專(zhuān)注互聯(lián)網(wǎng)開(kāi)發(fā),積累了豐富的網(wǎng)站經(jīng)驗(yàn),為廣大企業(yè)客戶提供一站式企業(yè)網(wǎng)站建設(shè)服務(wù),在網(wǎng)站建設(shè)行業(yè)內(nèi)樹(shù)立了良好口碑。概念
什么是“傳統(tǒng)”應(yīng)用?
并沒(méi)有一個(gè)特定的定義能夠描述所有的傳統(tǒng)應(yīng)用,但它們有一些共同的特性:
使用本地文件系統(tǒng)來(lái)持久化存儲(chǔ),數(shù)據(jù)文件和應(yīng)用的文件混合在一起。
在同一個(gè)服務(wù)器上運(yùn)行很多服務(wù),比如 MySQL 數(shù)據(jù)庫(kù),Redis 服務(wù)器,nginx web 服務(wù)器,一個(gè) Ruby on Rails 應(yīng)用,以及一大堆定時(shí)任務(wù)
使用大雜燴式的腳本和手工流程進(jìn)行安裝和升級(jí)(文檔也很簡(jiǎn)陋)。
配置是存儲(chǔ)在文件里的,通常散落在多個(gè)位置,并與應(yīng)用的文件混在一起。
進(jìn)程間的通信是借助本地文件系統(tǒng)進(jìn)行的(比如在磁盤(pán)上放一個(gè)文件,另一個(gè)進(jìn)程來(lái)讀取),而不是TCP/IP。
按照單個(gè)服務(wù)器上只運(yùn)行一個(gè)應(yīng)用的示例的方式來(lái)設(shè)計(jì)的。
傳統(tǒng)應(yīng)用的缺點(diǎn)
自動(dòng)化部署很困難。
如果需要運(yùn)行應(yīng)用的多個(gè)不同的實(shí)例,很難讓多個(gè)實(shí)例在同一個(gè)服務(wù)器上“共存”。
如果服務(wù)器停機(jī),由于需要手工流程所以需要較長(zhǎng)的時(shí)間來(lái)恢復(fù)。
部署新版本的過(guò)程基本是手動(dòng)的,或者大部分是手動(dòng)的,難以回滾。
很有可能測(cè)試環(huán)境與生產(chǎn)環(huán)境有較大差異,導(dǎo)致一些生產(chǎn)環(huán)境問(wèn)題不能在測(cè)試期間發(fā)現(xiàn)。
很難通過(guò)增加新的實(shí)例來(lái)進(jìn)行橫向擴(kuò)展。
什么是容器化?
將應(yīng)用“容器化”的過(guò)程,就是讓?xiě)?yīng)用能夠運(yùn)行在 Docker 容器或類(lèi)似技術(shù)中,它們能將操作系統(tǒng)環(huán)境和應(yīng)用封裝在一起(完整的系統(tǒng)鏡像)。由于容器能給應(yīng)用提供近似于完整系統(tǒng)的環(huán)境,這就為在不修改,或者少量修改應(yīng)用的情況下,對(duì)應(yīng)用的部署進(jìn)行現(xiàn)代化改造提供了一種思路。這也是應(yīng)用的架構(gòu)持續(xù)能保持“云友好”的基礎(chǔ)。
容器化的好處
部署容易多了:使用新的容器鏡像直接替換整個(gè)老版本。
自動(dòng)化部署也相對(duì)容易,甚至可以完全由 CI(Continuous Integration, 持續(xù)集成)來(lái)驅(qū)動(dòng)。
部署失敗時(shí)的回滾只要切換到之前的鏡像。
應(yīng)用升級(jí)非常容易,因?yàn)楝F(xiàn)在沒(méi)有可能出錯(cuò)的“中間步驟”了(不管它是否影響整個(gè)部署過(guò)程的成功)。
相同的容器鏡像可以在不同的環(huán)境中充分測(cè)試,再直接部署到生產(chǎn)環(huán)境。這可以確保測(cè)試態(tài)與生產(chǎn)態(tài)的產(chǎn)品是完全一致的。
系統(tǒng)更容易從宕機(jī)中恢復(fù),因?yàn)榭梢匝杆僭谛掠布Y源上啟動(dòng)裝有這個(gè)應(yīng)用的新容器,并附加到同一數(shù)據(jù)源上。
開(kāi)發(fā)人員能在本地以容器的形式,在更逼真的環(huán)境里測(cè)試新功能。
硬件資源的利用更高效,在單一主機(jī)上現(xiàn)在可以運(yùn)行多個(gè)容器應(yīng)用,而以前不能。
容器化是支持零停機(jī)升級(jí)、金絲雀部署、高可用和橫向擴(kuò)展的堅(jiān)實(shí)基礎(chǔ)。
容器化之外的選擇
用 Puppet 和 Chef 之類(lèi)的配置管理工具,能解決一部分的“傳統(tǒng)”問(wèn)題,比如環(huán)境一致性等。但它們不能支持“原子”部署,以及對(duì)應(yīng)用+環(huán)境的完整回滾。而一種無(wú)法方便回滾的部署方案,仍然會(huì)在部署中途充滿風(fēng)險(xiǎn)。
虛擬機(jī)鏡像是能實(shí)現(xiàn)部分上述能力的另一種方法,而且在有些情形中,相對(duì)于容器,使用完整的虛機(jī)進(jìn)行“原子地”部署會(huì)更合適。但使用虛機(jī)的主要問(wèn)題是,它對(duì)硬件的利用率更低效。因?yàn)樘摍C(jī)需要一些獨(dú)占的資源(CPU、內(nèi)存和磁盤(pán)等),而容器之間可以共享主機(jī)的資源。
如何容器化
一、準(zhǔn)備工作
列出存儲(chǔ)數(shù)據(jù)的文件系統(tǒng)位置
由于部署新版本應(yīng)用是通過(guò)替換 Docker 鏡像實(shí)現(xiàn)的,所以任何持久化的數(shù)據(jù)都應(yīng)該存儲(chǔ)在容器之外。如果運(yùn)氣不錯(cuò)的話,可能遇到應(yīng)用已經(jīng)將所有數(shù)據(jù)都寫(xiě)入了特定位置,不過(guò)多數(shù)傳統(tǒng)應(yīng)用常將它們的數(shù)據(jù)往磁盤(pán)上到處亂寫(xiě),還有可能與應(yīng)用本身的文件混在一起。Docker 的可加載存儲(chǔ)卷(volume)讓主機(jī)的文件系統(tǒng)能暴露給容器用作特定路徑,這樣數(shù)據(jù)可以在容器之間留存。所以,我們無(wú)論是哪種情況,我們都需要列出用于存儲(chǔ)數(shù)據(jù)的位置。
現(xiàn)在你可以考慮考慮讓?xiě)?yīng)用里所有輸出的數(shù)據(jù)寫(xiě)入到文件系統(tǒng)的同一目錄去了,這樣能明顯簡(jiǎn)化容器化版本的部署工作。不過(guò),如果修改應(yīng)用難以達(dá)成,這也并不是必須的。
找出會(huì)隨部署環(huán)境變化的配置數(shù)據(jù)
為了確保一致性,同一個(gè)鏡像要在多套環(huán)境中使用(比如,測(cè)試和生產(chǎn)),因此必須要列出所有在不同環(huán)境中會(huì)變化的配置值,在啟動(dòng)容器的時(shí)刻再設(shè)置值。容器中的程序到時(shí)候可以從環(huán)境變量,或者從配置文件中獲取這些配置的值。
你可以現(xiàn)在就考慮修改應(yīng)用并支持從環(huán)境變量中讀取配置,以便簡(jiǎn)化容器化的過(guò)程。同樣的,如果不好修改應(yīng)用,這也是不一定是必要的。
找出容易移出去的服務(wù)
在同一機(jī)器上,我們的應(yīng)用可能要依賴(lài)一些其他服務(wù),它們?nèi)绻?dú)立性比較高、使用 TCP/IP 通信,就很容易能移出去。舉例來(lái)說(shuō),如果在同一機(jī)器上運(yùn)行 MySQL 或 PostgreSQL 數(shù)據(jù)庫(kù),或者類(lèi)似 Redis 的緩存,那就容易移出去了。可能同時(shí)還需要調(diào)整配置,才能支持指定機(jī)器名(hostname)和端口(port)而不是直接認(rèn)為應(yīng)用運(yùn)行在 localhost。
二、創(chuàng)建容器鏡像
創(chuàng)建用于安裝應(yīng)用的 Dockerfile
如果已經(jīng)有基于腳本或者 Chef、Puppet 之類(lèi)的配置管理工具的自動(dòng)化安裝能力,那這個(gè)過(guò)程就很簡(jiǎn)單了。挑選一個(gè)喜歡的系統(tǒng)鏡像、安裝所有依賴(lài),然后運(yùn)行自動(dòng)化腳本就行了。
如果目前的安裝過(guò)程是手動(dòng)的,就需要寫(xiě)一些腳本了。不過(guò),由于鏡像的狀態(tài)是已知的,在這兒編寫(xiě)腳本要比基于可能存在不一致性的原生系統(tǒng)來(lái)的容易。
如果提前找出了要移出去的服務(wù),那么在腳本里就不應(yīng)該安裝它們了。
下面是一個(gè)簡(jiǎn)單的示例 Dockerfile:
# 基于官方 Ubuntu 16.04 Docker 鏡像 FROM ubuntu:16.04 # 安裝所依賴(lài)的 Ubuntu 軟件包 RUN apt-get install -y <REQUIRED UBUNTU PACKAGES> \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # 將應(yīng)用的文件復(fù)制到鏡像里 ADD . /app # 運(yùn)行安裝腳本 RUN /app/setup.sh # 切換到應(yīng)用的目錄 WORKDIR /app # 指定應(yīng)用的啟動(dòng)腳本 COMMAND /app/start.sh
制作用于配置的啟動(dòng)腳本
如果應(yīng)用已經(jīng)在使用環(huán)境變量中讀取配置值了,那這一步可以跳過(guò)了。如果要從文件里讀取特定環(huán)境相關(guān)的配置值,那啟動(dòng)腳本就要能從環(huán)境變量里讀取配置值,并將這些值更新到配置文件中去。
這里有一個(gè)啟動(dòng)腳本的例子:
#!/usr/bin/env bash set -e # 把環(huán)境變量 $MYAPPCONFIG 的值添加到配置文件中 cat >>/app/config.txt <<END my_app_config = "${MYAPPCONFIG}" END # 用環(huán)境變量 $MYAPPARG 作為應(yīng)用的啟動(dòng)參數(shù) /app/bin/my-app --my-arg="${MYAPPARG}"
推送鏡像
鏡像生成之后(使用 docker build),需要推送到 Docker 倉(cāng)儲(chǔ)(Registry)中才能從部署機(jī)器上拉取到(如果要在生成鏡像的同一臺(tái)機(jī)器上運(yùn)行,就不需要)。
可以使用 Docker Hub 來(lái)存儲(chǔ)鏡像(用付費(fèi)賬號(hào)可以創(chuàng)建私有倉(cāng)庫(kù)),大多數(shù)云服務(wù)商也提供容器倉(cāng)儲(chǔ)(比如 Amazon ECR)。
給鏡像設(shè)置標(biāo)簽(比如 docker tag myimage mycompany/myimage:mytag)之后,就可以推送到倉(cāng)庫(kù)了(比如 docker push mycompany/myimage:mytag)。每次在應(yīng)用新版本生成鏡像時(shí)打上新的標(biāo)簽,這樣既能明確當(dāng)前所運(yùn)行的版本,還能保留舊版本的鏡像以便回滾。
三、如何部署
部署容器是個(gè)很大的話題,接下來(lái)只關(guān)注直接使用 docker 命令運(yùn)行容器的部分。在現(xiàn)實(shí)世界中,應(yīng)該考慮使用 docker-compose(對(duì)于所有容器都運(yùn)行在同一機(jī)器上的簡(jiǎn)單情形)和 Kubernetes (在集群中編排容器)之類(lèi)的工具。
被移出來(lái)的服務(wù)
提前移出來(lái)的服務(wù)可以運(yùn)行在單獨(dú)的 Docker 容器中,然后鏈接(link)到我們的應(yīng)用所在容器。另外,還可以用云上托管的服務(wù)。舉個(gè)例子,在 AWS 上,可以使用 RDS 作為數(shù)據(jù)庫(kù)、用 Elasticache 作為緩存,這樣可以極大地簡(jiǎn)化你的工作,因?yàn)樗麄兡転槟憬鉀Q后期維護(hù),高可用和備份等需求。
運(yùn)行 Postgres 數(shù)據(jù)庫(kù)容器的例子:
docker run -d \ --name db \ -v /usr/local/postgresql/data:/var/lib/postgresql/data \ postgres
容器化之后的應(yīng)用
要在 Docker 容器中運(yùn)行一個(gè)應(yīng)用,只要用一個(gè)命令行:
docker run -d \ -p 8080:80 \ --name myapp \ -v /usr/local/myappdata:/var/lib/myappdata \ -e MYAPPCONFIG=myvalue \ -e MYAPPARG=myarg \ --link db:db \ myappimage:mytag
其中的 -p 參數(shù)將容器里的 80 端口公開(kāi)并映射到主機(jī)上的 8080 端口,-v 參數(shù)設(shè)置要在容器里加載的、用于持久化數(shù)據(jù)的存儲(chǔ)卷(格式是 主機(jī)上的路徑:容器中的路徑)-e 參數(shù)設(shè)置一個(gè)用于配置的環(huán)境變量值(這些參數(shù)可以指定多次,從而設(shè)置多個(gè)卷和環(huán)境變量),而 --link參數(shù)將數(shù)據(jù)庫(kù)所在容器以鏈接的方式傳入,這樣應(yīng)用就可以與數(shù)據(jù)庫(kù)通信了。容器會(huì)根據(jù) Dockerfile 中的 COMMAND 指令指定的腳本來(lái)啟動(dòng)。
對(duì)應(yīng)用進(jìn)行升級(jí)
如果要升級(jí)到應(yīng)用的新版本,只要停掉舊版的容器(比如 docker rm -f myapp),并用新的鏡像標(biāo)簽啟動(dòng)新的容器就可以了(可能有短暫的停機(jī)時(shí)間)。回滾操作也類(lèi)似,只要換用舊版的鏡像標(biāo)簽。
更多相關(guān)考量
“init” 進(jìn)程(PID 1)
傳統(tǒng)應(yīng)用通常有多個(gè)進(jìn)程,如果沒(méi)有 “init” 守護(hù)進(jìn)程(PID 1)的清理,就容易出現(xiàn)孤兒進(jìn)程(orphan processes)發(fā)生累積的情況了。Docker 默認(rèn)并不提供這樣的守護(hù)進(jìn)程,所以推薦自己用 ENTRYPOINT 在 Dockerfile 里添加一個(gè)。dumb-init 是眾多初始守護(hù)進(jìn)程中的比較輕量級(jí)的一個(gè)。phusion/baseimage 是一個(gè)包含 init 初始守護(hù)進(jìn)程和其他一些服務(wù)的全功能基準(zhǔn)鏡像。 請(qǐng)查看我們博客上關(guān)于這個(gè)主題的文章:Docker 守護(hù)進(jìn)程:PID-1, 孤兒進(jìn)程, 僵尸進(jìn)程和信號(hào)。
守護(hù)進(jìn)程和定時(shí)任務(wù)
在使用 Docker 容器時(shí),一般只會(huì)在每個(gè)容器中運(yùn)行一個(gè)進(jìn)程。理想情況下,所有守護(hù)進(jìn)程和定時(shí)任務(wù)都應(yīng)該移到其他容器中去,不過(guò)對(duì)于傳統(tǒng)應(yīng)用來(lái),這也不一定都行得通,主要是經(jīng)常要求對(duì)應(yīng)用進(jìn)行重新設(shè)計(jì)。要運(yùn)行多個(gè)進(jìn)程也不是一定不行,但確實(shí)會(huì)需要一些額外的一些配置,因?yàn)闃?biāo)準(zhǔn)的基準(zhǔn)鏡像里并不包含進(jìn)程管理和調(diào)度能力。小型進(jìn)程管理程序,比如 runit,比 systemd 之類(lèi)的完整功能的子系統(tǒng)更適合在容器中用。phusion/baseimage 是一個(gè)包含 runit 和定時(shí)能力和其他一些服務(wù)的全功能基準(zhǔn)鏡像。
存儲(chǔ)卷的權(quán)限
在容器里,所有進(jìn)程通常都以 root 身份運(yùn)行(不過(guò)也不是必須的)。傳統(tǒng)的應(yīng)用對(duì)用戶的需求通常復(fù)雜一些,可能要用其他用戶來(lái)運(yùn)行(或者用不同的用戶運(yùn)行多個(gè)進(jìn)程)。這可能給存儲(chǔ)卷的使用帶來(lái)一些麻煩,因?yàn)?Docker 默認(rèn)讓加載的卷的所有權(quán)指向 root,也就是說(shuō)非 root 進(jìn)程就不能寫(xiě)入到這些卷了。有兩個(gè)方法可以解決這個(gè)問(wèn)題:
第一種方式是在在創(chuàng)建容器之前,先在主機(jī)上創(chuàng)建好目錄,由有正確的 UID/GID 的用戶持有所有權(quán)。注意,由于容器里和主機(jī)上的用戶不能匹配,所以需要用容器里用戶的 UID/GID,而不僅僅是用戶名要一致。
另一種方式是在容器里,在啟動(dòng)過(guò)程中調(diào)整加載點(diǎn)的所有權(quán)。這就需要在切換到用來(lái)啟動(dòng)應(yīng)用的非 root 用戶之前,還在以 root 身份運(yùn)行期間處理。
數(shù)據(jù)庫(kù)遷移
數(shù)據(jù)庫(kù)結(jié)構(gòu)遷移在部署工作中經(jīng)常是一大挑戰(zhàn),因?yàn)閿?shù)據(jù)庫(kù)結(jié)構(gòu)通常與應(yīng)用是嚴(yán)格耦合的,這對(duì)遷移的時(shí)機(jī)提出了要求,而且這也讓回滾到舊版本變得更難,因?yàn)閿?shù)據(jù)庫(kù)遷移并不一定容易回滾。
完成這種遷移的方法是引入一個(gè)過(guò)渡步驟。如果需要對(duì)數(shù)據(jù)庫(kù)結(jié)構(gòu)做出與舊版本不兼容的變更,那就將這個(gè)變更分為兩次部署。比如,如果想將數(shù)據(jù)移到另一處,兩個(gè)步驟是:
將數(shù)據(jù)同時(shí)寫(xiě)入舊的位置和的位置,并只從新的位置讀取。這意味著,如果把應(yīng)用回滾到前一個(gè)版本,在回滾之前新產(chǎn)生的新數(shù)據(jù)是不會(huì)丟的。
不再向舊的位置寫(xiě)入數(shù)據(jù)。 要注意的是,如果希望部署期間沒(méi)有停機(jī)時(shí)間,就意味著在同一時(shí)間會(huì)有應(yīng)用的多個(gè)版本在運(yùn)行,相應(yīng)的也會(huì)帶來(lái)更多挑戰(zhàn)。
數(shù)據(jù)備份
對(duì)容器化的應(yīng)用進(jìn)行備份通常比較簡(jiǎn)單。數(shù)據(jù)文件可以從主機(jī)上備份,而不需要擔(dān)心數(shù)據(jù)會(huì)與應(yīng)用程序的文件混在一起,因?yàn)樗鼈円呀?jīng)嚴(yán)格地分開(kāi)了。如果將數(shù)據(jù)庫(kù)遷移到了像 RDS 這樣的托管服務(wù),他們就會(huì)處理好備份(至少自己的工作會(huì)簡(jiǎn)化一些)。
遷移已有數(shù)據(jù)
在生產(chǎn)環(huán)境中,要把現(xiàn)有應(yīng)用遷向容器化的版本,就需要對(duì)舊的已有數(shù)據(jù)進(jìn)行遷移。這個(gè)工作往往因地制宜,不過(guò)最簡(jiǎn)單的就是停掉舊版本,把數(shù)據(jù)備份直接恢復(fù)給新版本用。這個(gè)過(guò)程應(yīng)該提前做好,也不可避免地會(huì)需要一定的停機(jī)時(shí)間。
到此,關(guān)于“怎么創(chuàng)建用于安裝應(yīng)用的Dockerfile”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
名稱(chēng)欄目:怎么創(chuàng)建用于安裝應(yīng)用的Dockerfile-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://vcdvsql.cn/article44/ieche.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開(kāi)發(fā)、用戶體驗(yàn)、靜態(tài)網(wǎng)站、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、商城網(wǎng)站、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容