Docker-Compose

以下內(nèi)容轉(zhuǎn)載于Breeze
原博客地址:https://www.cnblogs.com/breezey/

九、Docker-Compose

1、Docker Compose介紹

Docker Compose是一個(gè)定義和運(yùn)行多容器應(yīng)用的單機(jī)編排工具。通過(guò)Docker Compose你可以使用一個(gè)單一的YAML文件來(lái)配置多個(gè)應(yīng)用服務(wù),通過(guò)一條命令,就可以將所有配置的服務(wù)全部啟動(dòng)起來(lái)。

使用Docker Compose的三個(gè)步驟:

  • 使用Dockerfile定義環(huán)境,這樣可以確保其在任意地方運(yùn)行
  • 使用docker-compose.yml文件定義服務(wù),這樣它們就可以在獨(dú)立環(huán)境中一起運(yùn)行
  • 運(yùn)行docker-compose up使用docker-compose啟動(dòng)所有應(yīng)用

Docker Compose可以管理應(yīng)用的整個(gè)生命周期:

  • 啟動(dòng)、停止、重建服務(wù)
  • 查看服務(wù)的運(yùn)行狀態(tài)
  • 流式輸出服務(wù)日志
  • 對(duì)服務(wù)執(zhí)行一次性命令

2、Docker Compose安裝

二進(jìn)制安裝:

下載地址:https://github.com/docker/compose/releases

pip安裝:

pip install docker-compose

3、Docker Compose基本示例

3.1、基本文件及目錄設(shè)置

  1. 創(chuàng)建一個(gè)目錄:
mkdir composetest
cd composetest
  1. 在上面的目錄中創(chuàng)建一個(gè)app.py文件,內(nèi)容如下:
import time

import redis
from flask import Flask


app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)


def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)


@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
  1. 再創(chuàng)建一個(gè)pip.conf文件,內(nèi)容如下:
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/

[install]
trusted-host=mirrors.aliyun.com

3.2、創(chuàng)建一個(gè)Dockerfile

仍然在composetest目錄中創(chuàng)建一個(gè)Dockerfile,內(nèi)容如下:

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

3.3、通過(guò)docker-compose.yml定義服務(wù)

docker-compose.yml內(nèi)容如下:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

這個(gè)文件定義了兩個(gè)服務(wù):web和redis。

  • web服務(wù)使用當(dāng)前目錄的Dockerfile進(jìn)行構(gòu)建,并且映射web服務(wù)的5000端口到宿主機(jī)5000端口。
  • redis服務(wù)使用一個(gè)公共的redis鏡像。

3.4、通過(guò)Docker Compose構(gòu)建并啟動(dòng)服務(wù)

docker-compose up

這個(gè)時(shí)候可以通過(guò)http://127.0.0.1:5000來(lái)訪問(wèn)這個(gè)web服務(wù)。

3.5、 修改Compse文件,添加一個(gè)掛載點(diǎn)

修改docker-compose.yml,內(nèi)容如下:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"

添加了一個(gè)volumes配置項(xiàng),將當(dāng)前目錄掛載至web容器的/code目錄下。

然后我們通過(guò)docker-compose up重新構(gòu)建應(yīng)用,再次訪問(wèn),會(huì)發(fā)現(xiàn)結(jié)果與上面完全相同。

3.6、 更新應(yīng)用

我們修改本地的app.py,修改Hello World!Hello from Dokcer,如下:

return 'Hello from Docker! I have been seen {} times.\n'.format(count)

這個(gè)時(shí)候再次訪問(wèn)http://127.0.0.1:5000,發(fā)現(xiàn)訪問(wèn)內(nèi)容也隨之修改。

這是因?yàn)樵谏厦嫖覀儗⒈镜啬夸洅燧d進(jìn)了容器,我們修改本地的app.py就相當(dāng)于修改了容器內(nèi)的文件。

4、Docker Compose常用命令說(shuō)明

