19、Docker Compose

可莉
• 阅读 488

  编排(Orchestration)功能是复杂系统实现灵活可操作性的关键。特别是docker应用场景中,编排意味着用户可以灵活地对各种容器资源实现定义和管理。

  在我们部署多容器的应用时:

  • 要从Dockerfile build image或者从dockerhub拉取image
  • 要创建多个container
  • 要管理这些container(启动、停止、删除)

  为了方便我们部署和管理多容器的应用,docker compose就出现了。

19、Docker Compose

19.1 什么是docker compose

  docker compose项目是docker官方的开源项目,负责实现对docker容器集群的快速编排。其代码在GitHub上开源https://github.com/docker/compose

  • Docker Compose是一个工具
  • 这个工具可以通过一个yml文件定义多容器的docker应用
  • 通过一条命令就可以根据yml文件的定义去创建或者管理这多个容器

  Compose定位是“定义和运行多个docker容器的应用”。它允许用户通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project)。

Compose中有三个重要的概念:

  • 服务(services)

  一个service代表一个container,这个container可以从dockerhub的image创建,或者从本地的Dockerfile build出来的image来创建。

  service的启动类似docker run,我们可以给其指定network和volume,所以可以给service指定network和volume的引用。

  • 网络(networks)
  • 数据卷(volumes)

举例

  • service举例

    services: db: image: postgres:9.4 volumes: - "db-data:/var/lib/postgresql/data" network: - back-tier

  这个例子类似于运行了下面这条命令:

docker run -d --network back-tier -v db-data:/var/lib/postgresql/data postgres:9.4


services:
  worker:
    build: ./worker    # 指定了Dockerfile的路径
    links:
      - db
      - redis

    networks:
      - back-tier

  安装WordPress的一个docker compose文件:

version: '3'  # 指定docker compose的版本

services:

  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-bridge

  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-bridge

volumes:
  mysql-data:

networks:
  my-bridge:
    driver: bridge

19.2 docker-compose安装

  docker compose 官方安装文档

curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

19.3 docker-compose命令说明

1. -f, --file           指定使用的Compose模板文件,默认为当前目录下的docker-compose.yml文件。
2. -p, --project-name   指定项目名称,默认将使用当前所在目录名称作为项目名。
3. --verbose            打印更多的日志输出
4. --log-level          设置日志级别,(DEBUG, INFO, WARNING, ERROR, CRITICAL)
5. -v, --version        打印版本并退出
6. -H, --host           指定连接到的守护进程
7. build                构建(重新构建)项目中的服务容器
8. logs                 查看服务容器的输出
9. kill                 强制停止服务容器
10. pause               暂停一个服务容器
11. port                打印某个容器端口所映射的公共端口
12. ps                  列出项目中目前的所有容器
13. pull                拉取服务依赖的镜像
14. restart             重启项目中的服务
15. rm                  删除所有(停止状态的)服务容器
16. run                 在指定服务上执行一个命令
17. exec                在指定服务上执行一个命令
17. scale               设置指定服务运行的容器个数
18. start               启动已经存在的服务容器
19. stop                停止已经处于运行状态的容器,但是不能删除
20. unpause             恢复处于暂停状态的服务
21. up                  自动完成包括构建镜像、创建服务、创建指定网络、启动服务并关联服务相关容器的一系列操作
22. migrate-to-labels   创建容器,并添加lable
23. version             打印版本信息
24. down                停止正在运行的容器并删除容器和网络

19.4 通过docker-compose scale实现负载均衡

  通过haproxy实现flask调用redis的负载均衡

  docker-compose.yml:

version: "3"

services:
  redis:
    image: redis
  web:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      REDIS_HOST: redis
  lb:
    image: dockercloud/haproxy
    links:
      - web
    ports:
      - 8080:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  Dockerfile:

FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 80
CMD [ "python", "app.py" ][

  app.py:

from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80, debug=True)

  首先通过docker-compose up -d启动:

[root@docker lb-scale]# docker-compose up -d
Creating network "lb-scale_default" with the default driver
Creating lb-scale_redis_1 ... done
Creating lb-scale_web_1   ... done
Creating lb-scale_lb_1    ... done
[root@docker lb-scale]# 

  通过docker-compose ps查看:

[root@docker lb-scale]# docker-compose ps
      Name                    Command               State                    Ports
---------------------------------------------------------------------------------------------------
lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
lb-scale_web_1     python app.py                    Up      80/tcp
[root@docker lb-scale]# \

  通过 curl 127.0.0.1:8080

