一、docker-compose講解
1、docker-compose是什么
Compose是定義和運行多容器Docker應用程序的工具。 使用Compose,您可以使用YAML文件來配置應用程序的服務。 然后,使用單個命令,您可以創建並啟動配置中的所有服務。
Compose適用於所有環境:生產,開發,測試以及CI工作流程。使用Compose基本上是一個三步過程:
- 使用Dockerfile定義應用程序的環境,以便在任何地方進行復制。
- 在docker-compose.yml中定義組成應用程序的服務,以便它們可以在隔離的環境中一起運行。
- 運行docker-compose並撰寫開始並運行你的整個應用程序。
可以參考docker-compose官方說明詳細了解:https://docs.docker.com/compose/overview/
還沒有完全理解的朋友,用通俗的語言來說:
docker-compose 是用來做docker 的多容器控制,docker-compose 是一個用來把 docker 自動化的東西,有了 docker-compose 你可以把所有繁復的 docker 操作全都一條命令,自動化的完成。
2、談談容器編排與部署
Docker有很多優勢,但對於運維或開發者來說,Docker最大的有點在於它提供了一種全新的發布機制。這種發布機制,指的是我們使用Docker鏡像作為統一的軟件制品載體,使用Docker容器提供獨立的軟件運行上下文環境,使用Docker Hub提供鏡像統一協作,最重要的是該機制使用Dockerfile定義容器內部行為和容器關鍵屬性來支撐軟件運行。
Dockerfile作為整個機制的核心。這是一個非常了不起的創新,因為在Dockerfile中,不但能夠定義使用者在容器中需要進行的操作,而且能夠定義容器中運行軟件需要的配置,於是軟件開發和運維終於能夠在一個配置文件上達成統一。運維人員使用同一個Dockerfile能在不同的場合下“重現”與開發者環境中一模一樣的運行單元(Docker容器)出來。
3、為什么要使用Compose
先來想一下我們平時是怎么樣使用docker的?把它進行拆分一下:
1、docker search 鏡像,是不是先查找一個鏡像;
2、docker run -itd 鏡像名稱 ,然后在運行這個鏡像;
3、然后如果你要在運行第二個鏡像、第三個鏡像.....等等鏡像,你是不是又要docker search、docker run運行。
上面“ docker run it 鏡像名稱 ”這只是最小的動作, 如果你要映射硬盤,設置nat網絡或者映射端品,等等…你就要做更多的 docker 操作, 這顯然是非常沒有效率的,況且如果你要大規模部署,是不是覺得就很麻煩了。
但是我們寫在 docker-compose.file 里面就很好了。你只需要寫好后只運行一句:
docker-compose up -d
4、了解下編排和部署
編排,即orchestration,它根據被部署的對象之間的耦合關系,以及被部署對象環境的依賴,制定部署流程中各個動作的執行順序,部署過程所需要的依賴文件的存儲位置和獲取方式,以及如何驗證部署成功。這些信息都會在編排工具中以指定的格式(比如配置文件或者特定的代碼)來要求運維人員定義並保存起來,從而保證這個流程能夠隨時在全新的環境中可靠有序地重現出來。
部署,即deployment,它是指按照編排所指定的內容和流程 ,在目標機器上執行編排指定環境初始化,存放指定的依賴和文件,運行指定的部署動作,最終按照編排中的規則來確認聯署成功。
而在Compose的世界里,編排和部署的組合結果,就是一朵“容器雲”。
5、一探究竟~~ Compose原理
docker-compose的調用過程扁平的像一張紙,僅用一張簡單的模塊圖就足夠解釋明白,如下圖所示:

