目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Docker Compose多容器部署

多容器的 APP 的痛点

  • 要从 Dockerfile build image 或者 Dockerhub 拉取 iage
  • 要创建多个 container
  • 要管理这些 container(启动停止删除)
  • 一个应用可能由多个容器之间相互配合完成,追个容器进行管理成本高,将多个容器定义为一个组,对组进行统一的管理。
  • 微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。

Docker Compose 简介

Docker Compose 批处理
 使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具。

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

yml 概念

yml 概念

Services

  • 一个 service 代表一个 container,这个 container 可以从 dockerhub 的 image 创建而来,或是从本地的 Dockerfile build 构建的 image 创建而来。
  • Service 的启动类似 docker run,我们可以给其指定 network 和 volume,所以可以给 service 指定 network 和 Volume 的引用。

docker-compose.yml

 1version: '3'
 2
 3services:
 4
 5  wordpress:
 6    image: wordpress
 7    ports:
 8      - 8080:80
 9    environment:
10      WORDPRESS_DB_HOST: mysql
11      WORDPRESS_DB_PASSWORD: root
12    networks:
13      - my-bridge
14
15  mysql:
16    image: mysql
17    environment:
18      MYSQL_ROOT_PASSWORD: root
19      MYSQL_DATABASE: wordpress
20    volumes:
21      - mysql-data:/var/lib/mysql
22    networks:
23      - my-bridge
24
25volumes:
26  mysql-data:
27
28networks:
29  my-bridge:
30    driver: bridge

docker compose

Linux 下需要单独安装 docker compose,windows 和 mac 不需要。

1curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-`uname -s `-`uname -m` > /usr/local/bin/docker-compose
2chmod +x /usr/local/bin/docker-compose

常用命令

 1[root@localhost docker-compose]# pwd
 2/docker/docker-compose
 3[root@localhost docker-compose]# ls /docker/docker-compose/
 4docker-compose.yml
 5[root@localhost docker-compose]# docker-compose -f docker-compose.yml up
 6# 也可以缺省为:启动当前目录下docker-compose文件中定义的容器
 7[root@localhost docker-compose]# docker-compose up
 8# 后台执行:平时用的比较多
 9[root@localhost docker-compose]# docker-compose up -d 
10
11# 查看当前目录下docker-compose文件中定义的容器运行状态
12[root@localhost docker-compose]# docker-compose ps
13
14# 停止容器组
15[root@localhost docker-compose]# docker-compose stop
16
17# 停止容器组,并删除容器、networks、volumes
18[root@localhost docker-compose]# docker-compose down
19
20# 列举出docker-compose.yml中所定义的container及它使用的image
21[root@localhost docker-compose]# docker-compose images
22
23# 进入容器后面跟着docker-compose.yml中定义的service
24[root@localhost docker-compose]# docker-compose exec mysql bash
25[root@localhost docker-compose]# docker-compose exec wordpress bash

docker-compose 快速上手

编写一个最简单的 docker-compose.yml

1version: '3'
2services:
3  redis:
4    image: mycentos:redis

compose 相关操作
 操作 docker-compose 一定要在配置文件 docker-compose.yml 文件路径下操作。

 1# 后台启动容器
 2[root@master docker-compose]# docker-compose up -d
 3Creating network "docker-compose_default" with the default driver
 4Creating docker-compose_redis_1 ... done
 5[root@master docker-compose]# docker ps | grep redis
 6ed82c76ba738        mycentos:redis         "/bin/sh -c '/usr/lo…"   24 seconds ago      Up 23 seconds                                           docker-compose_redis_1
 7
 8# 查看容器
 9[root@master docker-compose]# docker-compose ps
10         Name                       Command               State   Ports
11-----------------------------------------------------------------------
12docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Up  
13
14# 进入容器
15[root@master docker-compose]# docker-compose exec redis bash
16[root@ed82c76ba738 /]# 
17
18# 停止容器
19[root@master docker-compose]# docker-compose stop
20Stopping docker-compose_redis_1 ... done
21[root@master docker-compose]# docker-compose ps
22         Name                       Command               State    Ports
23------------------------------------------------------------------------
24docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Exit 0   
25
26# 启动容器
27[root@master docker-compose]# docker-compose start
28Starting redis ... done
29[root@master docker-compose]# docker-compose ps
30         Name                       Command               State   Ports
31-----------------------------------------------------------------------
32docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Up   
33
34# 删除容器
35[root@master docker-compose]# docker-compose down
36Stopping docker-compose_redis_1 ... done
37Removing docker-compose_redis_1 ... done
38Removing network docker-compose_default
39
40# 删除容器并且删除volumes
41[root@master docker-compose]# docker-compose down --volumes

docker-compose 参考案例

 docker-compose.yml 分为三大部分:version、services、networks。通过编写 docker-compose.yml 文件可以设置网络模式、端口映射、文件共享、同时管理多个容器。
