Docker容器的"單進(jìn)程模型"
剛開始學(xué)Docker的時(shí)候因?yàn)椴恢?/span>Docker跟以前在VirtualBox里安的虛擬機(jī)還有Vargrant有啥區(qū)別,我都是習(xí)慣性的把開發(fā)環(huán)境里用的東西往單個(gè)容器里塞。后來看網(wǎng)上的教程還有別人分享的案例多了后,才知道把應(yīng)用容器化的第一步是:要把應(yīng)用用到的東西拆解放到多個(gè)容器里。慢慢地我發(fā)現(xiàn)不少人剛開始學(xué)Docker時(shí)候跟我一樣都有剛接觸時(shí)把Docker當(dāng)虛擬機(jī)來用的問題,比如我特別早以前發(fā)過一篇文章《用Docker-Compose搭建Laravel開發(fā)環(huán)境》里,我用三個(gè)分別裝著PHP、MySQL和Nginx的容器搭建了一個(gè)開發(fā)環(huán)境。有讀者就問了這么一個(gè)問題:

不過那會(huì)兒我對(duì)Docker的掌握程度也僅限在搭建個(gè)開發(fā)環(huán)境這個(gè)級(jí)別,很多原理也不太理解所以只是告訴他每個(gè)容器里只能有單一的進(jìn)程,這樣更好管理、擴(kuò)展之類的,希望這個(gè)大哥最后找到了正確的學(xué)習(xí)方法。不過在許多關(guān)于Docker的博客文章和教程里列舉的最佳實(shí)踐里確實(shí)都有:"每個(gè)容器只運(yùn)行一個(gè)進(jìn)程"這樣的說法。為什么存在此規(guī)則?為什么不在單個(gè)容器中運(yùn)行Nginx,PHP,Go或者更多進(jìn)程?
通過最近的文章《容器和虛擬機(jī)到底有啥區(qū)別?》我們聊了,容器不像虛擬機(jī)那樣擁有獨(dú)立的操作系統(tǒng),容器只是通過Linux的Namespaces、Cgroups實(shí)現(xiàn)了進(jìn)程級(jí)別的隔離。雖然在容器里看不見宿主機(jī)上的其他進(jìn)程,但歸根結(jié)底它還只是一個(gè)運(yùn)行在宿主機(jī)上的進(jìn)程,所以就不具備操作系統(tǒng)的進(jìn)程管理能力。
每個(gè)容器里只運(yùn)行一個(gè)進(jìn)程這個(gè)說法其實(shí)不太準(zhǔn)確,因?yàn)橄?/span>Nginx在啟動(dòng)后主進(jìn)程會(huì)再開啟若干個(gè)Worker進(jìn)程負(fù)責(zé)請(qǐng)求的處理,Apache更是會(huì)為每個(gè)請(qǐng)求創(chuàng)建一個(gè)進(jìn)程。容器的"單進(jìn)程模型",并不是指容器里只能運(yùn)行"一個(gè)"進(jìn)程,而是指容器沒有管理多個(gè)進(jìn)程的能力。這是因?yàn)槿萜骼锏闹鬟M(jìn)程(PID=1 的進(jìn)程)就是應(yīng)用本身,其他的進(jìn)程都是這個(gè)主進(jìn)程的子進(jìn)程。可是,用戶編寫的應(yīng)用,并不能夠像正常操作系統(tǒng)里的init進(jìn)程或者systemd 那樣擁有進(jìn)程管理的功能。比如,你的容器啟動(dòng)命令是執(zhí)行一個(gè)shell腳本,腳本里依次啟動(dòng)容器里的Nginx和Web應(yīng)用。
比如是下面這個(gè)shell腳本
sudo?su?-root?-c?"nginx?-s?start?&&?/app/go_web_bin"
那么這個(gè)容器里主進(jìn)程是sh,Nginx和Web應(yīng)用是子進(jìn)程。可是,當(dāng)這個(gè) Nginx進(jìn)程異常退出的時(shí)候,主進(jìn)程sh是感知不到的,也就沒法對(duì)Nginx進(jìn)行重啟。Docker只能識(shí)別主進(jìn)程的狀態(tài),如果主進(jìn)程正常,Docker的狀態(tài)就是Running所以在容器里不推薦跑多個(gè)進(jìn)程。
所以更確切的說法是每個(gè)容器應(yīng)該只有一個(gè)關(guān)注點(diǎn),只有一個(gè)單一的功能。將應(yīng)用程序解耦到多個(gè)容器中,可以更輕松地水平縮擴(kuò)和重復(fù)使用容器。例如,一個(gè)Web應(yīng)用程序服務(wù)可能由三個(gè)單獨(dú)的容器組成,每個(gè)容器都有自己的鏡像,以松耦合的方式管理Web應(yīng)用程序,數(shù)據(jù)庫和Redis緩存。對(duì)于這些相互依賴的容器,則使用Docker容器網(wǎng)絡(luò)來保持這些容器的通信。
推薦閱讀
站長(zhǎng) polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)
Go語言中文網(wǎng)
每天為你
分享 Go 知識(shí)
Go愛好者值得關(guān)注