在上面的一個(gè)簡(jiǎn)單示例中,我們已經(jīng)使用了docker-compose up來(lái)啟動(dòng)一個(gè)docker-compose.yml文件定義的服務(wù)。我們剛剛通過(guò)docker-compose up雖然啟動(dòng)了服務(wù),當(dāng)是docker-compose指令卻在前臺(tái)執(zhí)行,如果需要將其放入后臺(tái)運(yùn)行,可以使用-d參數(shù):

docker-compose up -d

docker-compose up還可以使用--scale參數(shù)實(shí)現(xiàn)服務(wù)的擴(kuò)縮容:

[root@app composetest]# docker-compose up -d --scale web=2
Recreating composetest_web_1 ... 
Recreating composetest_web_1 ... done
Creating composetest_web_2   ... done

還可以通過(guò)-f選項(xiàng)指定compose文件:

[root@app tranning]# docker-compose -f test-compose.yml up -d
Creating network "tranning_default" with the default driver
Creating network "tranning_frontend" with the default driver
Creating network "tranning_backend" with the default driver
Creating tranning_visualizer_1 ... done
Creating tranning_redis_1      ... done
Creating tranning_worker_1     ... done
Creating tranning_db_1         ... done
Creating tranning_result_1     ... done
Creating tranning_vote_1       ... done

需要說(shuō)明的是,如果使用自動(dòng)擴(kuò)容,則web服務(wù)不能做端口映射,否則會(huì)出現(xiàn)端口沖突的情況

下面我們說(shuō)一說(shuō)其他常用的docker-compose命令:

  1. docker-compose ps
[root@app composetest]# docker-compose ps 
       Name                      Command               State           Ports         
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp              
composetest_web_1     python app.py    
  1. docker-compose stop
[root@app composetest]# docker-compose stop
Stopping composetest_redis_1 ... done
Stopping composetest_web_1   ... done

[root@app composetest]# docker-compose stop web
Stopping composetest_web_1 ... done
  1. docker-compose start
[root@app composetest]# docker-compose start
Starting web   ... done
Starting redis ... done

[root@app composetest]# docker-compose start web
Starting web ... done
  1. docker-compose restart
[root@app composetest]# docker-compose restart
Restarting composetest_web_1   ... done
Restarting composetest_redis_1 ... done
  1. docker-compose run [command]
[root@app composetest]# docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=72ad8a0682b7
TERM=xterm
LANG=C.UTF-8
GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D
PYTHON_VERSION=3.4.9
PYTHON_PIP_VERSION=18.0
HOME=/root
  1. docker-compose down
[root@app composetest]# docker-compose down
Stopping composetest_redis_1 ... done
Stopping composetest_web_1   ... done
Removing composetest_redis_1 ... done
Removing composetest_web_1   ... done
Removing network composetest_default

通過(guò)--volumes還要以刪除自動(dòng)掛載的容器卷

  1. docker-compose build

默認(rèn)情況下,我們寫好了Dockerfile,第一次通過(guò)docker-compose啟動(dòng)的時(shí)候,會(huì)自動(dòng)完成構(gòu)建,但如果隨后Dockerfile發(fā)生了改動(dòng),再次通過(guò)docker-compose來(lái)啟動(dòng)實(shí)現(xiàn)更新的話,docker-compose不會(huì)再次自動(dòng)構(gòu)建鏡像,而是復(fù)用第一次生成的鏡像,如果希望鏡像能夠被重新構(gòu)建,需要單獨(dú)執(zhí)行docker-compose build

  1. docker-compose top
[root@app composetest]# docker-compose top
composetest_redis_1
UID    PID    PPID    C   STIME   TTY     TIME         CMD     
---------------------------------------------------------------
100   89653   89634   0   23:26   ?     00:00:00   redis-server

composetest_web_1
UID     PID    PPID    C   STIME   TTY     TIME                 CMD             
--------------------------------------------------------------------------------
root   89635   89619   0   23:26   ?     00:00:00   python app.py               
root   89742   89635   0   23:26   ?     00:00:00   /usr/local/bin/python app.py
  1. 其它
