在docker中,程序管理的基礎是linux核心的pid命名空間技術。在不同的pid命名空間下,可以有相同的pid。
linux核心為所有的pid命名空間維護了乙個樹狀的資料結構,最頂層是系統初始化時建立的root namespace(根命名空間), 父節點可以看到子節點中的程序,並可以通過訊號等方式對子節點中的程序產生影響。反過來,子節點不能看到父節點名空間中的任何內容,也不可能通過kill或ptrace影響父節點或其他名空間中的程序。
在docker中有乙個很特殊的程序——pid為1的程序,這也是docker的主程序,通過dockerfile中的 entrypoint 和/或 cmd指令指定。當主程序退出的時候,容器所擁有的pig命名空間就會被銷毀,容器的生命週期也會結束docker最佳實踐建議的是乙個container乙個service,並不強制要你乙個container乙個執行緒。有的服務,會催生更多的子程序,比如apache和uwsgi,這是完全ok的。
pid1程序需要對自己建立的子程序負責,當主程序沒有設計好,不能優雅地讓子程序退出,就會照成很多問題,比如資料庫container,如果處理資料的程序沒有優雅地退出,可能會照成資料丟失。如果很不幸,你的主程序就是這種管理不了子程序的那種,docker提供了乙個小工具,幫助你來完成這部分內容。你只需要在run建立container的時候提供乙個—init flag就行,docker就會手動為你處理好這些問題。
在docker中,對於cmd和 entrypoint,支援兩種程序執行方式:exec和shell。
shell的格式是:
最終pid1程序將是: /bin/sh -c 」executable param1 param2」cmd "executable param1 param2"
複製**
exec的格式是:
最終的pid1程序是: executable param1 param2cmd ["executable","param1","param2"]
複製**
現在有兩個映象,dockerfile分別如下:
from ubuntu:14.04
runapt-get update && apt-get -y install redis-server && rm -rf /var/lib/apt/lists/*
expose
6379
cmd"/usr/bin/redis-server"
複製**
from ubuntu:14.04
runapt-get update && apt-get -y install redis-server && rm -rf /var/lib/apt/lists/*
expose
6379
cmd["/usr/bin/redis-server"]
複製**
那個docker映象更好一點呢?docker run -d --name myredis1 redis:shell
docker run -d --name myredis2 redis:exec
複製**
我們前面講過,pid1程序(主程序)需要對自己的子程序負責,對於redis:shell,它產生的pid1程序是
也就是說,是/bin/sh這個程序,不是/usr/bin/redis-server!/usr/bin/redis-server只是它建立的乙個子程序!/bin/sh -c "/usr/bin/redis-server"
複製**
執行命令
可以驗證這種猜測docker exec myredis1 ps -ef
複製**
通過exec方式執行的container的主程序則是我們所期望的。
你可能會覺得,這有什麼大不了的呢,問題出現當我們停止container的時候。
docker stop myredis1
docker logs myredis1
複製**
stop的時候,docker明顯停頓了一段時間,而且檢視日誌可以看出,redis沒有做任何儲存資料庫的操作,直接被強制退出了。這期間發生了什麼?首先,執行stop命令會向容器傳送 sigterm訊號,告訴主程序:你該退出了,感覺收拾收拾。但是,這裡的主程序是/bin/sh啊,它怎麼可能會有處理redis程序退出的機制?所以redis程序不會馬上退出。 docker daemon等待一段時間之後(預設是10s),發現容器還沒有完全退出,這時候就會傳送 sigkill,將容器強行殺死。在這過程中,redis程序完全不知道自己該退出了,所以他沒有做任何收尾的工作。
docker stop myredis2
docker logs myredis2
複製**
這一次stop的時候是立即生效了,沒有卡頓延遲現象,從輸出來看,redis進行了shutdown的操作,把該持久化的資料都儲存到磁碟了。因為這時候的pid1程序是
它是能夠正確處理sigterm訊號的。這才是我們所期望的。/usr/bin/redis-server
複製**
docker的主程序(pid1程序)是乙個很特殊的存在,它的生命週期就是docker container的生命週期,它得對產生的子程序負責,在寫dockerfile的時候,務必明確pid1程序是什麼。
從乙個例項學習 FLASK WTF
本案例通過實現乙個註冊頁面的編寫,來帶你了解flask wtf的運用.主要功能為表單基礎的功能 手機號碼必須為11位數,且通過資料庫查詢不能有已經註冊的了,密碼要求輸入兩遍且必須一樣,且所有內容不能為空的提示等內容.那麼現在就開始把 一.建立表單類.首先運用flask wtf你必須確保你的環境中已經...
從乙個例項中學習DTW演算法
dtw為 dynamic time warping,動態時間歸準 的簡稱。應用很廣,主要是在模板匹配中,比如說用在孤立詞語音識別,計算機視覺中的行為識別,資訊檢索等中。可能大家學過這些類似的課程都看到過這個演算法,公式也有幾個,但是很抽象,當時看懂了但不久就會忘記,因為沒有具體的例項來加深印象。這次...
程序只執行乙個例項
守護程序往往需要設定使其只執行乙個例項,這裡展示檔案鎖的方式實現 1.使用fcntl 函式設定檔案鎖 include include include include include include include int main else pause return 0 2.使用flock 設定鎖 ...