docker-compose一些小理解
Docker Compose的前身是Fig,它是一個定義及執行多個Docker容器的工具。使用Docker Compose你只需要在一個配置檔案中定義多個Docker容器,然後使用一條命令將多個容器啟動,Docker Compose會通過解析容器件的依賴關係(link, 網路容器 –net-from或資料容器 –volume-from)按先後順序啟動所定義的容器。
Docker Compose的工作原理
Docker Compose將所管理的容器分為三層,工程(project),服務(service)以及容器(contaienr)。Docker Compose執行的目錄下的所有檔案(docker-compose.yml, extends檔案或環境變數檔案等)組成一個工程,若無特殊指定工程名即為當前目錄名。一個工程當中可包含多個服務,每個服務中定義了容器執行的映象,引數,依賴。一個服務當中可包括多個容器例項,Docker Compose並沒有解決負載均衡的問題,因此需要藉助其他工具實現服務發現及負載均衡。
Docker Compose的工程配置檔案預設為docker-compose.yml,可通過環境變數COMPOSE_FILE或-f引數自定義配置檔案,其定義了多個有依賴關係的服務及每個服務執行的容器。以下是一個簡單的配置檔案:
其定義了兩個服務web和redis。web服務的映象需要在當前目錄實時構建,其容器執行時需要在宿主機開放埠5000並對映到容器埠5000,並且掛載儲存卷/code以及關聯服務redis。redis服務通過映象redis啟動。
Docker Compose是由python語言實現的,它通過呼叫docker-py庫(可參考https://github.com/docker/docker-py
下面我們通過分析docker-compose最複雜的命令up的原始碼來了解一下docker compose的工作原理。
通過命令docker-compose up -d啟動以上docker-compose.yml定義的服務。
我們可以看到redis服務先於web服務建立,這是因為docker-compose解析到服務間的依賴關係,web服務依賴於redis服務,所以進行了排序。我們來看一下docker compose up的工作流程。
工程初始化 – 解析配置檔案(包括docker-compose.yml,外部配置檔案extends files,環境變數配置檔案env_file),並將每個服務的配置轉換成python字典,初始化docker-py客戶端用於與本地或遠端的docker engine通訊。
根據docker-compose的命令引數將命令分發給相應的處理函式,此處為up
呼叫project類的up函式,得到當前工程中的所有服務,並根據服務的依賴性(links,external links – 本工程或docker-compose之外的容器,多用於多專案共用容器,網路容器net-from以及資料容器volume-from)進行排序並去掉重複出現服務(此情況可因某服務被其他多個服務依賴所造成)
Docker Compose使用labels標記啟動的容器
使用docker inspect可以看到一個通過docker compose啟動的容器被添加了一些compose使用的標記
- Docker Compose通過compose工程名以及服務名從docker engine獲取當前所有含有此標記的容器以檢查當前工程所包含的服務狀態,根據當前狀態為每個服務制定接下來的動作。
a. 若容器不存在,則服務動作設定為建立(create)
b. 若容器存在但設定不允許重建,則服務動作設定為啟動(start)
c. 若容器配置發生變化(config-hash)或者設定強制重建標誌,則服務動作設定為重建(recreate)
d. 若容器狀態為停止,則服務動作設定為啟動(start)
e. 若容器狀態為執行但其依賴容器需要重建,則服務狀態設定為重建(recreate)
f. 若容器狀態為執行其無配置改變則不作操作
6. 根據每個服務不同的動作執行不同的操作
服務動作為建立
a. 檢查映象是否存在(呼叫docker-py client inspect函式從本地或遠端的docker engine獲取映象資訊)。若映象不存在,則檢查配置檔案中關於映象的定義。如果在配置檔案中設定為build則呼叫docker-py build函式與docker engine通訊完成docker build的功能。如果在配置檔案中設定為image則通過docker-py pull函式與docker engine通訊完成docker pull的功能。
b. 獲取當前服務中容器的配置資訊,如埠,儲存卷,主機名,使用映象環境變數等配置的資訊。若在配置中指定本服務必須與某個服務在同一臺主機(previous_container,用於叢集)則在環境變數中設定affinity:container=。通過docker-py與docker engine通訊建立並啟動容器。
服務動作為重建
a. 停止當前的容器
b. 將現有的容器重新命名,這樣資料卷在原容器被刪除前就可以拷貝到新建立的容器中了
c. 建立並啟動新容器,previsous_container設定為原容器確保其執行在同一臺主機(儲存卷掛載)
d. 刪除舊容器
服務動作為啟動則啟動停止的容器
若docker-compose up沒有指明-d即前臺執行,則將所有各個容器的輸出匯聚列印
註冊訊號SIGINT處理函式,若收到訊號SIGINT則並行殺掉所有容器
到此為止docker-compose up的命令執行完畢,docker-compose.yml檔案中定義的服務 全部啟動。
Docker Compose的命令主要分為以下幾類
管理服務:up/start/scale/stop/restart/rm/kill
管理映象:build/pull
檢視服務執行狀態:ps/port
列印執行中的服務log:logs
在一個服務中執行一個一次性命令:run
以上這些命令都是通過label標記來過濾當前工程裡的容器,然後呼叫docker-py庫呼叫Docker remote API與docker engine通訊控制容器。
Docker Compose是一個部署多個容器的簡單但是非常必要的工具,它使你使用一條簡單的命令部署多個容器。Docker Compose在實際工作中非常有價值,其大大簡化了多容器的部署過程,避免了在不同環境執行多個重複步驟所帶來的錯誤可能,使多容器移植變得簡單可控。從其Roadmap可以看出,Docker Compose的目標是做一個生產環境可用的工具,包括服務回滾,多環境支援(dev/test/staging/prod),支援線上服務部署升級,防止服務中斷並且監控服務使其始終執行在正確的狀態。Roadmap中的另一個目標是更好的與Docker Swarm整合,目前版本存在的主要問題是無法保證處於多個主機的容器間正常通訊因為目前不支援跨主機間容器通訊,我們相信新的Docker網路實現將會解決這一問題。另一個問題是在Docker Compose中定義構建的映象只存在在一臺Docker Swarm主機上,無法做到多主機共享,因此目前需要手動構建映象並上傳到一個映象倉庫使多個Docker Swarm主機可以訪問並下載映象。相信隨著Docker Compose的完善,其必將取代docker run成為開發者啟動docker容器的首選。
docker-compose只會為每個映象維護一個例項,每次執行
docker-compose up
的時候,compose會查詢之前的容器,把舊容器的volume-data拷貝到容器中。除非手動用docker rm命令刪除容器,否則CONTAINER ID不會發生改變。
這和
docker run [images name]
不一樣,這個命令每次執行會新生成一個映象的例項,即新容器,它們對應的CONTAINER ID也各不相同。