docker-compose.yml

 1version: '3'
 2services:
 3  nginx:
 4    image: mycentos:nginx
 5    network_mode: "host"
 6    volumes:
 7    - /docker/nginx/html:/usr/local/nginx/html
 8    - /docker/nginx/logs:/usr/local/nginx/logs
 9    command: /usr/local/nginx/sbin/nginx -g "daemon off;"
10  redis:
11    image: mycentos:redis
12    ports:
13    - "6380:6379"

启动

1[root@master docker-compose]# docker-compose up -d
2Creating network "docker-compose_default" with the default driver
3Creating docker-compose_nginx_1 ... done
4Creating docker-compose_redis_1 ... done

docker-compose 搭建个人博客 wordpress

docker-compose.yml

 1version: '3.3'
 2services:
 3   db:
 4     image: mysql:5.7
 5     volumes:
 6       - db_data:/var/lib/mysql  # 采用的是卷标的形式挂载(注意:- db_data是参数,可以变,自 定义,必须与下面对应)
 7     restart: always  # 自动重启,保证服务在线
 8     environment:
 9       MYSQL_ROOT_PASSWORD: somewordpress # 数据库远程连接的密码
10       MYSQL_DATABASE: wordpress  # 数据库名称
11       MYSQL_USER: wordpress	# 用户名称
12       MYSQL_PASSWORD: wordpress	# 用户密码
13
14   wordpress:
15     depends_on:	#只有容器db(mysql)成功启动之后,才可以运行wordpress容器,并且等同于 --link 的功能
16       - db
17     image: wordpress:latest
18     ports:
19       - "8000:80"
20     restart: always
21     environment:
22       WORDPRESS_DB_HOST: db:3306
23       WORDPRESS_DB_USER: wordpress
24       WORDPRESS_DB_PASSWORD: wordpress
25       WORDPRESS_DB_NAME: wordpress
26volumes:
27    db_data: {}

如何查看容器自定义的 volumes

1# 查看所有卷
2[root@master docker-compose]# docker volume ls
3
4# 查看具体卷的信息
5[root@master docker-compose]# docker volume inspect wordpress_db_data  | grep "Mountpoint"
6此宿主机路径挂载至容器内/var/lib/mysql

使用 docker compose 构建 flask app

访问:http://192.168.31.220:8080

 1# Dockerfile 
 2[root@localhost flask-redis]# cat Dockerfile 
 3FROM python:2.7
 4LABEL maintaner="xxx"
 5COPY . /app
 6WORKDIR /app
 7RUN pip install flask redis
 8 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
 9EXPOSE 5000
10
11# docker-compose.yml 
12[root@localhost flask-redis]# cat docker-compose.yml 
13version: "3"
14services:
15
16  redis:
17    image: redis
18
19  web:
20    build:
21      context: .
22      dockerfile: Dockerfile
23    ports:
24      - 8080:5000
25    environment:
26      REDIS_HOST: redis
27
28# app.py 
29[root@localhost flask-redis]# cat app.py 
30from flask import Flask
31from redis import Redis
32import os
33import socket
34
35app = Flask(__name__)
36redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
37
38@app.route('/')
39def hello():
40    redis.incr('hits')
41    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
42
43if __name__ == "__main__":
44    app.run(host="0.0.0.0", port=5000, debug=True)
45
46# 启动容器组
47[root@localhost flask-redis]# docker-compose  up

水平扩展和负载均衡之 Scale