Compose的一次調用過程
首先,用戶執行的docker-compose up指令調用了命令行中的啟動方法。功能很簡單明了,一個docker-compose.yml定義了一個docker-compose的project,docker-compose操作提供的命令行參數則作為這個project的啟動參數交由project模塊去處理。
其次,如果當前宿主機已經存在與該應用對應的容器,docker-compose將進行行為邏輯判斷。如果用戶指定可以重新啟動已有服務,docker-compose就會執行service模塊的容器重啟方法,否則就將直接啟動已有容器。這兩種操作的區別在於前者會停止舊的容器,創建啟動新的容器,並把舊容器移除掉。在這個過程中創建容器的各項定義參數都是從docker-compose up 指令和docker-compose.yml中傳入的。
接下來,啟動容器的方法也很簡潔,這個方法中完成了一個Docker容器啟動所需的主要參數的封裝,並在container模塊執行啟動。該方法所支持的參數我想大多數朋友過是有所了解的。
最后,container模塊會調用docker-py客戶端執行向Docker daemon發起創建容器的POST請求,再往后就是Docker處理的范疇了。
為了能夠說明compose如何實現上述編排與部署的原理,下面和大家分享一個通過compose來編排部署LNMP服務來更好的理解它。
二、compose編排LNMP服務
4.1 yaml
YAML是一種標記語言,可讀性很強。類似於XML數據描述語言,語法比XML簡單的多。YAML數據結構通過縮進來表示,連續的項目通過減號來表示,鍵值對用冒號分融,數組用括號括起來,hash用花括號括起來。詳細了解的朋友可以參考 YAML百度百科 https://baike.baidu.com/item/YAML/1067697?fr=aladdin
YAML文件格式注意事項:
- 在縮排中空白字符的數目並不是非常重要,只要相同階層的元素左側對齊就可以了(不過不能使用TAB字符);
- 通常開頭縮進2個空格;
- 字符的后面縮進1個空格,比如冒號、逗號、橫桿;
- 支持#注釋;
- 允許在文件中加入選擇性的空行,以增加可讀性;
docker-compose中YAML常用的字段:

4.2 目錄結構
我們先來看下所需要的文件、目錄結構是怎樣的:
[root@ganbing /]# tree compose_lnmp/
compose_lnmp/
├── docker-compose.yml
├── mysql
│ ├── conf
│ │ └── my.cnf
│ └── data
├── nginx
│ ├── Dockerfile
│ ├── nginx-1.12.1.tar.gz
│ └── nginx.conf
├── php
│ ├── Dockerfile
│ ├── php-5.6.31.tar.gz
│ └── php.ini
└── wwwroot
├── index.html
└── index.php
這里多了兩個目錄:
mysql目錄>>conf目錄>>my.cnf(mysql默認配置)
mysql目錄>>data目錄(用於后期掛載到mysql容器)
wwwroot目錄>>index.html和index.php這兩個首頁,用於部署成功后進行訪問測試
4.3 安裝docker-compose
下載最新版本安裝,下載時間可能比較長
[root@ganbing ~]# curl -L https://github.com/docker/compose/releases/download/1.15.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose [root@ganbing ~]# chmod +x /usr/local/bin/docker-compose
或者用pip安裝:pip install docker-compose
docker-compose用法
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose常用命令:
build 構建或重建服務
kill 殺掉容器
logs 顯示容器的輸出內容
port 打印綁定的開放端口
ps 顯示容器
pull 拉取服務鏡像
restart 重啟服務
rm 刪除停止的容器
run 運行一個一次性命令
scale 設置服務的容器數目
exec 在容器里搪行命令
start 開啟服務
stop 停止服務
up 創建並啟動容器
其實這些常用命令用docker的命令功能是一樣的。
4.4 一鍵部署lnmp平台
我們先來看下/compose_lnmp目錄下的docker-compose.yml文件:
[root@ganbing compose_lnmp]# ls docker-compose.yml mysql nginx php wwwroot [root@ganbing compose_lnmp]# cat docker-compose.yml version: '3' services: nginx: hostname: nginx build: context: ./nginx dockerfile: Dockerfile ports: - 80:80 networks: - lnmp volumes: - ./wwwroot:/usr/local/nginx/html php: hostname: php build: context: ./php dockerfile: Dockerfile networks: - lnmp volumes: - ./wwwroot:/usr/local/nginx/html mysql: hostname: mysql image: mysql:5.6 ports: - 3306:3306 networks: - lnmp volumes: - ./mysql/conf:/etc/mysql/conf.d - ./mysql/data:/var/lib/mysql command: --character-set-server=utf8 environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: wordpress MYSQL_USER: ganbing MYSQL_PASSWORD: ganbing123 networks: lnmp:
可以看到一份標准配置文件應該包含 version、services、networks 三大部分,共有三級標簽,每一級都是縮進兩個空格。下面來詳細說明一下里面的內容:
-
version: '3'
這是定義compose的版本號為version 3,可以參考官方文檔詳細了解具體有哪些版本 https://docs.docker.com/compose/compose-file/ - services:
nginx:這是services下面的二級標簽,名字用戶自己定義,它將是服務運行后的名稱;
hostname: nginx 這是定義容器的主機名,將寫入到/etc/hostname中;
build:
context: ./nginx 指定nginx服務的上下文路徑;
dockerfile:Dockerfile 指定通過上面指定路徑中的Dockerilfe來構建;
ports:
- 80:80 端口映射沒什么好說的;
networks:
-lnmp 指定的網絡環境
volumes:把宿主機的/wwwroot目錄綁定到容器中的/usr/local/nginx/html目錄;
php:這個二級標簽服務和下面的內容跟nginx差不多;
mysql:這個二級標簽服務也和nginx、php差不多,唯一不同的是多了個images標簽、還有定義了些環境變量。
image: mysql:5.6 它是通過mysql:5.6鏡像來構建mysql服務器,前面nginx、php都指定了上下文通過Dockerfile來構建的。
environment:
MYSQL_ROOT_PASSWORD:定義root用戶密碼變量為123456;
MYSQL_DATABASE:定義了數據變量為wordpress;
MYSQL_USER:定義了普通用戶變量為ganbing;
MYSQL_PASSWORD:定義了普通用戶密碼變量為ganbing123;
3、networks:
lnmp: 相當於執行docker network create lnmp命令了;
最后來運行docker-compose命令來啟動:
[root@ganbing /]# cd compose_lnmp/ [root@ganbing compose_lnmp]# docker-compose -f docker-compose.yml up -d
來查看一下是否啟動完成:
[root@ganbing compose_lnmp]# docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------- composelnmp_mysql_1 docker-entrypoint.sh --cha ... Up 0.0.0.0:3306->3306/tcp composelnmp_nginx_1 ./sbin/nginx -g daemon off; Up 0.0.0.0:80->80/tcp composelnmp_php_1 ./sbin/php-fpm -c /usr/loc ... Up 9000/tcp
從上面可以看出這3個服務都是UP狀態,運行 docker-compose ps必須要在有docker-compose.yml文件目錄下執行才可以。
同樣,還可以用docker ps來查看:

訪問網站:
總結思考
大家想想,僅僅使用Compose,就可以構建自己的容器雲嗎?答案顯然是否定的。docker-compose解決的問題局限在“編排”二字,甚至連“部署”范疇都涉足甚少,而在一個能夠服務於大眾的雲平台中,編排與部署也僅僅是其中的一個組成部分而已。來一起分析一下它的局限制會有哪些:
- docker-compse是面向單宿主機部署的,這是一種部署能力的欠缺。在更多的場合下,管理員需要面對大量物理服務器(或者虛擬機),這時如果要實現基於docker-compose的容器自動化編排與部署,管理員就得借助成熟的自動化運維工具(ansible、puppet、chef、saltstack)來負責管理多個目標主機,將docker-compose所需的所有資源(配置文件、用戶代碼)交給目標主機,然后在目標主機上執行docker-compose指令。
- 同樣網絡和存儲也比較棘手,Docker不能提供跨宿主機的網絡,完全面向Docker daemon的docker-compose當然也不支持。這意味着管理員必須部署一套類似於Open vSwich的獨立網絡工具,而且管理員還需要完成集成工作。當好不容易把容器編排都安排妥當之后,又會發現容器還處在內網環境中,於是負載均衡、服務發現等一堆問題就面臨而來了,這些問題很快能消耗掉工程師所有的耐心。
那么,是否有一種能夠提供完善的面向服務器集群的Docker編排和部署方案呢?Docker官方給出的答案是Compose同Machine和Swarm聯動,其實還有大家近期經常聽到了kubernetes(k8s)
