編排(Orchestration)功能是複雜系統實現靈活可操做性的關鍵。
特別是在Docker應用場景中,編排意味着用戶能夠靈活的對各類容器資源實現定義和管理。
做爲Docker官方編排工具,Compose的重要性不言而喻,
它可讓用戶經過編寫一個簡單模板文件,快速地建立和管理基於Docker容器地應用集羣。
Compose項目是Docker官方的開源項目,負責實現對Docker容器的快速編排。從功能上看,跟OpenStack中的Heat十分類似。
Compose定位是「定義和運行多個Docker容器的應用」,其前身是開源項目Fig,目前仍然兼容Fig格式的模板文件。
咱們知道使用一個DockerFile模板文件,可讓用戶很方便的定義一個單獨的應用容器。
若是須要定義多個容器就須要容器編排,那麼就可使用Compose了。
Compose容許用戶經過一個單獨的docker-compose.yml模板文件(YAML格式)來定義一組相關聯的應用容器爲一個項目。
Compose中有兩個重要的概念:
服務(service):一個應用的容器,實際上能夠包括若干個運行相同鏡像的容器實例。
項目(project):由一組關聯的應用容器組成的一個完整的業務單元,在docker-compose.yml文件中定義。
Compose的默認管理對象是項目,經過子命令對項目中的一組容器進行便捷地生命週期管理。
Compose項目由Python編寫,實現上調用了Docker服務提供地API來對容器進行地管理。
所以,只要所操做地平臺支持Docker API,就能夠在其上利用Compose來進行編排管理。php
pip install -U docker-compose
curl -L https://github.com/docker/compose/releases/download/1.23.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
官方提供了安裝腳本html
curl -L https://github.com/docker/compose/releases/download/1.23.0/run.sh > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
若是是二進制包安裝,將包刪除就能夠了,若是是pip安裝,使用pip uninstallpython
對於Compose來講,大部分命令地對象既能夠是項目自己,也能夠指定爲項目中地服務或者容器。
若是沒有特別說明,命令對象將是項目,這意味着項目中全部的服務都會受到命令地影響。
命令格式:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
options選項:mysql
Compose選項:nginx
命令使用說明:git
構建或重建項目中的服務器。
格式:
build [options] [--build-arg key=val...] [SERVICE...]
說明:
--compress 使用gzip壓縮構陷上下文
--force-rm 刪除構建過程當中的臨時容器
--no-cache 構建鏡像過程當中不適用緩存,不然會加長構建過程
--pull 始終嘗試拉取較新版本的鏡像
--m, --memory MEM 設置構建容器的內存限制
--build-arg key=val 設置服務構建時的變量
--parallel 並行構建鏡像github
從Compose中生成Docker包
格式:
bundle [options]
說明:
--push-images 自動推送任何服務的鏡像
-o, --output PATH 設置文件的寫入路徑web
驗證並查看Compose文件
格式:
config [options]
說明:
--resolve-image-digests 將鏡像標籤標記爲摘要
-q, --quiet 僅驗證配置,不打印任何東西
--services 打印服務名,每行一個
--volumes 打印卷名,每行一個
--hash="*" 打印服務配置的哈希redis
爲服務建立容器,不推薦使用此命令。推薦up --no-start
格式:
create [options] [SERVICE...]
說明:
--force-recreate 從新配置容器,即便它們的配置和鏡像沒有改變
--no-recreate 若是容器已經存在,不要從新建立
--no-build 不構建鏡像,即便丟失了
--build 在建立容器以前構建鏡像sql
中止並刪除容器以及網絡、鏡像和卷
格式:
down [options]
說明:
--rmi type 刪除鏡像,type是all或者local
-v, --volumes 刪除volumes中聲明的命名卷
--remove-orphans 刪除沒有在服務中定義的容器
-t, --timeout TIMEOUT 以秒爲單位指定關閉超時
從容器接受實時事件
格式:
events [options] [SERVICE...]
說明:
--json 將事件做爲json對象流輸出
列出建立容器所使用的鏡像
格式:
images [options] [SERVICE...]
說明:
-q, --quiet 僅輸出鏡像的id
強制中止一個容器的服務
格式:
kill [options] [SERVICE...]
說明:
-s SIGNAL 發送SIGNAL信號,默認發送的是SIGKILL
查看容器的輸出
格式:
logs [options] [SERVICE...]
說明:
--no-color 單色輸出
-f, --follow 遵循日誌輸出
-t, --timestamps 顯示時間戳
--tail="all" 每一個容器的日誌末尾顯示行數
打印某個容器端口所映射的公共端口
格式:
port [options] SERVICE PRIVATE_PORT
說明:
--protocol=proto 協議的類型,tcp或udp
--index=index 若是有多個容器,則爲容器的索引值,默認爲1
列出項目中的全部容器
格式:
ps [options] [SERVICE...]
說明:
-q, --quiet 僅顯示ID
--services 顯示服務
--filter KEY=VAL 經過一個鍵值對過濾
爲compose文件中定義的服務拉取鏡像,但不啓動容器。
格式:
Usage: pull [options] [SERVICE...]
說明:
--ignore-pull-failures 忽略拉取過程當中的錯誤
--parallel 並行拉出多個鏡像
--no-parallel 禁用並行
-q, --quiet 拉出而不打印進度信息
--include-deps 拉取服務的聲明做爲依賴項
刪除全部中止狀態的服務容器
說明:
-f,--force 強制直接刪除,包括非中止狀態的容器
-v 刪除容器所掛載的數據卷
在指定服務上執行一個命令。
默認狀況下,若是存在關聯,則關聯的服務也將會被自動啓動,除非這些服務已經載運行中。
若是不但願自動啓動關聯容器,可使用--no-deps選項。
格式:
run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]
說明:
-d 在後臺運行服務容器
--name NAME 爲容器指定一個名字
--entrypoint CMD覆蓋默認的容器啓動指令
-e KEY=VAL 設置環境變量,可屢次使用選項來設置多個環境變量
-u, --user=「」 指定運行容器的用戶名或者Uid
--no-deps 不自動啓動關聯的服務容器
--rm 運行命令後自動刪除容器,d模式下忽略
-p, --publish=[] 映射容器端口到本地主機
--service-ports 配置服務端口,並映射到本地主機
-T 不分配僞tty,意味着依賴tty的指令將沒法運行
設置服務運行個容器個數
格式:
scale [options] [SERVICE=NUM...]
說明:
-t, --timeout TIMEOUT中止容器時候的超時,默認10秒
該命令十分強大,它將嘗試自動完成包括構建鏡像,從新建立服務,啓動服務,並關聯服務相關容器的一系列操做。
連接的服務都將會被自動啓動,除非已經處於運行狀態。
若是容器已經存在,up將嘗試將容器中止,而後建立。
格式:
up [options] [--scale SERVICE=NUM...] [SERVICE...]
說明:
-d 在後臺運行服務器
--no-color 單色輸出
--no-deps 不啓動服務所關聯的容器
--force-recreate 強制從新建立容器
--no-recreate 若是容器已經存在了,則不從新建立
--no-build 不自動構建缺失的服務鏡像
-t, --timeout TIMEOUT 中止容器時候的超時
環境變量能夠用來配置Compose的行爲:
模板文件是使用Compose的核心,默認的模板文件名稱爲docker-compose.yml,格式爲YAML格式。
每一個服務都必須經過image指定鏡像或build(須要Dockerfile)來自動構成生成鏡像。
先來看一個基本示例:
version: '2' services: web: image: dockercloud/hello-world ports: - 8080 networks: - front-tier - back-tier redis: image: redis links: - web networks: - back-tier lb: image: dockercloud/haproxy ports: - 80:80 links: - web networks: - front-tier - back-tier volumes: - /var/run/docker.sock:/var/run/docker.sock networks: front-tier: driver: bridge back-tier: driver: bridge
能夠看到一份標準配置文件應該包含version、service、network三大部分。
其中最關鍵的就是services和networks兩部分。
下面是具體命令的書寫規則:
services: web: image: dockercloud/hello-world
在services標籤下的第二個標籤是web,這個名字是用戶本身自定義,它就是服務器名稱。
image則是指定服務的鏡像名稱。若是鏡像在本地不存在,Compose將會嘗試拉取這個鏡像。
下面這些格式都是可行的:
image: redis image: ubuntu:14.04 image: tutum/influxdb image: example-registry.com:4000/postgresql image: a4bc65fd
服務除了能夠基於指定的鏡像,還能夠基於以分Dockerfile,在使用up啓動之時執行構建任務。
這個構建標籤就是build,它能夠指定Dockerfile所在文件夾的路徑。
Compose將會利用它自動構建這個鏡像,而後利用這個鏡像啓動服務容器。
build: /path/to/build/dir
也能夠時相對路徑
build: ./dir
設定上下文根目錄,而後以該目錄爲準指定Dockerfile。
build: context: ../ dockerfile: path/of/Dockerfile
注意build都是一個目錄,若是你要指定Dockerfile文件,須要在build標籤的子級標籤中使用dockerfile標籤指定。
若是你同時指定了image和build兩個標籤,那麼Compose會構建鏡像而且把鏡像命名爲image後面的那個名字。
build: ./dir image: webapp:tag
既然能夠在docker-compose.yml中定義構建任務,那麼必定少不了arg這個標籤,
就像Dockerfile中的ARG指令,它能夠在構建過程當中指定環境變量,可是在構建成功後取消。
在docker-compose.yml文件中也支持這樣的寫法:
build: context: . args: buildno: 1 password: secret
下面這種寫法也是支持的,通常來講下面的寫法更適合閱讀。
build: context: . args: - buildno=1 - password=secret
與ENV不一樣的是,ARG是容許空指的,例如:
args: - buildno - password
這樣構建過程能夠向它們賦值。
注意:YAML的布爾值(true、false、yes、no、on、off)必需要使用引號引發來,不然會當成字符串解析。
使用command能夠覆蓋容器啓動後默認執行的命令。
command: bundle exec thin -p 3000
也能夠寫成相似Dockerfile中的格式
command: [bundle, exec, thin, -p, 3000]
前面說過Compose的容器名稱格式是:<項目名稱><服務名稱><序號>
雖然能夠自定義項目名稱、服務名稱,可是若是你想徹底控制容器的命名,可使用下面標籤指定:
container_name: app
這樣容器的名字就指定爲app了。
注意:指定容器名稱以後,該服務將沒法進行擴展,由於Docker不容許多個容器具備相同的名稱。
在使用Compose時,最大的好處就是少打啓動命令,但通常項目容器啓動的順序是有要求的。
若是直接從上到下啓動容器,必然會由於容器依賴問題而啓動失敗。
例如咱們在沒有啓動數據庫容器的時候啓動了應用容器,這時候應用容器會應爲找不到數據庫而退出。
爲了不這種狀況咱們須要加入一個標籤,就是depend_on,這個標籤解決了容器的依賴、啓動前後的問題。
例以下面容器會先啓動redis和db兩個服務,最後才啓動web服務:
version: '2' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
注意的是,默認狀況下使用docker-compose up web這樣的方式啓動web服務時,也會啓動redis和db兩個服務。由於配置文件中定義了依賴關係。
和--dns參數同樣用途,格式以下:
dns: 8.8.8.8
也能夠是一個列表:
dns: - 8.8.8.8 - 9.9.9.9
此外dns_search的配置也相似:
dns_search: example.com dns_search: - dc1.example.com - dc2.example.com
掛載臨時目錄到容器內部,與run的參數同樣效果:
tmpfs: /run tmpfs: - /run - /tmp
在Dockerfile中有一個指令ENTRYPOINT指令,用於指定接入點。
在docker-compose.yml中能夠定義接入點,覆蓋Dockerfile中的定義:
entrypoint: /code/entrypoint.sh
格式和Docker相似,不過還能夠寫成這樣:
entrypoint: php - -d - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so - -d - memory_limit=-1 - vendor/bin/phpunit
在docker-compose.yml中能夠定義一個專門存放變量的文件。
若是經過docker-compose -f FILE指定配置文件,則env_file中路徑會使用配置文件路徑。
若是有變量名稱與environment指令衝突,則之後者爲準。格式以下:
env_file: .env
或者根據docker-compose.yml設置多個:
env_file: - ./common.env - ./apps/web.env - /opt/secrets.env
注意的是這裏所說的環境變量是對宿主機的Compose而言,若是在配置文件中有build操做,
這些變量並不會進入構建過程,若是要在構建中使用變量仍是首選前面所說的arg標籤。
環境變量中的每一行必須符合格式,支持#開頭的註釋行。
與上面的env_file標籤徹底不一樣,這個標籤的做用是設置鏡像變量,
它能夠保存變量到鏡像裏面,也就是說啓動的容器也會包含這些變量設置,這是與arg最大的不一樣。
通常arg標籤的變量僅用在構建過程當中。
而enviroment和Dockerfile中ENV指令同樣會把變量一直保存在鏡像、容器中,相似docker run -e的效果。
environment: RACK_ENV: development SHOW: 'true' SESSION_SECRET: environment: - RACK_ENV=development - SHOW=true - SESSION_SECRET
這個標籤進和Dockerfile中EXPOSE指令同樣,用於指定暴露的端口,
可是隻是做爲一種參考,實際上docker-compose.yml的端口映射還得ports這樣的標籤。
expose: - "3000" - "8000"
在使用Docker過程當中,咱們會有許多單獨使用docker run啓動的容器,
爲了使Compose可以鏈接這些不在docker-compose.yml中定義的容器,
咱們須要一個特殊的標籤,也就是external_links,它可讓Compose項目裏面的容器鏈接到那些項目配置外部的容器。
前提是外部容器中必須至少有一個容器是鏈接到項目內的服務的同一個網絡裏面。
external_links: - redis_1 - project_db_1:mysql - project_db_1:postgresql
添加主機名的標籤,就是往/etc/hosts文件中添加一些記錄,與Docker client的--add-host相似:
extra_hosts: - "somehost:162.242.195.82" - "otherhost:50.31.209.229"
啓動以後查看容器內部hosts:
162.242.195.82 somehost 50.31.209.229 otherhost
向容器添加元數據,和Dockerfile的LABEL指令一個意思,格式以下:
labels: com.example.description: "Accounting webapp" com.example.department: "Finance" com.example.label-with-empty-value: "" labels: - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.label-with-empty-value"
前面講過depends_on,那個標籤解決啓動順序問題,這個標籤解決的是容器的鏈接問題。
與Docker client的--link同樣效果,會鏈接到其它服務中的容器。
格式以下:
links: - db - db:database - redis
使用的別名將會自動在服務容器中的/etc/hosts裏建立。例如:
172.12.2.186 db 172.12.2.186 database 172.12.2.187 redis
相應的環境變量也將被建立。
這個標籤用於配置日誌服務。格式以下:
logging: driver: syslog options: syslog-address: "tcp://192.168.0.42:123"
默認的driver是json-file。只有json-file和journald能夠經過docker-compose logs顯示日誌。
其它方式有其它的查看方式,但目前Compose還不支持。對於可選值可使用options指定。
詳細信息:https://docs.docker.com/engine/admin/logging/overview/
將PID模式設置爲主機PID模式,跟主機系統共享進程命名空間。
容器使用這個標籤將可以訪問和操做其它容器和宿主機的名稱空間。
pid: "host"
映射端口的標籤。
使用HOST.CONTAINER格式或者指定容器的端口,宿主機會隨機映射端口。
ports: - "3000" - "8000:8000" - "49100:22" - "127.0.0.1:8001:8001"
注意:當使用HOST>CONTAINER格式來映射端口時,若是你使用的容器端口小於60可能會獲得錯誤的結果。
由於YAML將會解析xxyy這種數字格式爲60進制。因此建議採用字符串格式。
爲一個容器覆蓋默認的標籤。簡單說來就是管理所有服務的標籤。
好比設置所有服務的user標籤值爲USER。
security_opt: - label:user:USER - label:role:ROLE
設置一個信號來中止容器。在默認狀況下是使用的是SIGTERM中止容器。
設置另外一個信號可使用stop_signal標籤。
stop_signal: SIGUSR1
掛載一個目錄或者一個已存在的數據卷容器,能夠直接使用[HOST:CONTAINER]這樣的格式,
或者使用[HOST:CONTAINER:ro]這樣的格式,後者對於容器來講,數據卷是隻讀的,這樣能夠有效保護宿主機的文件系統。
Compose的數據卷指定路徑能夠是相對路徑,使用.或者..來指定相對路徑。
數據卷的格式能夠是下面多種形式:
volumes: // 只是指定一個路徑,Docker 會自動在建立一個數據卷(這個路徑是容器內部的)。 - /var/lib/mysql // 使用絕對路徑掛載數據卷 - /opt/data:/var/lib/mysql // 以 Compose 配置文件爲中心的相對路徑做爲數據卷掛載到容器。 - ./cache:/tmp/cache // 使用用戶的相對路徑(~/ 表示的目錄是 /home/<用戶目錄>/ 或者 /root/)。 - ~/configs:/etc/configs/:ro // 已經存在的命名的數據卷。 - datavolume:/var/lib/mysql
若是你不使用宿主機的路徑,你能夠指定一個volume_driver.
volume_driver: mydriver
從其餘容器或者服務掛載數據卷,可選參數是:ro或:rw,
前者表示容器只讀,後者表示容器對數據卷是可讀可寫的。默認狀況下是可讀可寫的。
volumes_from: - service_name - service_name:ro - container:container_name - container:container_name:rw
添加或刪除容器的內核功能
cap_add: - ALL 讓容器擁有全部能力 cap_drop: 去掉某些能力 - NET_ADMIN - SYS_ADMIN
指定一個容器的父級cgroup
cgroup_parent: m-executor-abcd
設備映射列表。與Docker client的--device參數相似。
devices: - "/dev/ttyUSB0:/dev/ttyUSB0"
這個標籤能夠擴展另外一個服務,擴展內容能夠是來自當前文件,也能夠是來自其它文件,
相同服務的狀況下,後來者會有選擇的覆蓋原有配置。
extends: file: common.yml service: webapp
用戶能夠在任何地方使用這個標籤,只要標籤內容包含file和service兩個值就能夠了。
file的值能夠是相對或者絕對路徑,若是不指定file的值,那麼Compose會讀取當前YML文件的信息。
注意避免循環依賴。
網絡模式,與Docker client的--net參數相似,只是相對多了一個service:[service name]的格式。
network_mode: "bridge" network_mode: "host" network_mode: "none" network_mode: "service:[service name]" network_mode: "container:[container name/id]"
能夠指定使用服務或者容器的網絡。
加入指定網絡。
services: some-service: networks: - some-network - other-network
關於這個標籤還有一個特別的子標籤aliases,這是一個用來設置服務別名的標籤:
services: some-service: networks: some-network: aliases: - alias1 - alias3 other-network: aliases: - alias2
相同的服務能夠在不一樣的網絡有不一樣的別名。
指定容器的ulimits限制值。
例如,指定最大進程數爲65535,指定文件句柄數爲20000(軟限制,應用能夠隨時修改,不能超過硬限制)和40000(系統硬限制,只能root用戶提升)
ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000
此外,還有包括cpu_shares、cpuset、domainname、hostname、ipc、mac_address、mem_limit、memswap_limit、
privileged、read_only、restart、stdin_open、tty、user、working_dir等指令。
指定使用CPU核0和核1,只用50%的CPU資源:
cpu_shares: 73 cpuset: 0,1
指定容器中運行應用的用戶名:
user: nginx
指定容器中工做目錄:
working_dir: /code
指定容器中搜索域名、主機名、mac地址等:
domainname: your_website.com hostname: test mac_address: 08-00-27-00-0C-0A
指定容器:
ipc: host
指定容器中內存和內存減緩去限制都爲1G:
mem_limit: 1g menswap_limit: 1g
容許容器運行一些特權命令:
privileged: true
指定容器退出後的重啓策略爲始終重啓。該命令對保持服務始終運行十分有效,推薦配置爲always或者unless-stopped
restart: always
以只讀模式掛載容器的root文件系統,意味着不能對容器內容進行修改:
read_only: true
打開標準輸入,能夠接受外部輸入:
stdin_open: true
模擬一個假的遠程控制檯:
tty: true
從1.5.0版本開始,Compose模板文件支持動態讀取主機的系統環境變量。
例如:下面的Compose文件將從運行它的環境中讀取變量${MONGO_VERSION}的值,並將其寫入執行的指令中。
db: images: 「mongo:${MONGO_VERSION}」
dvc: image: centos volumes: - /root/composetest:/usr/share/nginx/html/:ro nginx: image: nginx volumes_from: - dvc ports: - "8081:80"
建立一個web項目:將Haproxy做爲負載均衡器,後端掛載三個web容器。
首相建立一個haproxy_web目錄做爲項目的工做目錄,其中分別建立兩個子目錄:web和haproxy。
[root@centos002 haproxy_web]# ls docker-compose.yml haproxy web [root@centos002 haproxy_web]# tree . . |-- docker-compose.yml |-- haproxy | `-- haproxy.cfg `-- web |-- Dockerfile |-- index.html `-- index.py 2 directories, 5 files
index.py
#!/usr/bin/python import sys import BaseHTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler import socket import fcntl import struct import pickle from datetime import datetime from collections import OrderedDict class HandlerClass(SimpleHTTPRequestHandler): def get_ip_address(self,ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # SIOCGIFADDR struct.pack('256s', ifname[:15]) )[20:24]) def log_message(self, format, *args): if len(args) < 3 or "200" not in args[1]: return try: request = pickle.load(open("pickle_data.txt","r")) except: request=OrderedDict() time_now = datetime.now() ts = time_now.strftime('%Y-%m-%d %H:%M:%S') server = self.get_ip_address('eth0') host=self.address_string() addr_pair = (host,server) if addr_pair not in request: request[addr_pair]=[1,ts] else: num = request[addr_pair][0]+1 del request[addr_pair] request[addr_pair]=[num,ts] file=open("index.html", "w") file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\" face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit Results</h1>"); for pair in request: if pair[0] == host: guest = "LOCAL: "+pair[0] else: guest = pair[0] if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d %H:%M:%S')).seconds < 3: file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"red\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"blue\">"+guest+"</font>> to WebServer <<font color=\"blue\">"+pair[1]+"</font>></p>") else: file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"navy\">"+guest+"</font>> to WebServer <<font color=\"navy\">"+pair[1]+"</font>></p>") file.write("</center></body> </html>"); file.close() pickle.dump(request,open("pickle_data.txt","w")) if __name__ == '__main__': try: ServerClass = BaseHTTPServer.HTTPServer Protocol = "HTTP/1.0" addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1] port = len(sys.argv) < 3 and 80 or int(sys.argv[2]) HandlerClass.protocol_version = Protocol httpd = ServerClass((addr, port), HandlerClass) sa = httpd.socket.getsockname() print "Serving HTTP on", sa[0], "port", sa[1], "..." httpd.serve_forever() except: exit()
關於index.py裏面說的什麼咱們不須要去深究,只須要知道用來響應HTTP的請求,返回結果就好了。
同時它還會像index.html的文件中寫入標籤元素。
index.html
這是一個空的文件,它的內容由index.py動態寫入。
Dockerfile
FROM python:2.7 WORKDIR /code ADD . /code EXPOSE 80 CMD python index.py
咱們知道Dockerfile用來建立一個容器。
這裏會建立一個python2.7的容器,同時還會執行index.py文件
該目錄將配置haproxy鏡像,這裏面的配置實際上是haproxy的配置文件,咱們將會利用這個配置文件來構建咱們想要的鏡像。
global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 defaults log global mode http option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms listen stats bind 0.0.0.0:70 mode http stats enable stats hide-version stats scope . stats realm Haproxy\ Statistics stats uri / stats auth user:pass frontend balancer bind 0.0.0.0:80 mode http default_backend web_backends backend web_backends mode http option forwardfor balance roundrobin server weba weba:80 check server webb webb:80 check server webc webc:80 check option httpchk GET / http-check expect status 200
這個文件Compose使用的主模板文件。
其中會指定啓動3個web容器(weba、webb、webc),以及一個haproxy容器。
#建立三個web服務 weba: build: ./web 指定Dockerfile文件所在的路徑,Compose將會使用這個文件來構建鏡像,而後利用這個鏡像來建立容器 expose: - 80 webb: build: ./web expose: - 80 webc: build: ./web expose: - 80 haproxy: image: haproxy:1.6 拉取鏡像 volumes: 掛載配置文件到指定的位置 - ./haproxy:/haproxy-override - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro links: links標籤解決容器的鏈接問題,它會鏈接到另外的三個容器,以此來達到編排的目的。 - weba - webb - webc ports: - "80:80" 端口映射,可使用docker ps來查看 - "70:70"
啓動:
docker-compose up 會自動查找當前目錄下的docker-compose.yml文件,若是沒有會去上級目錄查找
查看容器信息:
[root@centos002 haproxy_web]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9eac212b5a4d haproxy:1.6 "/docker-entrypoint.…" 44 minutes ago Up 44 minutes 0.0.0.0:70->70/tcp, 0.0.0.0:80->80/tcp haproxy_web_haproxy_1_8843fbe31d1f 696b91016f39 haproxy_web_webc "/bin/sh -c 'python …" 44 minutes ago Up 44 minutes 80/tcp haproxy_web_webc_1_159bfc7f2644 dfcb7f1a0e8e haproxy_web_weba "/bin/sh -c 'python …" 44 minutes ago Up 44 minutes 80/tcp haproxy_web_weba_1_f047051398b2 0508a092fca0 haproxy_web_webb "/bin/sh -c 'python …" 44 minutes ago Up 44 minutes 80/tcp haproxy_web_webb_1_ef0b108c4e3b
咱們能夠看到建立並啓動了四個容器,haproxy完成了兩個端口的映射,web服務默認使用的80端口,expose只是聲明。
查看鏡像:
理論上說會下載python2.7和haproxy1.6的鏡像,同時又會在python鏡像的基礎上建立3個web鏡像。
查看負載均衡的效果:
咱們連續刷新三次:
咱們能夠看到在三個ip以前來回切換,這樣就達到了負載均衡的效果。
再回來看目錄結果:
[root@centos002 haproxy_web]# tree . |-- docker-compose.yml |-- haproxy | `-- haproxy.cfg `-- web |-- Dockerfile |-- index.html `-- index.py 2 directories, 5 files
貌似有好幾個目錄,可是其實核心目錄只有一個就是docker-compose.yml。
咱們稍微改一下,也許就會更加清晰明確。
weba: image:nginx webb: image:nginx webc: image:nginx haproxy: image: haproxy:1.6 volumes: - haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro links: - weba - webb - webc ports: - "80:80" - "70:70"
這樣咱們的目錄結構:
[root@centos002 web_haproxy]# tree . |-- docker-compose.yml `-- haproxy.cfg 這個文件沒有的話,不能實現負載均衡的 0 directories, 2 files
之因此建立web和haproxy這兩個目錄,就是爲了更加的清晰明確。