docker-compose rm       # 通過(guò)這種方式也能刪除指定服務(wù),但不會(huì)刪除網(wǎng)絡(luò)和volumes
docker-compose kill     # 強(qiáng)制殺死一個(gè)服務(wù)
docker-compose logs     # 用于查看日志

5、Docker Compose文件詳解

通過(guò)之前的示例,其實(shí)我們可以看到,所有服務(wù)的管理,都是依靠docker-compose.yml文件來(lái)實(shí)現(xiàn)的。那么我們接下來(lái)就詳細(xì)說(shuō)一說(shuō)docker-compose.yml文件中的常用指令。

compose文件使用yml格式,docker規(guī)定了一些指令,使用它們可以去設(shè)置對(duì)應(yīng)的東西,主要分為了四個(gè)區(qū)域:

  • version:用于指定當(dāng)前docker-compose.yml語(yǔ)法遵循哪個(gè)版本
  • services:服務(wù),在它下面可以定義應(yīng)用需要的一些服務(wù),每個(gè)服務(wù)都有自己的名字、使用的鏡像、掛載的數(shù)據(jù)卷、所屬的網(wǎng)絡(luò)、依賴哪些其他服務(wù)等等。
  • networks:應(yīng)用的網(wǎng)絡(luò),在它下面可以定義應(yīng)用的名字、使用的網(wǎng)絡(luò)類型等。
  • volumes:數(shù)據(jù)卷,在它下面可以定義數(shù)據(jù)卷,然后掛載到不同的服務(wù)下去使用。

version

用于指定當(dāng)前compose文件語(yǔ)法遵循哪個(gè)版本,下面這張表是不同的Compose文件版本兼容的Docker版本:


docker-compse

services

我們上面所說(shuō)的所有服務(wù)的定義都是定義在services區(qū)域中,接下來(lái),我們學(xué)習(xí)下services下常用的配置項(xiàng)

image

標(biāo)明image的ID,這個(gè)image ID可以是本地也可以是遠(yuǎn)程的,如果本地不存在,compose會(huì)嘗試pull下來(lái)
示例:

image: ubuntu
image: hub.dz11.com/library/tomcat:8

build

該參數(shù)指定Dockerfile文件的路徑,compose會(huì)通過(guò)Dockerfile構(gòu)建并生成鏡像,然后使用該鏡像
示例:

build: /path/to/build/dir

command

重寫默認(rèn)的命令,或者說(shuō)指定啟動(dòng)容器的命令
示例:

command: "/run.sh"

links

鏈接到其他服務(wù)中的容器,可以指定服務(wù)名稱和這個(gè)鏈接的別名,或者只指定服務(wù)名稱
示例:

links:
  - db
  - db:database
  - redis

此時(shí),在容器內(nèi)部,會(huì)在/etc/hosts文件中用別名創(chuàng)建幾個(gè)條目,如下:

172.17.2.100 db
172.17.2.100 database
172.17.2.100 redis

external_links

鏈接到compose外部啟動(dòng)的容器,特別是對(duì)于提供共享和公共服務(wù)的容器。在指定容器名稱和別名時(shí),external_links遵循著和links相同的語(yǔ)義用法
示例:

external_links:
  - redis_1
  - project_db_1: mysql
  - project_db_2: postgresql

ports

暴露端口,指定宿主機(jī)到容器的端口映射,或者只指定容器的端口,則表示映射到主機(jī)上的隨機(jī)端口
注:當(dāng)以 主機(jī):容器 的形式來(lái)映射端口時(shí),如果使容器的端口小于60,那可能會(huì)出現(xiàn)錯(cuò)誤,因?yàn)閅AML會(huì)將 xx:yy這樣格式的數(shù)據(jù)解析為六十進(jìn)制的數(shù)據(jù),基于這個(gè)原因,時(shí)刻記得要將端口映射明確指定為字符串
示例:

ports:  
 - "3000"  
 - "8000:8000"  
 - "49100:22"  
 - "127.0.0.1:8001:8001" 

expose

暴露端口,但不需要建立與宿主機(jī)的映射,只是會(huì)向鏈接的服務(wù)提供
示例:

expose:
  - "3000"
  - "8000"

environment

加入環(huán)境變量,可以使用數(shù)組或者字典,只有一個(gè)key的環(huán)境變量可以在運(yùn)行compose的機(jī)器上找到對(duì)應(yīng)的值
示例:

environment:
  RACK_ENV: development
  SESSION_SECRET:

environment:
  - RACK_ENV: development
  - SESSION_SECRET:

env_file

從一個(gè)文件中引入環(huán)境變量,該文件可以是一個(gè)單獨(dú)的值或者一個(gè)列表,如果同時(shí)定義了environment,則environment中的環(huán)境變量會(huì)重寫這些值
示例:

env_file:
  - env
cat env
RACK_ENV: development

depends_on

定義當(dāng)前服務(wù)啟動(dòng)時(shí),依賴的服務(wù),當(dāng)前服務(wù)會(huì)在依賴的服務(wù)啟動(dòng)后啟動(dòng)

depends_on:
  - redis

deploy

該配置項(xiàng)在version 3里才引入,用于指定服務(wù)部署和運(yùn)行時(shí)相關(guān)的參數(shù)

version: '3'
services:
  redis:
    image: redis:alpine
    deploy:
      replicas: 6
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

下面是deploy中常用參數(shù)的說(shuō)明

replicas

指定副本數(shù):

version: '3'
services:
  worker:
    image: dockersamples/examplevotingapp_worker
    deploy:
      replicas: 6
restart_policy

指定重啟策略:

version: "3"
services:
  redis:
    image: redis:alpine
    deploy:
      restart_policy:
        condition: on-failure   #重啟條件:on-failure, none, any
        delay: 5s   # 等待多長(zhǎng)時(shí)間嘗試重啟
        max_attempts: 3 #嘗試的次數(shù)
        window: 120s    # 在決定重啟是否成功之前等待多長(zhǎng)時(shí)間
update_config

定義更新服務(wù)的方式,常用于滾動(dòng)更新

version: '3.4'
services:
  vote:
    image: dockersamples/examplevotingapp_vote:before
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2  # 一次更新2個(gè)容器
        delay: 10s  # 開(kāi)始下一組更新之前,等待的時(shí)間
        failure_action:pause  # 如果更新失敗,執(zhí)行的動(dòng)作:continue, rollback, pause,默認(rèn)為pause
        max_failure_ratio: 20 # 在更新過(guò)程中容忍的失敗率
        order: stop-first   # 更新時(shí)的操作順序,停止優(yōu)先(stop-first,先停止舊容器,再啟動(dòng)新容器)還是開(kāi)始優(yōu)先(start-first,先啟動(dòng)新容器,再停止舊容器),默認(rèn)為停止優(yōu)先,從version 3.4才引入該配置項(xiàng)
resources

限制服務(wù)資源:

version: '3'
services:
  redis:
    image: redis:alpine
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M

healthcheck

執(zhí)行健康檢查

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]   # 用于健康檢查的指令
  interval: 1m30s   # 間隔時(shí)間
  timeout: 10s  # 超時(shí)時(shí)間
  retries: 3    # 重試次數(shù)
  start_period: 40s # 啟動(dòng)多久后開(kāi)始檢查

network_mode

網(wǎng)絡(luò)類型,可指定容器運(yùn)行的網(wǎng)絡(luò)類型
示例:

network_mode: "bridge"
network_mode: "host"
network_mode: "none"

dns

自定義dns服務(wù)
示例:

dns: 8.8.8

dns:
  - 223.5.5.5
  - 223.6.6.6

networks