[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 1 times and my hostname is 857fdbc456fb.
[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 2 times and my hostname is 857fdbc456fb.
[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 3 times and my hostname is 857fdbc456fb.
[root@docker lb-scale]# 

  通过scale创建多个web服务的容器数,并且通过haproxy是爱你负载均衡:

[root@docker lb-scale]# docker-compose up --scale web=3 -d
lb-scale_redis_1 is up-to-date
Starting lb-scale_web_1 ... done
Creating lb-scale_web_2 ... done
Creating lb-scale_web_3 ... done
lb-scale_lb_1 is up-to-date
[root@docker lb-scale]# 

  再次通过 curl 127.0.0.1:8080

[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 4 times and my hostname is 857fdbc456fb.
[root@docker lb-scale]#curl 127.0.0.1:8080
Hello Container World! I have been seen 5 times and my hostname is 43f2925c52d1.
[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 6 times and my hostname is 354a407ee7b1.
[root@docker lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 7 times and my hostname is 857fdbc456fb.
[root@docker lb-scale]#curl 127.0.0.1:8080
Hello Container World! I have been seen 8 times and my hostname is 43f2925c52d1.
[root@docker lb-scale]#curl 127.0.0.1:8080
Hello Container World! I have been seen 9 times and my hostname is 354a407ee7b1.
[root@docker lb-scale]#

  继续增加WEB容器的数量,并访问:

[root@docker lb-scale]# docker-compose up --scale web=10 -d
lb-scale_redis_1 is up-to-date
Starting lb-scale_web_1 ... done
Starting lb-scale_web_2 ... done
Starting lb-scale_web_3 ... done
Creating lb-scale_web_4  ... done
Creating lb-scale_web_5  ... done
Creating lb-scale_web_6  ... done
Creating lb-scale_web_7  ... done
Creating lb-scale_web_8  ... done
Creating lb-scale_web_9  ... done
Creating lb-scale_web_10 ... done
lb-scale_lb_1 is up-to-date
[root@docker lb-scale]#for i in `seq 10`;do curl 127.0.0.1:8080;done
Hello Container World! I have been seen 10 times and my hostname is 857fdbc456fb.
Hello Container World! I have been seen 11 times and my hostname is a529d9001556.
Hello Container World! I have been seen 12 times and my hostname is 43f2925c52d1.
Hello Container World! I have been seen 13 times and my hostname is 354a407ee7b1.
Hello Container World! I have been seen 14 times and my hostname is 25698b41ea54.
Hello Container World! I have been seen 15 times and my hostname is 4114fe5258fa.
Hello Container World! I have been seen 16 times and my hostname is 749e6918a6c5.
Hello Container World! I have been seen 17 times and my hostname is 7792a42d1219.
Hello Container World! I have been seen 18 times and my hostname is c91ab986a554.
Hello Container World! I have been seen 19 times and my hostname is 01fc4550b204.
[root@docker lb-scale]#

  可以看出,通过docker-compose的scale可以快速的实现某个服务容器数量的增加,在访问量突增的情况下可以轻松应对,减轻服务器压力。

当访问量恢复正常的时候也可以5个docker-compose up --scale来减少容器的数量:

[root@docker lb-scale]# docker-compose up --scale web=5 -d
lb-scale_redis_1 is up-to-date
Stopping and removing lb-scale_web_6  ... done
Stopping and removing lb-scale_web_7  ... done
Stopping and removing lb-scale_web_8  ... done
Stopping and removing lb-scale_web_9  ... done
Stopping and removing lb-scale_web_10 ... done
Starting lb-scale_web_1               ... done
Starting lb-scale_web_2               ... done
Starting lb-scale_web_3               ... done
Starting lb-scale_web_4               ... done
Starting lb-scale_web_5               ... done
lb-scale_lb_1 is up-to-date
[root@docker lb-scale]# docker-compose ps
      Name                    Command               State                    Ports
---------------------------------------------------------------------------------------------------
lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
lb-scale_web_1     python app.py                    Up      80/tcp
lb-scale_web_2     python app.py                    Up      80/tcp
lb-scale_web_3     python app.py                    Up      80/tcp
lb-scale_web_4     python app.py                    Up      80/tcp
lb-scale_web_5     python app.py                    Up      80/tcp
[root@docker lb-scale]# 

  上述只是实现了单机的容器编排,毕竟单台服务器的资源是有限的,容器数量过多会导致单台服务器资源使用率不够用,但是,如果可以在多机服务器上编排容器数量,那么服务器的性能将会得到更好的利用,能够承受的并发将会呈指数上升。

  在docker-compose 3.0之前,docker-compose只支持单机的容器编排,到3.0的时候,docker-compose已经可以支持多机的容器编排了,也就是说利用3.0及以上的docker-compose可以实现多服务器上的容器编排。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这