Scale
 假设启动 3 个 web(servbice)作为负载均衡

  • scale 只能在单机对容器进行扩容/缩容,如果单机的资源有上限,需要将同一个容器扩容并运行在不同的 Docker 节点上,需要使用 swarm。
  1[root@localhost lb-scale]# pwd
  2/docker/docker-compose/lb-scale
  3
  4# docker-compose.yml 
  5[root@localhost lb-scale]# cat docker-compose.yml 
  6version: "3"
  7
  8services:
  9
 10  redis:
 11    image: redis
 12
 13  web:
 14    build:
 15      context: .
 16      dockerfile: Dockerfile
 17    environment:
 18      REDIS_HOST: redis
 19
 20  lb:
 21    image: dockercloud/haproxy
 22    links:
 23      - web
 24    ports:
 25      - 8080:80
 26    volumes:
 27      - /var/run/docker.sock:/var/run/docker.sock 
 28
 29# Dockerfile 
 30[root@localhost lb-scale]# cat Dockerfile 
 31FROM python:2.7
 32LABEL maintaner="xxx"
 33COPY . /app
 34WORKDIR /app
 35RUN pip install flask redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
 36EXPOSE 80
 37
 38# app.py 
 39[root@localhost lb-scale]# cat app.py 
 40from flask import Flask
 41from redis import Redis
 42import os
 43import socket
 44
 45app = Flask(__name__)
 46redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
 47
 48@app.route('/')
 49def hello():
 50    redis.incr('hits')
 51    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
 52
 53if __name__ == "__main__":
 54    app.run(host="0.0.0.0", port=80, debug=True)
 55
 56# 启动容器组
 57[root@localhost lb-scale]# docker-compose up
 58
 59# 查看容器组中各容器状态
 60[root@localhost lb-scale]# docker-compose ps
 61      Name                    Command               State                    Ports                 
 62--------------------------------------------------------------------------------------
 63lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
 64lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                               
 65lb-scale_web_1     python app.py                    Up      80/tcp   
 66
 67# 访问发现此时 hostname是 9b57020bdd3c.
 68  是web的hostname
 69[root@localhost lb-scale]# curl 127.0.0.1:8080
 70Hello Container World! I have been seen 9 times and my hostname is 9b57020bdd3c.
 71
 72# 验证hostname
 73[root@localhost lb-scale]# docker ps
 74CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                     NAMES
 750cae2375e720        dockercloud/haproxy   "/sbin/tini -- docke…"   3 minutes ago       Up 3 minutes        443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp   lb-scale_lb_1
 76f64a9093ba45        redis                 "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        6379/tcp                                  lb-scale_redis_1
 779b57020bdd3c        lb-scale_web          "python app.py"          3 minutes ago       Up 3 minutes        80/tcp                                    lb-scale_web_1
 78
 79# 使用scale做水平扩展:web 容器的数量。
 80[root@localhost lb-scale]# docker-compose up --scale web=5 -d 
 81Starting lb-scale_web_1 ... done
 82lb-scale_redis_1 is up-to-date
 83Creating lb-scale_web_2 ... done
 84Creating lb-scale_web_3 ... done
 85Creating lb-scale_web_4 ... done
 86Creating lb-scale_web_5 ... done
 87lb-scale_lb_1 is up-to-date
 88
 89# 验证
 90[root@localhost lb-scale]# docker-compose ps
 91      Name                    Command               State                    Ports                 
 92--------------------------------------------------------------------------------------
 93lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
 94lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                               
 95lb-scale_web_1     python app.py                    Up      80/tcp                                 
 96lb-scale_web_2     python app.py                    Up      80/tcp                                 
 97lb-scale_web_3     python app.py                    Up      80/tcp                                 
 98lb-scale_web_4     python app.py                    Up      80/tcp                                 
 99lb-scale_web_5     python app.py                    Up      80/tcp  
100
101[root@localhost lb-scale]# docker ps
102CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS                                     NAMES
1032d3206abc32e        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_3
10408114069ebb6        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_2
1052ad3c66ab1e3        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_5
1063edd57819130        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_4
1070cae2375e720        dockercloud/haproxy   "/sbin/tini -- docke…"   9 minutes ago        Up 9 minutes        443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp   lb-scale_lb_1
108f64a9093ba45        redis                 "docker-entrypoint.s…"   9 minutes ago        Up 9 minutes        6379/tcp                                  lb-scale_redis_1
1099b57020bdd3c        lb-scale_web          "python app.py"          9 minutes ago        Up 9 minutes        80/tcp                                    lb-scale_web_1
110
111# 再次访问,发现第六次6次访问的hostname和第一次的一致,可判断Haproxy访问web的方式为轮询。
112[root@localhost lb-scale]# curl 127.0.0.1:8080
113Hello Container World! I have been seen 10 times and my hostname is 9b57020bdd3c.
114[root@localhost lb-scale]# curl 127.0.0.1:8080
115Hello Container World! I have been seen 11 times and my hostname is 08114069ebb6.
116[root@localhost lb-scale]# curl 127.0.0.1:8080
117Hello Container World! I have been seen 12 times and my hostname is 2d3206abc32e.
118[root@localhost lb-scale]# curl 127.0.0.1:8080
119Hello Container World! I have been seen 13 times and my hostname is 3edd57819130.
120[root@localhost lb-scale]# curl 127.0.0.1:8080
121Hello Container World! I have been seen 14 times and my hostname is 2ad3c66ab1e3.
122[root@localhost lb-scale]# curl 127.0.0.1:8080
123Hello Container World! I have been seen 15 times and my hostname is 9b57020bdd3c.
124
125# 服务缩容(修改容器名称后面的数量即可)
126[root@localhost lb-scale]# docker-compose up --scale web=3 -d 

docker compose 部署投票系统

投票系统架构图

  • Voting App 采用 python,接收前端用户投票输入操作,并写入 Redis。
  • Java worker 采用 Java,读取 Redis 中数据写入数据库。
  • Result App 采用 Node.js,实时从数据库中拉取数据展示给前端用户。

投票系统源码


作者:Soulboy