網(wǎng)絡(luò)決定了服務(wù)之間以及服務(wù)和外界之間如何去通信,在執(zhí)行docker-compose up的時(shí)候,docker會(huì)默認(rèn)創(chuàng)建一個(gè)默認(rèn)網(wǎng)絡(luò),創(chuàng)建的服務(wù)也會(huì)默認(rèn)的使用這個(gè)默認(rèn)網(wǎng)絡(luò)。服務(wù)和服務(wù)之間,可以使用服務(wù)的名字進(jìn)行通信,也可以自己創(chuàng)建網(wǎng)絡(luò),并將服務(wù)加入到這個(gè)網(wǎng)絡(luò)之中,這樣服務(wù)之間可以相互通信,而外界不能夠與這個(gè)網(wǎng)絡(luò)中的服務(wù)通信,可以保持隔離性。

在networks中定義一個(gè)名為app_net,類型為driver的網(wǎng)絡(luò):

version: '2'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10

networks:
  app_net:
    driver: bridge
    enable_ipv6: true
    ipam:
      driver: default
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.168.238.254

volumes

version: "3.2"
services:
  web:
    image: nginx:alpine
    volumes:
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./static
        target: /opt/app/static

  db:
    image: postgres:latest
    volumes:
      - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
      - "dbdata:/var/lib/postgresql/data"

volumes:
  mydata:
  dbdata:

6、Docker Compose案例實(shí)踐

1、部署一個(gè)web集群

項(xiàng)目說(shuō)明

這是一個(gè)典型的web項(xiàng)目,由一個(gè)haproxy容器加三個(gè)web容器組成。haproxy在前端充當(dāng)負(fù)載均衡器,反向代理到后臺(tái)三個(gè)服務(wù)服務(wù)。

基本目錄結(jié)構(gòu)

首先創(chuàng)建一個(gè)compose-haproxy-web的目錄,然后在目錄里面,創(chuàng)建兩個(gè)子目錄:haproxy和web。

在web目錄里包含三個(gè)文件: Dockerfile、index.py、index.html

在haproxy目錄里包含一個(gè)文件: haproxy.cfg

目錄結(jié)構(gòu)如下:

compose-haproxy-web/
├── docker-compose.yml
├── haproxy
│   └── haproxy.cfg
└── web
    ├── Dockerfile
    ├── index.html
    └── index.py

2 directories, 5 files

web目錄下的index.py提供一個(gè)簡(jiǎn)單的http服務(wù),打印出訪問(wèn)者的ip和實(shí)際的本地IP,內(nèi)容如下:

#!/usr/bin/python
#authors: yeasy.github.com
#date: 2013-07-05
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></center>");
    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 &lt<font color=\"blue\">"+guest+"</font>&gt to WebServer &lt<font color=\"blue\">"+pair[1]+"</font>&gt</p>")
      else:
        file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from &lt<font color=\"navy\">"+guest+"</font>&gt to WebServer &lt<font color=\"navy\">"+pair[1]+"</font>&gt</p>")
    file.write("</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()

web目錄下index.html文件是一個(gè)空文件,在程序啟動(dòng)之后會(huì)用到。

web目錄下Dockerfile內(nèi)容如下:

FROM python:2.7
WORKDIR /code
ADD . /code
EXPOSE 80
CMD python index.py

haproxy目錄下的haproxy.cfg內(nèi)容如下:

global
    log 127.0.0.1 local0
    log 127.0.0.1 local1 notice

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
    stats enable
    stats uri /

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

配置docker-compose

docker-compose.yml內(nèi)容如下:

version: '3'
services:
  weba:
    build: ./web
    expose:
    - 80
  
  webb:
    build: ./web
    expose:
    - 80

  webc:
    build: ./web
    expose:
    - 80

  haproxy:
    image: haproxy:latest
    volumes:
    - ./haproxy:/haproxy-override
    - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    links:
    - weba
    - webb
    - webc
    ports:
    - "80:80"
    - "70:70"
    expose:
    - "80"
    - "70"

啟動(dòng)docker-compose:

docker-compose up -d

通過(guò)驗(yàn)證,我們可以看到服務(wù)正常部署,訪問(wèn)http://127.0.0.1:80也可以完成服務(wù)的正常訪問(wèn)。但是在前面,我們講過(guò),weba和webb以及webc都是由同一個(gè)image創(chuàng)建而來(lái),那么我們是否可以使用deploy配置項(xiàng),直接配置三副本呢?

我們驗(yàn)證一下,修改docker-compose.yml內(nèi)容如下:

version: '3'
services:
  web:
    build: ./web
    expose:
    - 80
    deploy:
      replicas: 3

  haproxy:
    image: haproxy:latest
    volumes:
    - ./haproxy:/haproxy-override
    - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    external_links:
    - compose-haproxy-web_web_1
    - compose-haproxy-web_web_2
    - compose-haproxy-web_web_3
    ports:
    - "80:80"
    - "70:70"
    expose:
    - "80"
    - "70"

執(zhí)行docker-compose up -d:

root@ubuntu:~/trainning/compose-haproxy-web# docker-compose up -d
WARNING: Some services (web) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
compose-haproxy-web_web_1 is up-to-date
compose-haproxy-web_haproxy_1 is up-to-date

上面提示deploy不被支持,然后web也只啟動(dòng)了一個(gè)。這是為什么呢?

因?yàn)閐eploy在使用的時(shí)候,有一些限制,但你的compose文件中出現(xiàn)如下配置項(xiàng)時(shí),deploy就無(wú)法使用:

  • build
  • cgroup_parent
  • container_name
  • devices
  • tmpfs
  • external_links
  • links
  • network_mode
  • restart
  • security_opt
  • stop_signal
  • sysctls
  • userns_mode

2、使用Docker Compose一鍵部署zabbix

version: '3'
services:
  mysql-server:
    hostname: mysql-server
    container_name: mysql-server
    image: mysql:5.7
    network_mode: host
    volumes:
      - /data/mysql5721/data:/var/lib/mysql
    command: --character-set-server=utf8
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: zabbix
      MYSQL_USER: zabbix
      MYSQL_PASSWORD: zabbix

  zabbix-web-nginx-mysql:
    hostname: zabbix-web-nginx-mysql
    container_name: zabbix-web-nginx-mysql
    image: zabbix/zabbix-web-nginx-mysql:alpine-3.4.11
    network_mode: host
    depends_on:
      - mysql-server
      - zabbix-server
    ports:
      - 80:80
    environment:
      DB_SERVER_HOST: 127.0.0.1
      MYSQL_DATABASE: zabbix
      MYSQL_USER: zabbix
      MYSQL_PASSWORD: zabbix
      MYSQL_ROOT_PASSWORD: 123456
      ZBX_SERVER_HOST: 127.0.0.1
      PHP_TZ: Asia/Shanghai

  zabbix-server:
    hostname: zabbix-server-mysql 
    container_name: zabbix-server-mysql 
    image: zabbix/zabbix-server-mysql:alpine-3.4.11
    depends_on:
      - mysql-server
    network_mode: host
    ports:
      - 10051:10051
    environment:
      DB_SERVER_HOST: 127.0.0.1
      MYSQL_DATABASE: zabbix
      MYSQL_USER: zabbix
      MYSQL_PASSWORD: zabbix
      MYSQL_ROOT_PASSWORD: 123456

  zabbix-agent:
    hostname: zabbix-agent
    container_name: zabbix-agent
    image: zabbix/zabbix-agent:alpine-3.4.11
    network_mode: host
    environment:
      ZBX_HOSTNAME: monitor
      ZBX_SERVER_HOST: 127.0.0.1
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,986評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,204評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,964評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,354評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,554評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,918評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,093評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,342評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,755評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,009評(píng)論 1 289
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,839評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,107評(píng)論 2 375